diff --git a/packages/amplify-gen2-codegen/API.md b/packages/amplify-gen2-codegen/API.md index c6da4e52715..e5e702c982c 100644 --- a/packages/amplify-gen2-codegen/API.md +++ b/packages/amplify-gen2-codegen/API.md @@ -56,7 +56,7 @@ export type AuthLambdaTriggers = Record; export type AuthTriggerEvents = 'createAuthChallenge' | 'customMessage' | 'defineAuthChallenge' | 'postAuthentication' | 'postConfirmation' | 'preAuthentication' | 'preSignUp' | 'preTokenGeneration' | 'userMigration' | 'verifyAuthChallengeResponse'; // @public (undocumented) -export const createGen2Renderer: ({ outputDir, appId, backendEnvironmentName, auth, storage, data, functions, fileWriter, }: Readonly) => Renderer; +export const createGen2Renderer: ({ outputDir, appId, backendEnvironmentName, auth, storage, data, functions, unsupportedCategories, fileWriter, }: Readonly) => Renderer; // @public (undocumented) export type CustomAttribute = { @@ -118,6 +118,8 @@ export interface Gen2RenderingOptions { outputDir: string; // (undocumented) storage?: StorageRenderParameters; + // (undocumented) + unsupportedCategories?: Map; } // @public (undocumented) diff --git a/packages/amplify-gen2-codegen/src/backend/synthesizer.test.ts b/packages/amplify-gen2-codegen/src/backend/synthesizer.test.ts index 135ddf676d6..45fb886bc4d 100644 --- a/packages/amplify-gen2-codegen/src/backend/synthesizer.test.ts +++ b/packages/amplify-gen2-codegen/src/backend/synthesizer.test.ts @@ -136,6 +136,34 @@ describe('BackendRenderer', () => { assert(!output.includes('cfnUserPoolClient')); }); }); + describe('errors for unsupported categories', () => { + it('Renders error statement if unsupported categories are present', () => { + const renderer = new BackendSynthesizer(); + const rendered = renderer.render({ + unsupportedCategories: new Map([ + ['rest api', 'https://docs.amplify.aws/react/build-a-backend/add-aws-services/rest-api/'], + ['geo', 'https://docs.amplify.aws/react/build-a-backend/add-aws-services/geo/'], + ['predictions', 'https://docs.amplify.aws/react/build-a-backend/add-aws-services/predictions/'], + ]), + }); + const output = printNodeArray(rendered); + assert( + output.includes( + 'throw new Error("Category rest api is unsupported, please follow https://docs.amplify.aws/react/build-a-backend/add-aws-services/rest-api/")', + ), + ); + assert( + output.includes( + 'throw new Error("Category geo is unsupported, please follow https://docs.amplify.aws/react/build-a-backend/add-aws-services/geo/")', + ), + ); + assert( + output.includes( + 'throw new Error("Category predictions is unsupported, please follow https://docs.amplify.aws/react/build-a-backend/add-aws-services/predictions/")', + ), + ); + }); + }); describe('imports', () => { for (const resource of ['storage', 'data', 'auth']) { describe(resource, () => { diff --git a/packages/amplify-gen2-codegen/src/backend/synthesizer.ts b/packages/amplify-gen2-codegen/src/backend/synthesizer.ts index 30c546d692d..cc13ed7f7e1 100644 --- a/packages/amplify-gen2-codegen/src/backend/synthesizer.ts +++ b/packages/amplify-gen2-codegen/src/backend/synthesizer.ts @@ -37,6 +37,7 @@ export interface BackendRenderParameters { importFrom: string; functionNamesAndCategories: Map; }; + unsupportedCategories?: Map; } export class BackendSynthesizer { @@ -114,6 +115,7 @@ export class BackendSynthesizer { const backendFunctionIdentifier = factory.createIdentifier('defineBackend'); const imports = []; + const errors: ts.CallExpression[] = []; const defineBackendProperties = []; const nodes = []; @@ -170,6 +172,26 @@ export class BackendSynthesizer { imports.push(this.createImportStatement([backendFunctionIdentifier], '@aws-amplify/backend')); + if (renderArgs.unsupportedCategories) { + const categories = renderArgs.unsupportedCategories; + + for (const [key, value] of categories) { + if (key == 'custom') { + errors.push( + factory.createCallExpression(factory.createIdentifier('throw new Error'), undefined, [ + factory.createStringLiteral(`Category ${key} has changed, learn more ${value}`), + ]), + ); + } else { + errors.push( + factory.createCallExpression(factory.createIdentifier('throw new Error'), undefined, [ + factory.createStringLiteral(`Category ${key} is unsupported, please follow ${value}`), + ]), + ); + } + } + } + const callBackendFn = this.defineBackendCall(backendFunctionIdentifier, defineBackendProperties); const backendVariable = factory.createVariableDeclaration('backend', undefined, undefined, callBackendFn); const backendStatement = factory.createVariableStatement( @@ -323,6 +345,6 @@ export class BackendSynthesizer { ), ); } - return factory.createNodeArray([...imports, backendStatement, ...nodes], true); + return factory.createNodeArray([...imports, ...errors, backendStatement, ...nodes], true); } } diff --git a/packages/amplify-gen2-codegen/src/index.ts b/packages/amplify-gen2-codegen/src/index.ts index 3249b0c4cfb..c8766851c83 100644 --- a/packages/amplify-gen2-codegen/src/index.ts +++ b/packages/amplify-gen2-codegen/src/index.ts @@ -53,6 +53,7 @@ export interface Gen2RenderingOptions { storage?: StorageRenderParameters; data?: DataDefinition; functions?: FunctionDefinition[]; + unsupportedCategories?: Map; fileWriter?: (content: string, path: string) => Promise; } const createFileWriter = (path: string) => async (content: string) => fs.writeFile(path, content); @@ -65,6 +66,7 @@ export const createGen2Renderer = ({ storage, data, functions, + unsupportedCategories, fileWriter = (content, path) => createFileWriter(path)(content), }: Readonly): Renderer => { const ensureOutputDir = new EnsureDirectory(outputDir); @@ -100,6 +102,10 @@ export const createGen2Renderer = ({ const renderers: Renderer[] = [ensureOutputDir, ensureAmplifyDirectory, amplifyPackageJson, amplifyTsConfigJson, jsonRenderer]; + if (unsupportedCategories && unsupportedCategories.size >= 1) { + backendRenderOptions.unsupportedCategories = unsupportedCategories; + } + if (functions && functions.length) { const functionNamesAndCategory = new Map(); for (const func of functions) { diff --git a/packages/amplify-migration/src/index.ts b/packages/amplify-migration/src/index.ts index 530fd8c74b0..c5b9bdc8dc2 100644 --- a/packages/amplify-migration/src/index.ts +++ b/packages/amplify-migration/src/index.ts @@ -63,6 +63,7 @@ const generateGen2Code = async ({ storage: await storageDefinitionFetcher.getDefinition(), data: await dataDefinitionFetcher.getDefinition(), functions: await functionsDefinitionFetcher.getDefinition(), + unsupportedCategories: unsupportedCategories(), }; const pipeline = createGen2Renderer(gen2RenderOptions); @@ -118,6 +119,44 @@ const resolveAppId = (): string => { return meta?.providers?.awscloudformation?.AmplifyAppId; }; +const unsupportedCategories = (): Map => { + const unsupportedCategories = new Map(); + const urlPrefix = 'https://docs.amplify.aws/react/build-a-backend/add-aws-services'; + + unsupportedCategories.set('geo', `${urlPrefix}/geo/`); + unsupportedCategories.set('analytics', `${urlPrefix}/analytics/`); + unsupportedCategories.set('predictions', `${urlPrefix}/predictions/`); + unsupportedCategories.set('notifications', `${urlPrefix}/in-app-messaging/`); + unsupportedCategories.set('interactions', `${urlPrefix}/interactions/`); + unsupportedCategories.set('custom', `${urlPrefix}/custom-resources/`); + unsupportedCategories.set('rest api', `${urlPrefix}/rest-api/`); + + const meta = stateManager.getMeta(); + const categories = Object.keys(meta); + + const unsupportedCategoriesList = new Map(); + + categories.forEach((category) => { + if (category == 'api') { + const apiList = meta?.api; + if (apiList) { + Object.keys(apiList).forEach((api) => { + const apiObj = apiList[api]; + if (apiObj.service == 'API Gateway') { + unsupportedCategoriesList.set('rest api', unsupportedCategories.get('rest api')!); + } + }); + } + } else { + if (unsupportedCategories.has(category)) { + unsupportedCategoriesList.set(category, unsupportedCategories.get(category)!); + } + } + }); + + return unsupportedCategoriesList; +}; + export async function execute() { const amplifyClient = new AmplifyClient(); const s3Client = new S3Client(); @@ -132,6 +171,7 @@ export async function execute() { const amplifyStackParser = new AmplifyStackParser(cloudFormationClient); const backendEnvironmentResolver = new BackendEnvironmentResolver(appId, amplifyClient); const backendEnvironment = await backendEnvironmentResolver.selectBackendEnvironment(); + await generateGen2Code({ outputDirectory: TEMP_GEN_2_OUTPUT_DIR, storageDefinitionFetcher: new AppStorageDefinitionFetcher(backendEnvironmentResolver, new BackendDownloader(s3Client), s3Client),