Skip to content

Commit

Permalink
feat: add index file renderer, and update sample imports to reference
Browse files Browse the repository at this point in the history
  • Loading branch information
alharris-at committed Nov 15, 2021
1 parent 78209e2 commit 361bed2
Show file tree
Hide file tree
Showing 10 changed files with 247 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { User } from \\"../models\\";"

exports[`ImportCollection buildImportStatements no imports 1`] = `"import React from \\"react\\";"`;

exports[`ImportCollection buildSampleSnippetImports 1`] = `"import MyButton from \\"./ui-components/MyButton\\";"`;
exports[`ImportCollection buildSampleSnippetImports 1`] = `"import { MyButton } from \\"./ui-components\\";"`;

exports[`ImportCollection mergeCollections 1`] = `
"import React from \\"react\\";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Object {
"compText": "export const App = () => {
return (<MyText />);
};",
"importsText": "import MyText from \\"./ui-components/MyText\\";
"importsText": "import { MyText } from \\"./ui-components\\";
",
}
`;
Expand All @@ -15,7 +15,7 @@ Object {
"compText": "export const App = () => {
return (<unknown_component_name />);
};",
"importsText": "import unknown_component_name from \\"./ui-components/unknown_component_name\\";
"importsText": "import { unknown_component_name } from \\"./ui-components\\";
",
}
`;
9 changes: 7 additions & 2 deletions packages/studio-ui-codegen-react/lib/import-collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,13 @@ export class ImportCollection {
factory.createImportDeclaration(
undefined,
undefined,
factory.createImportClause(factory.createIdentifier(topComponentName), undefined),
factory.createStringLiteral(`./ui-components/${topComponentName}`),
factory.createImportClause(
undefined,
factory.createNamedImports([
factory.createImportSpecifier(undefined, factory.createIdentifier(topComponentName)),
]),
),
factory.createStringLiteral('./ui-components'),
),
];
}
Expand Down
1 change: 1 addition & 0 deletions packages/studio-ui-codegen-react/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ export * from './react-render-config';
export * from './react-output-manager';
export * from './amplify-ui-renderers/amplify-renderer';
export * from './primitive';
export * from './react-index-studio-template-renderer';
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import { EOL } from 'os';
import { EmitHint, ExportDeclaration, factory } from 'typescript';
import { StudioTemplateRenderer, StudioTheme, StudioComponent } from '@amzn/studio-ui-codegen';
import { ReactRenderConfig, scriptKindToFileExtensionNonReact } from './react-render-config';
import { ImportCollection } from './import-collection';
import { ReactOutputManager } from './react-output-manager';
import {
transpile,
buildPrinter,
defaultRenderConfig,
getDeclarationFilename,
} from './react-studio-template-renderer-helper';
import { RequiredKeys } from './utils/type-utils';

type StudioSchema = StudioComponent | StudioTheme;

export class ReactIndexStudioTemplateRenderer extends StudioTemplateRenderer<
string,
StudioSchema[],
ReactOutputManager,
{
componentText: string;
renderComponentToFilesystem: (outputPath: string) => Promise<void>;
}
> {
protected importCollection = new ImportCollection();

protected renderConfig: RequiredKeys<ReactRenderConfig, keyof typeof defaultRenderConfig>;

fileName: string;

constructor(schemas: StudioSchema[], renderConfig: ReactRenderConfig) {
super(schemas, new ReactOutputManager(), renderConfig);
this.renderConfig = {
...defaultRenderConfig,
...renderConfig,
};
this.fileName = `index.${scriptKindToFileExtensionNonReact(this.renderConfig.script)}`;
}

renderComponentInternal() {
const { printer, file } = buildPrinter(this.fileName, this.renderConfig);

const exportStatements = this.buildExports()
.map((exportStatement) => printer.printNode(EmitHint.Unspecified, exportStatement, file))
.join(EOL);

const { componentText, declaration } = transpile(exportStatements, this.renderConfig);

return {
componentText,
renderComponentToFilesystem: async (outputPath: string) => {
await this.renderComponentToFilesystem(componentText)(this.fileName)(outputPath);
if (declaration) {
await this.renderComponentToFilesystem(declaration)(getDeclarationFilename(this.fileName))(outputPath);
}
},
};
}

/*
* export { default as MyTheme } from './MyTheme';
* export { default as ButtonComponent } from './ButtonComponent';
*/
private buildExports(): ExportDeclaration[] {
return this.component
.filter(({ name }) => name !== undefined)
.map(({ name }) => {
/**
* Type checker isn't detecting that name can't be undefined here
* including this (and return cast) to appease the checker.
*/
if (name === undefined) {
return undefined;
}
return factory.createExportDeclaration(
undefined,
undefined,
false,
factory.createNamedExports([
factory.createExportSpecifier(factory.createIdentifier('default'), factory.createIdentifier(name)),
]),
factory.createStringLiteral(`./${name}`),
);
}) as ExportDeclaration[];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,45 @@
import { useEffect, useState } from 'react';
import { AmplifyProvider } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import ViewTest from './ui-components/ViewTest';
import ViewWithButton from './ui-components/ViewWithButton';
import CustomButton from './ui-components/CustomButton';
import BasicComponentBadge from './ui-components/BasicComponentBadge';
import BasicComponentView from './ui-components/BasicComponentView';
import BasicComponentButton from './ui-components/BasicComponentButton';
import BasicComponentCard from './ui-components/BasicComponentCard';
import BasicComponentCollection from './ui-components/BasicComponentCollection';
import BasicComponentText from './ui-components/BasicComponentText';
import ComponentWithConcatenation from './ui-components/ComponentWithConcatenation';
import ComponentWithConditional from './ui-components/ComponentWithConditional';
import BasicComponentDivider from './ui-components/BasicComponentDivider';
import BasicComponentFlex from './ui-components/BasicComponentFlex';
import BasicComponentImage from './ui-components/BasicComponentImage';
import BasicComponentCustomRating from './ui-components/BasicComponentCustomRating';
import ComponentWithVariant from './ui-components/ComponentWithVariant';
import SimplePropertyBindingDefaultValue from './ui-components/SimplePropertyBindingDefaultValue';
import BoundDefaultValue from './ui-components/BoundDefaultValue';
import SimpleAndBoundDefaultValue from './ui-components/SimpleAndBoundDefaultValue';
import CollectionDefaultValue from './ui-components/CollectionDefaultValue';
import theme from './ui-components/MyTheme';
import ComponentWithSimplePropertyBinding from './ui-components/ComponentWithSimplePropertyBinding';
import ComponentWithDataBindingWithoutPredicate from './ui-components/ComponentWithDataBindingWithoutPredicate';
import ComponentWithDataBindingWithPredicate from './ui-components/ComponentWithDataBindingWithPredicate';
import CollectionWithBinding from './ui-components/CollectionWithBinding';
import CollectionWithSort from './ui-components/CollectionWithSort';
import ParsedFixedValues from './ui-components/ParsedFixedValues';
import CustomChildren from './ui-components/CustomChildren';
import CustomParent from './ui-components/CustomParent';
import CustomParentAndChildren from './ui-components/CustomParentAndChildren';
import { DataStore } from 'aws-amplify';
import { User, Listing } from './models';
import CollectionWithBindingItemsName from './ui-components/CollectionWithBindingItemsName';
import ComponentWithBoundPropertyConditional from './ui-components/ComponentWithBoundPropertyConditional';
import ComponentWithNestedOverrides from './ui-components/ComponentWithNestedOverrides';
import PaginatedCollection from './ui-components/PaginatedCollection';
import ComponentWithAuthBinding from './ui-components/ComponentWithAuthBinding';
import {
ViewTest,
ViewWithButton,
CustomButton,
BasicComponentBadge,
BasicComponentView,
BasicComponentButton,
BasicComponentCard,
BasicComponentCollection,
BasicComponentText,
ComponentWithConcatenation,
ComponentWithConditional,
BasicComponentDivider,
BasicComponentFlex,
BasicComponentImage,
BasicComponentCustomRating,
ComponentWithVariant,
SimplePropertyBindingDefaultValue,
BoundDefaultValue,
SimpleAndBoundDefaultValue,
CollectionDefaultValue,
MyTheme,
ComponentWithSimplePropertyBinding,
ComponentWithDataBindingWithoutPredicate,
ComponentWithDataBindingWithPredicate,
CollectionWithBinding,
CollectionWithSort,
ParsedFixedValues,
CustomChildren,
CustomParent,
CustomParentAndChildren,
CollectionWithBindingItemsName,
ComponentWithBoundPropertyConditional,
ComponentWithNestedOverrides,
PaginatedCollection,
ComponentWithAuthBinding,
} from './ui-components';
/* eslint-enable import/extensions */

const initializeUserTestData = async (): Promise<void> => {
Expand Down Expand Up @@ -137,7 +139,7 @@ export default function ComponentTests() {

return (
/* components prop is required. https://github.com/aws-amplify/amplify-ui/issues/575 */
<AmplifyProvider theme={theme} components={{}}>
<AmplifyProvider theme={MyTheme} components={{}}>
<h1>Generated Component Tests</h1>
<div id={'basic-components'}>
<h2>Basic Components</h2>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,44 @@
import React from 'react';

import { Heading, View } from '@aws-amplify/ui-react';
import AlertPrimitive from './ui-components/AlertPrimitive';
import BadgePrimitive from './ui-components/BadgePrimitive';
import ButtonPrimitive from './ui-components/ButtonPrimitive';
import ButtonGroupPrimitive from './ui-components/ButtonGroupPrimitive';
import CardPrimitive from './ui-components/CardPrimitive';
import CheckboxFieldPrimitive from './ui-components/CheckboxFieldPrimitive';
import CollectionPrimitive from './ui-components/CollectionPrimitive';
import DividerPrimitive from './ui-components/DividerPrimitive';
import FlexPrimitive from './ui-components/FlexPrimitive';
import GridPrimitive from './ui-components/GridPrimitive';
import HeadingPrimitive from './ui-components/HeadingPrimitive';
import IconPrimitive from './ui-components/IconPrimitive';
import ImagePrimitive from './ui-components/ImagePrimitive';
import LabelPrimitive from './ui-components/LabelPrimitive';
import LinkPrimitive from './ui-components/LinkPrimitive';
import LoaderPrimitive from './ui-components/LoaderPrimitive';
import PaginationPrimitive from './ui-components/PaginationPrimitive';
import PasswordFieldPrimitive from './ui-components/PasswordFieldPrimitive';
import PhoneNumberFieldPrimitive from './ui-components/PhoneNumberFieldPrimitive';
import PlaceholderPrimitive from './ui-components/PlaceholderPrimitive';
import RadioPrimitive from './ui-components/RadioPrimitive';
import RadioGroupFieldPrimitive from './ui-components/RadioGroupFieldPrimitive';
import RatingPrimitive from './ui-components/RatingPrimitive';
import ScrollViewPrimitive from './ui-components/ScrollViewPrimitive';
import SearchFieldPrimitive from './ui-components/SearchFieldPrimitive';
import SelectFieldPrimitive from './ui-components/SelectFieldPrimitive';
import SliderFieldPrimitive from './ui-components/SliderFieldPrimitive';
import StepperFieldPrimitive from './ui-components/StepperFieldPrimitive';
import SwitchFieldPrimitive from './ui-components/SwitchFieldPrimitive';
import TabsPrimitive from './ui-components/TabsPrimitive';
import TextPrimitive from './ui-components/TextPrimitive';
import TextFieldPrimitive from './ui-components/TextFieldPrimitive';
import ToggleButtonPrimitive from './ui-components/ToggleButtonPrimitive';
import ToggleButtonGroupPrimitive from './ui-components/ToggleButtonGroupPrimitive';
import ViewPrimitive from './ui-components/ViewPrimitive';
import VisuallyHiddenPrimitive from './ui-components/VisuallyHiddenPrimitive';
import {
AlertPrimitive,
BadgePrimitive,
ButtonPrimitive,
ButtonGroupPrimitive,
CardPrimitive,
CheckboxFieldPrimitive,
CollectionPrimitive,
DividerPrimitive,
FlexPrimitive,
GridPrimitive,
HeadingPrimitive,
IconPrimitive,
ImagePrimitive,
LabelPrimitive,
LinkPrimitive,
LoaderPrimitive,
PaginationPrimitive,
PasswordFieldPrimitive,
PhoneNumberFieldPrimitive,
PlaceholderPrimitive,
RadioPrimitive,
RadioGroupFieldPrimitive,
RatingPrimitive,
ScrollViewPrimitive,
SearchFieldPrimitive,
SelectFieldPrimitive,
SliderFieldPrimitive,
StepperFieldPrimitive,
SwitchFieldPrimitive,
TabsPrimitive,
TextPrimitive,
TextFieldPrimitive,
ToggleButtonPrimitive,
ToggleButtonGroupPrimitive,
ViewPrimitive,
VisuallyHiddenPrimitive,
} from './ui-components';

export default function PrimitivesTests() {
return (
Expand Down
12 changes: 11 additions & 1 deletion packages/test-generator/lib/generators/BrowserTestGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,24 @@

/* Test Generator to be used in the browser environment */
import { StudioComponent, StudioTheme } from '@amzn/studio-ui-codegen';
import { AmplifyRenderer, ReactThemeStudioTemplateRenderer } from '@amzn/studio-ui-codegen-react';
import {
AmplifyRenderer,
ReactThemeStudioTemplateRenderer,
ReactIndexStudioTemplateRenderer,
} from '@amzn/studio-ui-codegen-react';
import { TestGenerator } from './TestGenerator';

export class BrowserTestGenerator extends TestGenerator {
writeComponentToDisk() {} // no-op

writeThemeToDisk() {} // no-op

writeIndexFileToDisk() {} // no-op

renderIndexFile(schemas: (StudioComponent | StudioTheme)[]) {
return new ReactIndexStudioTemplateRenderer(schemas, this.renderConfig).renderComponent();
}

renderComponent(component: StudioComponent) {
return {
renderedComponent: new AmplifyRenderer(component, this.renderConfig).renderComponentOnly(),
Expand Down

0 comments on commit 361bed2

Please sign in to comment.