Skip to content

Commit

Permalink
fix: update imports and props for aliased components (#868)
Browse files Browse the repository at this point in the history
* fix: update imports and props for aliased components

* test: update tests for type declarations and same name validation
  • Loading branch information
rtpascual authored Jan 4, 2023
1 parent ffb68b7 commit 7c5138a
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5454,17 +5454,19 @@ export default function CustomButton(
exports[`amplify render tests custom components alias parent should render declarations 1`] = `
"import * as React from \\"react\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
import { CustomButtonProps } from \\"./CustomButton\\";
import { GridProps } from \\"./Grid\\";
import { ButtonProps } from \\"@aws-amplify/ui-react\\";
import { ViewTestProps } from \\"./ViewTest\\";
export declare type PrimitiveOverrideProps<T> = Partial<T> & React.DOMAttributes<HTMLDivElement>;
export declare type CustomParentAndChildrenOverridesProps = {
CustomParentAndChildren?: ViewTestProps;
MyCustomButton?: CustomButtonProps;
export declare type AliasParentOverridesProps = {
AliasParent?: ViewTestProps;
Grid?: GridProps;
Button?: PrimitiveOverrideProps<ButtonProps>;
} & EscapeHatchProps;
export declare type CustomParentAndChildrenProps = React.PropsWithChildren<Partial<ViewTestProps> & {
overrides?: CustomParentAndChildrenOverridesProps | undefined | null;
export declare type AliasParentProps = React.PropsWithChildren<Partial<ViewTestProps> & {
overrides?: AliasParentOverridesProps | undefined | null;
}>;
export default function CustomParentAndChildren(props: CustomParentAndChildrenProps): React.ReactElement;
export default function AliasParent(props: AliasParentProps): React.ReactElement;
"
`;

Expand All @@ -5475,15 +5477,16 @@ import {
EscapeHatchProps,
getOverrideProps,
} from \\"@aws-amplify/ui-react/internal\\";
import { GridCustom } from \\"./Grid\\";
import { Grid as GridCustom, GridProps } from \\"./Grid\\";
import { Button, ButtonProps } from \\"@aws-amplify/ui-react\\";
import ViewTest, { ViewTestProps } from \\"./ViewTest\\";
import { GridCustomProps } from \\"./GridCustom\\";

export declare type PrimitiveOverrideProps<T> = Partial<T> &
React.DOMAttributes<HTMLDivElement>;
export declare type AliasParentOverridesProps = {
AliasParent?: ViewTestProps;
Grid?: GridCustomProps;
Grid?: GridProps;
Button?: PrimitiveOverrideProps<ButtonProps>;
} & EscapeHatchProps;
export type AliasParentProps = React.PropsWithChildren<
Partial<ViewTestProps> & {
Expand All @@ -5498,6 +5501,7 @@ export default function AliasParent(
/* @ts-ignore: TS2322 */
<ViewTest {...getOverrideProps(overrides, \\"AliasParent\\")} {...rest}>
<GridCustom {...getOverrideProps(overrides, \\"Grid\\")}></GridCustom>
<Button {...getOverrideProps(overrides, \\"Button\\")}></Button>
</ViewTest>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ describe('amplify render tests', () => {

it('should render declarations', () => {
expect(
generateWithAmplifyRenderer('custom/customParentAndChildren', {
generateWithAmplifyRenderer('custom/aliasParent', {
script: ScriptKind.JS,
renderTypeDeclarations: true,
}).declaration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
import { StudioComponentChild } from '@aws-amplify/codegen-ui';
import { JsxChild, JsxElement, factory } from 'typescript';
import { Primitive } from '../primitive';
import { isAliased } from '../helpers';
import { ReactComponentRenderer } from '../react-component-renderer';

export default class CustomComponentRenderer<TPropIn> extends ReactComponentRenderer<TPropIn> {
Expand All @@ -27,8 +27,11 @@ export default class CustomComponentRenderer<TPropIn> extends ReactComponentRend
factory.createJsxClosingElement(factory.createIdentifier(this.component.componentType)),
);

if (Object.keys(Primitive).includes(this.component.name) && this.component.componentType.match(/(Custom$)/g)) {
this.importCollection.addImport(`./${this.component.name}`, this.component.componentType);
if (isAliased(this.component.componentType)) {
this.importCollection.addImport(
`./${this.component.name}`,
`${this.component.name} as ${this.component.componentType}`,
);
} else {
this.importCollection.addImport(`./${this.component.componentType}`, 'default');
}
Expand Down
9 changes: 9 additions & 0 deletions packages/codegen-ui-react/lib/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
import { GenericDataField, GenericDataSchema } from '@aws-amplify/codegen-ui/lib/types';
import { factory, Statement, Expression, NodeFlags, Identifier } from 'typescript';
import { isPrimitive } from '../primitive';

export const lowerCaseFirst = (input: string) => input.charAt(0).toLowerCase() + input.slice(1);

Expand Down Expand Up @@ -104,3 +105,11 @@ export function modelNeedsRelationshipsLoadedForCollection(modelName: string, da
)
);
}

export function isAliased(componentType: string): boolean {
return !!(isPrimitive(removeAlias(componentType)) && componentType.match(/(Custom$)/g));
}

export function removeAlias(aliasString: string): string {
return aliasString.replace(/(Custom$)/g, '');
}
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ import {
buildUseStateExpression,
modelNeedsRelationshipsLoadedForCollection,
fieldNeedsRelationshipLoadedForCollection,
isAliased,
removeAlias,
} from './helpers';

export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer<
Expand Down Expand Up @@ -355,9 +357,10 @@ export abstract class ReactStudioTemplateRenderer extends StudioTemplateRenderer
factory.createTypeLiteralNode(
Object.entries(this.componentMetadata.componentNameToTypeMap).map(([name, componentType]) => {
const isComponentTypePrimitive = isPrimitive(componentType);
const componentTypePropName = `${componentType}Props`;
const componentName = isAliased(componentType) ? removeAlias(componentType) : componentType;
const componentTypePropName = `${componentName}Props`;
this.importCollection.addImport(
isComponentTypePrimitive ? ImportSource.UI_REACT : `./${componentType}`,
isComponentTypePrimitive ? ImportSource.UI_REACT : `./${componentName}`,
componentTypePropName,
);
return factory.createPropertySignature(
Expand Down
5 changes: 5 additions & 0 deletions packages/codegen-ui/example-schemas/custom/aliasParent.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
"name": "Grid",
"componentType": "GridCustom",
"properties": {}
},
{
"name": "Button",
"componentType": "Button",
"properties": {}
}
],
"properties": {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ exports[`validation-helper validateComponentSchema fails on componentType with l

exports[`validation-helper validateComponentSchema fails on componentType with whitespace 1`] = `"Expected an alphanumeric string, starting with a character"`;

exports[`validation-helper validateComponentSchema throws on all components sharing a name 1`] = `"Duplicate names are not allowed within a component, found duplicates of [\\"DeepComp\\",\\"MyComp\\"]"`;
exports[`validation-helper validateComponentSchema throws on child components sharing a name 1`] = `"Duplicate names are not allowed within a component, found duplicates of [\\"ChildComponent\\"]"`;

exports[`validation-helper validateComponentSchema throws on invalid schema version 1`] = `"unsupported schemaVersion 1.1.4"`;

exports[`validation-helper validateComponentSchema throws on parent and child components sharing a name 1`] = `"Duplicate names are not allowed within a component, found duplicates of [\\"MyComp\\"]"`;

exports[`validation-helper validateComponentSchema throws on unsupported schema version 1`] = `"unsupported schemaVersion 1.1"`;

exports[`validation-helper validateComponentSchema top-level component requires componentType 1`] = `"componentType is a required field"`;
Expand Down
27 changes: 25 additions & 2 deletions packages/codegen-ui/lib/__tests__/validation-helper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ describe('validation-helper', () => {
}).toThrowErrorMatchingSnapshot();
});

test('throws on all components sharing a name', () => {
test('throws on parent and child components sharing a name', () => {
expect(() => {
validateComponentSchema({
name: 'MyComp',
Expand All @@ -308,7 +308,7 @@ describe('validation-helper', () => {
properties: {},
children: [
{
name: 'DeepComp',
name: 'DeepCompChild',
componentType: 'Tooltip',
properties: {},
},
Expand All @@ -324,6 +324,29 @@ describe('validation-helper', () => {
}).toThrowErrorMatchingSnapshot();
});

test('throws on child components sharing a name', () => {
expect(() => {
validateComponentSchema({
name: 'MyComp',
componentType: 'Flex',
properties: {},
schemaVersion: '1.0',
children: [
{
name: 'ChildComponent',
componentType: 'Button',
properties: {},
},
{
name: 'ChildComponent',
componentType: 'View',
properties: {},
},
],
});
}).toThrowErrorMatchingSnapshot();
});

test('throws on unsupported schema version', () => {
expect(() => {
validateComponentSchema({
Expand Down

0 comments on commit 7c5138a

Please sign in to comment.