diff --git a/src/__tests__/api.test.ts b/src/__tests__/api.test.ts index c8389f11..56ea77f0 100644 --- a/src/__tests__/api.test.ts +++ b/src/__tests__/api.test.ts @@ -58,6 +58,38 @@ describe('Api', () => { `); }); + it('should compile the Api Resource with config', () => { + const api = new Api( + given.appSyncConfig({ + introspection: false, + queryDepthLimit: 10, + resolverCountLimit: 20, + }), + plugin, + ); + expect(api.compileEndpoint()).toMatchInlineSnapshot(` + Object { + "GraphQlApi": Object { + "Properties": Object { + "AuthenticationType": "API_KEY", + "IntrospectionConfig": "DISABLED", + "Name": "MyApi", + "QueryDepthLimit": 10, + "ResolverCountLimit": 20, + "Tags": Array [ + Object { + "Key": "stage", + "Value": "Dev", + }, + ], + "XrayEnabled": false, + }, + "Type": "AWS::AppSync::GraphQLApi", + }, + } + `); + }); + it('should compile the Api Resource with logs enabled', () => { const api = new Api( given.appSyncConfig({ diff --git a/src/__tests__/validation/__snapshots__/base.test.ts.snap b/src/__tests__/validation/__snapshots__/base.test.ts.snap index 79de3130..5ee850ed 100644 --- a/src/__tests__/validation/__snapshots__/base.test.ts.snap +++ b/src/__tests__/validation/__snapshots__/base.test.ts.snap @@ -57,5 +57,13 @@ exports[`Valdiation should validate 1`] = ` /unknownPorp: invalid (unknown) property /xrayEnabled: must be boolean /visibility: must be \\"GLOBAL\\" or \\"PRIVATE\\" +/introspection: must be boolean +/queryDepthLimit: must be integer +/resolverCountLimit: must be integer /esbuild: must be an esbuild config object or false" `; + +exports[`Valdiation should validate 2`] = ` +"/queryDepthLimit: must be <= 75 +/resolverCountLimit: must be <= 1000" +`; diff --git a/src/__tests__/validation/base.test.ts b/src/__tests__/validation/base.test.ts index 4f899d21..e4d1f789 100644 --- a/src/__tests__/validation/base.test.ts +++ b/src/__tests__/validation/base.test.ts @@ -8,6 +8,9 @@ describe('Valdiation', () => { validateConfig({ ...basicConfig, visibility: 'GLOBAL', + introspection: true, + queryDepthLimit: 10, + resolverCountLimit: 10, xrayEnabled: true, tags: { foo: 'bar', @@ -23,11 +26,22 @@ describe('Valdiation', () => { expect(function () { validateConfig({ visibility: 'FOO', + introspection: 10, + queryDepthLimit: 'foo', + resolverCountLimit: 'bar', xrayEnabled: 'BAR', unknownPorp: 'foo', esbuild: 'bad', }); }).toThrowErrorMatchingSnapshot(); + + expect(function () { + validateConfig({ + ...basicConfig, + queryDepthLimit: 76, + resolverCountLimit: 1001, + }); + }).toThrowErrorMatchingSnapshot(); }); describe('Log', () => { diff --git a/src/resources/Api.ts b/src/resources/Api.ts index 95e41923..4a451b0a 100644 --- a/src/resources/Api.ts +++ b/src/resources/Api.ts @@ -111,6 +111,24 @@ export class Api { }); } + if (this.config.introspection !== undefined) { + merge(endpointResource.Properties, { + IntrospectionConfig: this.config.introspection ? 'ENABLED' : 'DISABLED', + }); + } + + if (this.config.queryDepthLimit !== undefined) { + merge(endpointResource.Properties, { + QueryDepthLimit: this.config.queryDepthLimit, + }); + } + + if (this.config.resolverCountLimit !== undefined) { + merge(endpointResource.Properties, { + ResolverCountLimit: this.config.resolverCountLimit, + }); + } + const resources = { [logicalId]: endpointResource, }; diff --git a/src/types/index.ts b/src/types/index.ts index c8cfae9b..8105630b 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -40,6 +40,9 @@ export type AppSyncConfig = { tags?: Record; visibility?: 'GLOBAL' | 'PRIVATE'; esbuild?: BuildOptions | false; + introspection?: boolean; + queryDepthLimit?: number; + resolverCountLimit?: number; }; export type BaseResolverConfig = { diff --git a/src/types/plugin.ts b/src/types/plugin.ts index f7e245de..c6f70166 100644 --- a/src/types/plugin.ts +++ b/src/types/plugin.ts @@ -36,6 +36,9 @@ export type AppSyncConfig = { tags?: Record; visibility?: 'GLOBAL' | 'PRIVATE'; esbuild?: BuildOptions | false; + introspection?: boolean; + queryDepthLimit?: number; + resolverCountLimit?: number; }; export type BaseResolverConfig = { diff --git a/src/validation.ts b/src/validation.ts index bc2887e2..447787e0 100644 --- a/src/validation.ts +++ b/src/validation.ts @@ -683,6 +683,9 @@ export const appSyncSchema = { enum: ['GLOBAL', 'PRIVATE'], errorMessage: 'must be "GLOBAL" or "PRIVATE"', }, + introspection: { type: 'boolean' }, + queryDepthLimit: { type: 'integer', minimum: 1, maximum: 75 }, + resolverCountLimit: { type: 'integer', minimum: 1, maximum: 1000 }, substitutions: { $ref: '#/definitions/substitutions' }, waf: { type: 'object',