Skip to content

Commit

Permalink
feat(amplify-provider-awscloudformation): enable custom resolvers for…
Browse files Browse the repository at this point in the history
… v2 transformer
  • Loading branch information
danielleadams committed Oct 8, 2021
1 parent f25abbf commit 2a447f1
Show file tree
Hide file tree
Showing 4 changed files with 348 additions and 39 deletions.
5 changes: 5 additions & 0 deletions packages/amplify-e2e-core/src/utils/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ export function addCustomResolver(projectDir: string, projectName: string, resol
const resolverPath = path.join(projectDir, 'amplify', 'backend', 'api', projectName, 'resolvers', resolverName);
fs.writeFileSync(resolverPath, resolver);
}

export function addCustomResourcesJson(projectDir: string, projectName: string, json?: string) {
const jsonPath = path.join(projectDir, 'amplify', 'backend', 'api', projectName, 'stacks', 'CustomResources.json');
fs.writeFileSync(jsonPath, json || '{}');
}
42 changes: 42 additions & 0 deletions packages/amplify-e2e-tests/src/__tests__/resolvers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
addApiWithSchema,
addCustomResolver,
apiGqlCompile,
addCustomResourcesJson,
} from 'amplify-e2e-core';
import { join } from 'path';
import * as fs from 'fs-extra';
Expand Down Expand Up @@ -41,3 +42,44 @@ describe('overriding generated resolvers', () => {
expect(fs.readFileSync(generatedResolverPath)).toEqual(resolver);
});
});

describe('custom 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 resolverReqName = 'Query.commentsForTodo.req.vtl';
const resolverResName = 'Query.commentsForTodo.res.vtl';

const resolverReq = '$util.unauthorized()';
const resolverRes = '$util.toJson({})';

const generatedReqResolverPath = join(projectDir, 'amplify', 'backend', 'api', apiName, 'build', 'pipelineFunctions', resolverReqName);
const generatedResResolverPath = join(projectDir, 'amplify', 'backend', 'api', apiName, 'build', 'pipelineFunctions', resolverResName);
const stackPath = join(projectDir, 'amplify', 'backend', 'api', apiName, 'build', 'stacks', 'CustomResources.json');

await addApiWithSchema(projectDir, 'simple_model.graphql');
await apiGqlCompile(projectDir, true);

addCustomResolver(projectDir, apiName, resolverReqName, resolverReq);
addCustomResolver(projectDir, apiName, resolverResName, resolverRes);
addCustomResourcesJson(projectDir, apiName);
await apiGqlCompile(projectDir, true);

expect(fs.readFileSync(generatedReqResolverPath)).toEqual(resolverReq);
expect(fs.readFileSync(generatedResResolverPath)).toEqual(resolverRes);
expect(fs.readFileSync(stackPath)).toEqual('{}');
});
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { mergeUserConfigWithTransformOutput } from '../../graphql-transformer/utils';
import { TransformerProjectConfig, DeploymentResources } from '@aws-amplify/graphql-transformer-core';

describe('mergeUserConfigWithTransformOutput', () => {
let userConfig;
let transformerOutput;
describe('graphql transformer utils', () => {
let userConfig: TransformerProjectConfig;
let transformerOutput: DeploymentResources;

beforeAll(() => {
transformerOutput = {
Expand All @@ -15,49 +15,226 @@ describe('mergeUserConfigWithTransformOutput', () => {
schema: '',
stackMapping: {},
stacks: {},
rootStack: null,
rootStack: {
Parameters: {},
Resources: {},
},
} 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;
describe('mergeUserConfigWithTransformOutput', () => {
describe('has user created functions', () => {
beforeAll(() => {
userConfig = {
schema: '',
functions: {
userFn: 'userFn()',
},
pipelineFunctions: {},
resolvers: {},
stacks: {},
config: { Version: 5, ElasticsearchWarning: true },
} as TransformerProjectConfig;
});

it('merges function with transform output functions', () => {
const { functions } = mergeUserConfigWithTransformOutput(userConfig, transformerOutput);

expect(functions['userFn']).toEqual('userFn()');
});
});

it('merges the custom resolver with transformer output', () => {
const output = mergeUserConfigWithTransformOutput(userConfig, transformerOutput);
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');
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;
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 { pipelineFunctions } = mergeUserConfigWithTransformOutput(userConfig, transformerOutput);

expect(pipelineFunctions['Query.listTodos.req.vtl']).toEqual('$util.unauthorized\n');
});
});

it('merges custom pipeline function with transformer output', () => {
const output = mergeUserConfigWithTransformOutput(userConfig, transformerOutput);
describe('has user created stacks', () => {
beforeAll(() => {
userConfig = {
schema: '',
functions: {},
pipelineFunctions: {},
resolvers: {},
stacks: {
'CustomResources.json': {
Resources: {
QueryCommentsForTodoResolver: {
Type: 'AWS::AppSync::Resolver',
Properties: {
ApiId: {
Ref: 'AppSyncApiId',
},
DataSourceName: 'CommentTable',
TypeName: 'Query',
FieldName: 'commentsForTodo',
RequestMappingTemplateS3Location: {
'Fn::Sub': [
's3://${S3DeploymentBucket}/${S3DeploymentRootKey}/pipelineFunctions/Query.commentsForTodo.req.vtl',
{
S3DeploymentBucket: {
Ref: 'S3DeploymentBucket',
},
S3DeploymentRootKey: {
Ref: 'S3DeploymentRootKey',
},
},
],
},
ResponseMappingTemplateS3Location: {
'Fn::Sub': [
's3://${S3DeploymentBucket}/${S3DeploymentRootKey}/pipelineFunctions/Query.commentsForTodo.res.vtl',
{
S3DeploymentBucket: {
Ref: 'S3DeploymentBucket',
},
S3DeploymentRootKey: {
Ref: 'S3DeploymentRootKey',
},
},
],
},
},
},
},
Parameters: {
AppSyncApiId: {
Type: 'String',
Description: 'The id of the AppSync API associated with this project.',
},
AppSyncApiName: {
Type: 'String',
Description: 'The name of the AppSync API',
Default: 'AppSyncSimpleTransform',
},
env: {
Type: 'String',
Description: 'The environment name. e.g. Dev, Test, or Production',
Default: 'NONE',
},
S3DeploymentBucket: {
Type: 'String',
Description: 'The S3 bucket containing all deployment assets for the project.',
},
S3DeploymentRootKey: {
Type: 'String',
Description: 'An S3 key relative to the S3DeploymentBucket that points to the root\n' + 'of the deployment directory.',
},
},
},
},
config: { Version: 5, ElasticsearchWarning: true },
} as unknown as TransformerProjectConfig;
});

it('merges custom pipeline function with transformer output', () => {
const { stacks } = mergeUserConfigWithTransformOutput(userConfig, transformerOutput);

expect(output.pipelineFunctions['Query.listTodos.req.vtl']).toEqual('$util.unauthorized\n');
expect(stacks).toEqual({
'CustomResources.json': {
Resources: {
QueryCommentsForTodoResolver: {
Type: 'AWS::AppSync::Resolver',
Properties: {
ApiId: {
Ref: 'AppSyncApiId',
},
DataSourceName: 'CommentTable',
TypeName: 'Query',
FieldName: 'commentsForTodo',
RequestMappingTemplateS3Location: {
'Fn::Sub': [
's3://${S3DeploymentBucket}/${S3DeploymentRootKey}/pipelineFunctions/Query.commentsForTodo.req.vtl',
{
S3DeploymentBucket: {
Ref: 'S3DeploymentBucket',
},
S3DeploymentRootKey: {
Ref: 'S3DeploymentRootKey',
},
},
],
},
ResponseMappingTemplateS3Location: {
'Fn::Sub': [
's3://${S3DeploymentBucket}/${S3DeploymentRootKey}/pipelineFunctions/Query.commentsForTodo.res.vtl',
{
S3DeploymentBucket: {
Ref: 'S3DeploymentBucket',
},
S3DeploymentRootKey: {
Ref: 'S3DeploymentRootKey',
},
},
],
},
},
},
},
Parameters: {
AppSyncApiId: {
Type: 'String',
Description: 'The id of the AppSync API associated with this project.',
},
AppSyncApiName: {
Type: 'String',
Description: 'The name of the AppSync API',
Default: 'AppSyncSimpleTransform',
},
env: {
Type: 'String',
Description: 'The environment name. e.g. Dev, Test, or Production',
Default: 'NONE',
},
S3DeploymentBucket: {
Type: 'String',
Description: 'The S3 bucket containing all deployment assets for the project.',
},
S3DeploymentRootKey: {
Type: 'String',
Description: 'An S3 key relative to the S3DeploymentBucket that points to the root\n' + 'of the deployment directory.',
},
},
},
});
});
});
});
});
Loading

0 comments on commit 2a447f1

Please sign in to comment.