diff --git a/packages/amplify-e2e-core/src/utils/api.ts b/packages/amplify-e2e-core/src/utils/api.ts index f1588fb348e..d47bd1fb943 100644 --- a/packages/amplify-e2e-core/src/utils/api.ts +++ b/packages/amplify-e2e-core/src/utils/api.ts @@ -11,3 +11,8 @@ export function updateConfig(projectDir: string, projectName: string, config: an const configPath = path.join(projectDir, 'amplify', 'backend', 'api', projectName, TRANSFORM_CONFIG_FILE_NAME); fs.writeFileSync(configPath, JSON.stringify(config, null, 4)); } + +export function addCustomResolver(projectDir: string, projectName: string, resolverName: string, resolver: string) { + const resolverPath = path.join(projectDir, 'amplify', 'backend', 'api', projectName, 'resolvers', resolverName); + fs.writeFileSync(resolverPath, resolver); +} diff --git a/packages/amplify-e2e-tests/src/__tests__/resolvers.test.ts b/packages/amplify-e2e-tests/src/__tests__/resolvers.test.ts new file mode 100644 index 00000000000..267a1d42a62 --- /dev/null +++ b/packages/amplify-e2e-tests/src/__tests__/resolvers.test.ts @@ -0,0 +1,43 @@ +import { + initJSProjectWithProfile, + deleteProject, + createNewProjectDir, + deleteProjectDir, + addFeatureFlag, + addApiWithSchema, + addCustomResolver, + apiGqlCompile, +} from 'amplify-e2e-core'; +import { join } from 'path'; +import * as fs from 'fs-extra'; + +describe('overriding generated resolvers', () => { + let projectDir: string; + let apiName = 'simpleapi'; + + beforeAll(async () => { + projectDir = await createNewProjectDir('overrideresolvers'); + await initJSProjectWithProfile(projectDir, {}); + + addFeatureFlag(projectDir, 'graphqltransformer', 'useexperimentalpipelinedtransformer', true); + }); + + afterAll(async () => { + await deleteProject(projectDir); + deleteProjectDir(projectDir); + }); + + it('adds the overwritten resolver to the build', async () => { + const resolverName = 'Query.listTodos.req.vtl'; + const resolver = '$util.unauthorized()'; + const generatedResolverPath = join(projectDir, 'amplify', 'backend', 'api', apiName, 'build', 'pipelineFunctions', resolverName); + + await addApiWithSchema(projectDir, 'simple_model.graphql'); + await apiGqlCompile(projectDir, true); + + addCustomResolver(projectDir, apiName, resolverName, resolver); + await apiGqlCompile(projectDir, true); + + expect(fs.readFileSync(generatedResolverPath)).toEqual(resolver); + }); +}); diff --git a/packages/amplify-provider-awscloudformation/src/__tests__/graphql-transformer/utils.test.ts b/packages/amplify-provider-awscloudformation/src/__tests__/graphql-transformer/utils.test.ts new file mode 100644 index 00000000000..dd6f0e2db62 --- /dev/null +++ b/packages/amplify-provider-awscloudformation/src/__tests__/graphql-transformer/utils.test.ts @@ -0,0 +1,63 @@ +import { mergeUserConfigWithTransformOutput } from '../../graphql-transformer/utils'; +import { TransformerProjectConfig, DeploymentResources } from '@aws-amplify/graphql-transformer-core'; + +describe('mergeUserConfigWithTransformOutput', () => { + let userConfig; + let transformerOutput; + + beforeAll(() => { + transformerOutput = { + resolvers: {}, + pipelineFunctions: { + 'Query.listTodos.req.vtl': '## [Start] List Request. **\n' + '#set( $limit = $util.defaultIfNull($context.args.limit, 100) )\n', + }, + functions: {}, + schema: '', + stackMapping: {}, + stacks: {}, + rootStack: null, + } as DeploymentResources; + }); + + describe('has user-created resolvers', () => { + beforeAll(() => { + userConfig = { + schema: '', + functions: {}, + pipelineFunctions: {}, + resolvers: { + 'Query.listTodos.req.vtl': '$util.unauthorized\n', + }, + stacks: {}, + config: { Version: 5, ElasticsearchWarning: true }, + } as TransformerProjectConfig; + }); + + it('merges the custom resolver with transformer output', () => { + const output = mergeUserConfigWithTransformOutput(userConfig, transformerOutput); + + expect(output.pipelineFunctions['Query.listTodos.req.vtl']).toEqual('$util.unauthorized\n'); + }); + }); + + describe('has user created pipeline function', () => { + beforeAll(() => { + userConfig = { + schema: '', + functions: {}, + pipelineFunctions: { + 'Query.listTodos.req.vtl': '$util.unauthorized\n', + }, + resolvers: {}, + stacks: {}, + config: { Version: 5, ElasticsearchWarning: true }, + } as TransformerProjectConfig; + }); + + it('merges custom pipeline function with transformer output', () => { + const output = mergeUserConfigWithTransformOutput(userConfig, transformerOutput); + + expect(output.pipelineFunctions['Query.listTodos.req.vtl']).toEqual('$util.unauthorized\n'); + }); + }); +}); diff --git a/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts b/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts index 9274dcad0a5..cf0b8140dd1 100644 --- a/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts +++ b/packages/amplify-provider-awscloudformation/src/graphql-transformer/transform-graphql-schema.ts @@ -24,7 +24,7 @@ import { import { SearchableModelTransformer } from '@aws-amplify/graphql-searchable-transformer'; import { ProviderName as providerName } from '../constants'; import { hashDirectory } from '../upload-appsync-files'; -import { writeDeploymentToDisk } from './utils'; +import { mergeUserConfigWithTransformOutput, writeDeploymentToDisk } from './utils'; import { loadProject as readTransformerConfiguration } from './transform-config'; import { loadProject } from 'graphql-transformer-core'; import { AppSyncAuthConfiguration } from '@aws-amplify/graphql-transformer-core'; @@ -432,5 +432,8 @@ async function _buildProject(opts: ProjectOptions) { stacks: opts.projectConfig.stacks || {}, featureFlags: new AmplifyCLIFeatureFlagAdapter(), }); - return transform.transform(userProjectConfig.schema.toString()); + + const transformOutput = transform.transform(userProjectConfig.schema.toString()); + + return mergeUserConfigWithTransformOutput(userProjectConfig, transformOutput); } diff --git a/packages/amplify-provider-awscloudformation/src/graphql-transformer/utils.ts b/packages/amplify-provider-awscloudformation/src/graphql-transformer/utils.ts index c849a903223..6eddd579f84 100644 --- a/packages/amplify-provider-awscloudformation/src/graphql-transformer/utils.ts +++ b/packages/amplify-provider-awscloudformation/src/graphql-transformer/utils.ts @@ -85,6 +85,20 @@ export function readFromPath(directory: string): any { return accum; } +export function mergeUserConfigWithTransformOutput(userConfig: any, transformOutput: any) { + const userResolvers = userConfig.resolvers || {}; + const userPipelineFunctions = userConfig.pipelineFunctions || {}; + const pipelineFunctions = transformOutput.pipelineFunctions; + + for (const userResolver of Object.keys(userResolvers)) pipelineFunctions[userResolver] = userResolvers[userResolver]; + for (const userResolver of Object.keys(userPipelineFunctions)) pipelineFunctions[userResolver] = userPipelineFunctions[userResolver]; + + return { + ...transformOutput, + pipelineFunctions, + }; +} + /** * Writes a deployment to disk at a path. */