diff --git a/doc/general-config.md b/doc/general-config.md
index ff6a19d2..8cb91965 100644
--- a/doc/general-config.md
+++ b/doc/general-config.md
@@ -44,7 +44,8 @@ appSync:
- `dataSources`: See [DataSources](dataSources.md)
- `resolvers`: See [Resolvers](resolvers.md)
- `pipelineFunctions`: See [Pipeline functions](pipeline-functions.md)
-- `substitutions`: See [Substitutions](substitutions.md)
+- `substitutions`: See [Substitutions](substitutions.md). Deprecated: Use environment variables.
+- `environment`: A list of environment variables for the API. See [Official Documentation](https://docs.aws.amazon.com/appsync/latest/devguide/environmental-variables.html)
- `caching`: See [Cacing](caching.md)
- `waf`: See [Web Application Firefall](WAF.md)
- `logging`: See [Logging](#Logging)
diff --git a/doc/resolvers.md b/doc/resolvers.md
index 7e3d7146..48de245b 100644
--- a/doc/resolvers.md
+++ b/doc/resolvers.md
@@ -29,7 +29,7 @@ appSync:
- `code`: The path of the JavaScript resolver handler file, relative to `serverless.yml`. If not specified, a [minimalistic default](#javascript-vs-vtl) is used.
- `request`: The path to the VTL request mapping template file, relative to `serverless.yml`.
- `response`: The path to the VTL response mapping template file, relative to `serverless.yml`.
-- `substitutions`: See [Variable Substitutions](substitutions.md)
+- `substitutions`: See [Variable Substitutions](substitutions.md). Deprecated: Use [environment variables](./general-config.md) instead.
- `caching`: [See below](#Caching)
- `sync`: [See SyncConfig](syncConfig.md)
diff --git a/doc/substitutions.md b/doc/substitutions.md
index 794953ba..f43bc53d 100644
--- a/doc/substitutions.md
+++ b/doc/substitutions.md
@@ -1,3 +1,5 @@
+> ⚠️ Substitutions are deprecated. Use [Environment Variables](./general-config.md) instead.
+
# Substitutions
`Substitutions` is a feature that allows you to replace some variables in your VTL mapping templates or JS resolvers with dynamic values.
@@ -30,27 +32,29 @@ appSync:
VTL mapping template
- ```vtl
- {
- "version" : "2018-05-29",
- "operation" : "BatchPutItem",
- "tables" : {
- "${postsTable}": [...]
- }
- }
- ```
+```vtl
+{
+ "version" : "2018-05-29",
+ "operation" : "BatchPutItem",
+ "tables" : {
+ "${postsTable}": [...]
+ }
+}
+```
+
JS Resolvers
-
- ```js
- const tableName = '#postsTable#';
- return {
- operation: "BatchGetItem",
- tables: {
- [tableName]: { keys },
- },
- };
- ```
+
+```js
+const tableName = '#postsTable#';
+return {
+ operation: 'BatchGetItem',
+ tables: {
+ [tableName]: { keys },
+ },
+};
+```
+
diff --git a/src/__tests__/__snapshots__/api.test.ts.snap b/src/__tests__/__snapshots__/api.test.ts.snap
index 37d43140..000e5ce5 100644
--- a/src/__tests__/__snapshots__/api.test.ts.snap
+++ b/src/__tests__/__snapshots__/api.test.ts.snap
@@ -20,6 +20,7 @@ Object {
},
],
"AuthenticationType": "API_KEY",
+ "EnvironmentVariables": undefined,
"Name": "MyApi",
"Tags": Array [
Object {
@@ -47,6 +48,7 @@ Object {
"GraphQlApi": Object {
"Properties": Object {
"AuthenticationType": "AWS_LAMBDA",
+ "EnvironmentVariables": undefined,
"LambdaAuthorizerConfig": Object {
"AuthorizerResultTtlInSeconds": undefined,
"AuthorizerUri": Object {
diff --git a/src/__tests__/api.test.ts b/src/__tests__/api.test.ts
index 56ea77f0..87405c9d 100644
--- a/src/__tests__/api.test.ts
+++ b/src/__tests__/api.test.ts
@@ -15,6 +15,7 @@ describe('Api', () => {
"GraphQlApi": Object {
"Properties": Object {
"AuthenticationType": "API_KEY",
+ "EnvironmentVariables": undefined,
"Name": "MyApi",
"Tags": Array [
Object {
@@ -42,6 +43,7 @@ describe('Api', () => {
"GraphQlApi": Object {
"Properties": Object {
"AuthenticationType": "API_KEY",
+ "EnvironmentVariables": undefined,
"Name": "MyApi",
"Tags": Array [
Object {
@@ -72,6 +74,7 @@ describe('Api', () => {
"GraphQlApi": Object {
"Properties": Object {
"AuthenticationType": "API_KEY",
+ "EnvironmentVariables": undefined,
"IntrospectionConfig": "DISABLED",
"Name": "MyApi",
"QueryDepthLimit": 10,
@@ -90,6 +93,44 @@ describe('Api', () => {
`);
});
+ it('should compile the Api Resource with Environments', () => {
+ const api = new Api(
+ given.appSyncConfig({
+ environment: {
+ TABLE_NAME: 'MyTable',
+ OTHER_TABLE: {
+ Ref: 'OtherTable',
+ },
+ },
+ }),
+ plugin,
+ );
+ expect(api.compileEndpoint()).toMatchInlineSnapshot(`
+ Object {
+ "GraphQlApi": Object {
+ "Properties": Object {
+ "AuthenticationType": "API_KEY",
+ "EnvironmentVariables": Object {
+ "OTHER_TABLE": Object {
+ "Ref": "OtherTable",
+ },
+ "TABLE_NAME": "MyTable",
+ },
+ "Name": "MyApi",
+ "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({
@@ -106,6 +147,7 @@ describe('Api', () => {
"GraphQlApi": Object {
"Properties": Object {
"AuthenticationType": "API_KEY",
+ "EnvironmentVariables": undefined,
"LogConfig": Object {
"CloudWatchLogsRoleArn": Object {
"Fn::GetAtt": Array [
@@ -215,6 +257,7 @@ describe('Api', () => {
},
],
"AuthenticationType": "AMAZON_COGNITO_USER_POOLS",
+ "EnvironmentVariables": undefined,
"Name": "MyApi",
"Tags": Array [
Object {
diff --git a/src/__tests__/validation/__snapshots__/base.test.ts.snap b/src/__tests__/validation/__snapshots__/base.test.ts.snap
index 5ee850ed..b2b9d274 100644
--- a/src/__tests__/validation/__snapshots__/base.test.ts.snap
+++ b/src/__tests__/validation/__snapshots__/base.test.ts.snap
@@ -60,6 +60,7 @@ exports[`Valdiation should validate 1`] = `
/introspection: must be boolean
/queryDepthLimit: must be integer
/resolverCountLimit: must be integer
+/environment: must be a valid environment definition
/esbuild: must be an esbuild config object or false"
`;
diff --git a/src/__tests__/validation/base.test.ts b/src/__tests__/validation/base.test.ts
index e4d1f789..5824bc2d 100644
--- a/src/__tests__/validation/base.test.ts
+++ b/src/__tests__/validation/base.test.ts
@@ -12,6 +12,10 @@ describe('Valdiation', () => {
queryDepthLimit: 10,
resolverCountLimit: 10,
xrayEnabled: true,
+ environment: {
+ MY_TABLE: 'my-table',
+ MY_OTHER_TABLE: { Ref: 'MyOtherTable' },
+ },
tags: {
foo: 'bar',
},
@@ -32,6 +36,7 @@ describe('Valdiation', () => {
xrayEnabled: 'BAR',
unknownPorp: 'foo',
esbuild: 'bad',
+ environment: 'Bad',
});
}).toThrowErrorMatchingSnapshot();
diff --git a/src/resources/Api.ts b/src/resources/Api.ts
index 4a451b0a..92a9663a 100644
--- a/src/resources/Api.ts
+++ b/src/resources/Api.ts
@@ -76,6 +76,7 @@ export class Api {
Name: this.config.name,
XrayEnabled: this.config.xrayEnabled || false,
Tags: this.getTagsConfig(),
+ EnvironmentVariables: this.config.environment,
},
};
diff --git a/src/types/common.ts b/src/types/common.ts
index b2815632..cc8157b9 100644
--- a/src/types/common.ts
+++ b/src/types/common.ts
@@ -128,6 +128,7 @@ export type SyncConfig = {
} & LambdaConfig;
export type Substitutions = Record;
+export type EnvironmentVariables = Record;
export type DsDynamoDBConfig = {
type: 'AMAZON_DYNAMODB';
diff --git a/src/types/index.ts b/src/types/index.ts
index 8105630b..e52f8388 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -15,6 +15,7 @@ import {
DsOpenSearchConfig,
DsRelationalDbConfig,
SyncConfig,
+ EnvironmentVariables,
} from './common';
export * from './common';
@@ -33,6 +34,7 @@ export type AppSyncConfig = {
| Record[]
| Record;
substitutions?: Substitutions;
+ environment?: EnvironmentVariables;
xrayEnabled?: boolean;
logging?: LoggingConfig;
caching?: CachingConfig;
diff --git a/src/types/plugin.ts b/src/types/plugin.ts
index c6f70166..0b8bf8f0 100644
--- a/src/types/plugin.ts
+++ b/src/types/plugin.ts
@@ -15,6 +15,7 @@ import {
DsEventBridgeConfig,
DsNone,
Substitutions,
+ EnvironmentVariables,
} from './common';
export * from './common';
@@ -29,6 +30,7 @@ export type AppSyncConfig = {
resolvers: Record;
pipelineFunctions: Record;
substitutions?: Substitutions;
+ environment?: EnvironmentVariables;
xrayEnabled?: boolean;
logging?: LoggingConfig;
caching?: CachingConfig;
diff --git a/src/validation.ts b/src/validation.ts
index 447787e0..4cc292e0 100644
--- a/src/validation.ts
+++ b/src/validation.ts
@@ -255,6 +255,14 @@ export const appSyncSchema = {
required: [],
errorMessage: 'must be a valid substitutions definition',
},
+ environment: {
+ type: 'object',
+ additionalProperties: {
+ $ref: '#/definitions/stringOrIntrinsicFunction',
+ },
+ required: [],
+ errorMessage: 'must be a valid environment definition',
+ },
dataSource: {
if: { type: 'object' },
then: { $ref: '#/definitions/dataSourceConfig' },
@@ -687,6 +695,7 @@ export const appSyncSchema = {
queryDepthLimit: { type: 'integer', minimum: 1, maximum: 75 },
resolverCountLimit: { type: 'integer', minimum: 1, maximum: 1000 },
substitutions: { $ref: '#/definitions/substitutions' },
+ environment: { $ref: '#/definitions/environment' },
waf: {
type: 'object',
properties: {