@ttoss/appsync-api 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -7
- package/dist/esm/cli.js +1 -4
- package/dist/esm/index.js +375 -4
- package/dist/index.d.ts +7 -6
- package/dist/index.js +32 -16
- package/package.json +4 -4
- package/src/cli.ts +1 -3
- package/src/createApiTemplate.ts +29 -8
- package/src/createAppSyncResolverHandler.ts +2 -3
- package/dist/esm/chunk-RWRQSJ4M.js +0 -364
package/dist/cli.js
CHANGED
|
@@ -25,18 +25,12 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
|
|
26
26
|
// src/cli.ts
|
|
27
27
|
var fs = __toESM(require("fs"));
|
|
28
|
-
|
|
29
|
-
// src/createApiTemplate.ts
|
|
30
|
-
var import_graphql_compose = require("graphql-compose");
|
|
31
|
-
var AppSyncGraphQLSchemaLogicalId = "AppSyncGraphQLSchema";
|
|
32
|
-
|
|
33
|
-
// src/cli.ts
|
|
34
28
|
var import_cloudformation = require("@ttoss/cloudformation");
|
|
35
29
|
var import_minimist = __toESM(require("minimist"));
|
|
36
30
|
var argv = (0, import_minimist.default)(process.argv.slice(2));
|
|
37
31
|
if (argv._.includes("build-schema")) {
|
|
38
32
|
const template = (0, import_cloudformation.findAndReadCloudFormationTemplate)({});
|
|
39
|
-
const sdl = template.
|
|
33
|
+
const sdl = template.Metadata.Schema.Definition;
|
|
40
34
|
fs.mkdirSync("schema", { recursive: true });
|
|
41
35
|
fs.writeFileSync("schema/schema.graphql", sdl);
|
|
42
36
|
}
|
package/dist/esm/cli.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
-
import {
|
|
3
|
-
AppSyncGraphQLSchemaLogicalId
|
|
4
|
-
} from "./chunk-RWRQSJ4M.js";
|
|
5
2
|
|
|
6
3
|
// src/cli.ts
|
|
7
4
|
import * as fs from "fs";
|
|
@@ -10,7 +7,7 @@ import minimist from "minimist";
|
|
|
10
7
|
var argv = minimist(process.argv.slice(2));
|
|
11
8
|
if (argv._.includes("build-schema")) {
|
|
12
9
|
const template = findAndReadCloudFormationTemplate({});
|
|
13
|
-
const sdl = template.
|
|
10
|
+
const sdl = template.Metadata.Schema.Definition;
|
|
14
11
|
fs.mkdirSync("schema", { recursive: true });
|
|
15
12
|
fs.writeFileSync("schema/schema.graphql", sdl);
|
|
16
13
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,377 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "
|
|
2
|
+
|
|
3
|
+
// src/createApiTemplate.ts
|
|
4
|
+
import { graphql } from "graphql-compose";
|
|
5
|
+
|
|
6
|
+
// ../../node_modules/tslib/tslib.es6.js
|
|
7
|
+
var __assign = function() {
|
|
8
|
+
__assign = Object.assign || function __assign2(t) {
|
|
9
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
10
|
+
s = arguments[i];
|
|
11
|
+
for (var p in s)
|
|
12
|
+
if (Object.prototype.hasOwnProperty.call(s, p))
|
|
13
|
+
t[p] = s[p];
|
|
14
|
+
}
|
|
15
|
+
return t;
|
|
16
|
+
};
|
|
17
|
+
return __assign.apply(this, arguments);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// ../../node_modules/lower-case/dist.es2015/index.js
|
|
21
|
+
function lowerCase(str) {
|
|
22
|
+
return str.toLowerCase();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ../../node_modules/no-case/dist.es2015/index.js
|
|
26
|
+
var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
|
|
27
|
+
var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
|
|
28
|
+
function noCase(input, options) {
|
|
29
|
+
if (options === void 0) {
|
|
30
|
+
options = {};
|
|
31
|
+
}
|
|
32
|
+
var _a = options.splitRegexp, splitRegexp = _a === void 0 ? DEFAULT_SPLIT_REGEXP : _a, _b = options.stripRegexp, stripRegexp = _b === void 0 ? DEFAULT_STRIP_REGEXP : _b, _c = options.transform, transform = _c === void 0 ? lowerCase : _c, _d = options.delimiter, delimiter = _d === void 0 ? " " : _d;
|
|
33
|
+
var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0");
|
|
34
|
+
var start = 0;
|
|
35
|
+
var end = result.length;
|
|
36
|
+
while (result.charAt(start) === "\0")
|
|
37
|
+
start++;
|
|
38
|
+
while (result.charAt(end - 1) === "\0")
|
|
39
|
+
end--;
|
|
40
|
+
return result.slice(start, end).split("\0").map(transform).join(delimiter);
|
|
41
|
+
}
|
|
42
|
+
function replace(input, re, value) {
|
|
43
|
+
if (re instanceof RegExp)
|
|
44
|
+
return input.replace(re, value);
|
|
45
|
+
return re.reduce(function(input2, re2) {
|
|
46
|
+
return input2.replace(re2, value);
|
|
47
|
+
}, input);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ../../node_modules/pascal-case/dist.es2015/index.js
|
|
51
|
+
function pascalCaseTransform(input, index) {
|
|
52
|
+
var firstChar = input.charAt(0);
|
|
53
|
+
var lowerChars = input.substr(1).toLowerCase();
|
|
54
|
+
if (index > 0 && firstChar >= "0" && firstChar <= "9") {
|
|
55
|
+
return "_" + firstChar + lowerChars;
|
|
56
|
+
}
|
|
57
|
+
return "" + firstChar.toUpperCase() + lowerChars;
|
|
58
|
+
}
|
|
59
|
+
function pascalCase(input, options) {
|
|
60
|
+
if (options === void 0) {
|
|
61
|
+
options = {};
|
|
62
|
+
}
|
|
63
|
+
return noCase(input, __assign({ delimiter: "", transform: pascalCaseTransform }, options));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ../carlin/src/deploy/lambdaLayer/getPackageLambdaLayerStackName.ts
|
|
67
|
+
var lambdaLayerStackNamePrefix = `LambdaLayer`;
|
|
68
|
+
var getPackageLambdaLayerStackName = (packageName) => {
|
|
69
|
+
const [scopedName, version] = packageName.split("@").filter((part) => {
|
|
70
|
+
return !!part;
|
|
71
|
+
});
|
|
72
|
+
return [
|
|
73
|
+
lambdaLayerStackNamePrefix,
|
|
74
|
+
pascalCase(scopedName),
|
|
75
|
+
version.replace(/[^0-9.]/g, "").replace(/\./g, "-")
|
|
76
|
+
].join("-");
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// package.json
|
|
80
|
+
var package_default = {
|
|
81
|
+
name: "@ttoss/appsync-api",
|
|
82
|
+
version: "0.8.2",
|
|
83
|
+
description: "A library for building GraphQL APIs for AWS AppSync.",
|
|
84
|
+
license: "UNLICENSED",
|
|
85
|
+
author: "ttoss",
|
|
86
|
+
contributors: [
|
|
87
|
+
"Pedro Arantes <pedro@arantespp.com> (https://arantespp.com)"
|
|
88
|
+
],
|
|
89
|
+
exports: {
|
|
90
|
+
".": {
|
|
91
|
+
import: "./dist/esm/index.js",
|
|
92
|
+
require: "./dist/index.js"
|
|
93
|
+
},
|
|
94
|
+
"./server": {
|
|
95
|
+
import: "./dist/esm/server.js",
|
|
96
|
+
require: "./dist/server.js"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
main: "dist/index.js",
|
|
100
|
+
module: "dist/esm/index.js",
|
|
101
|
+
bin: {
|
|
102
|
+
"ttoss-appsync-api": "./bin/cli.js"
|
|
103
|
+
},
|
|
104
|
+
files: [
|
|
105
|
+
"dist",
|
|
106
|
+
"src"
|
|
107
|
+
],
|
|
108
|
+
scripts: {
|
|
109
|
+
build: "tsup",
|
|
110
|
+
test: "jest"
|
|
111
|
+
},
|
|
112
|
+
sideEffects: false,
|
|
113
|
+
typings: "dist/index.d.ts",
|
|
114
|
+
dependencies: {
|
|
115
|
+
"@ttoss/cloudformation": "^0.5.2",
|
|
116
|
+
express: "^4.18.2",
|
|
117
|
+
"graphql-compose-connection": "^8.2.1",
|
|
118
|
+
"graphql-helix": "^1.13.0",
|
|
119
|
+
minimist: "^1.2.8"
|
|
120
|
+
},
|
|
121
|
+
peerDependencies: {
|
|
122
|
+
graphql: "^16.6.0",
|
|
123
|
+
"graphql-compose": "^9.0.10"
|
|
124
|
+
},
|
|
125
|
+
devDependencies: {
|
|
126
|
+
"@ttoss/config": "^1.28.1",
|
|
127
|
+
"@types/aws-lambda": "^8.10.110",
|
|
128
|
+
carlin: "^1.23.3",
|
|
129
|
+
graphql: "^16.6.0",
|
|
130
|
+
"graphql-compose": "^9.0.10"
|
|
131
|
+
},
|
|
132
|
+
keywords: [
|
|
133
|
+
"api",
|
|
134
|
+
"appsync",
|
|
135
|
+
"aws",
|
|
136
|
+
"graphql"
|
|
137
|
+
],
|
|
138
|
+
publishConfig: {
|
|
139
|
+
access: "public"
|
|
140
|
+
},
|
|
141
|
+
typesVersions: {
|
|
142
|
+
"*": {
|
|
143
|
+
".": [
|
|
144
|
+
"./dist/index.d.ts"
|
|
145
|
+
],
|
|
146
|
+
server: [
|
|
147
|
+
"./dist/server.d.ts"
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
// src/createApiTemplate.ts
|
|
154
|
+
var AppSyncGraphQLApiLogicalId = "AppSyncGraphQLApi";
|
|
155
|
+
var AppSyncGraphQLSchemaLogicalId = "AppSyncGraphQLSchema";
|
|
156
|
+
var AppSyncLambdaFunctionLogicalId = "AppSyncLambdaFunction";
|
|
157
|
+
var AppSyncLambdaFunctionAppSyncDataSourceLogicalId = "AppSyncLambdaFunctionAppSyncDataSource";
|
|
158
|
+
var AppSyncGraphQLApiKeyLogicalId = "AppSyncGraphQLApiKey";
|
|
159
|
+
var createApiTemplate = ({
|
|
160
|
+
additionalAuthenticationProviders,
|
|
161
|
+
authenticationType = "AMAZON_COGNITO_USER_POOLS",
|
|
162
|
+
schemaComposer: schemaComposer2,
|
|
163
|
+
dataSource,
|
|
164
|
+
lambdaFunction,
|
|
165
|
+
userPoolConfig
|
|
166
|
+
}) => {
|
|
167
|
+
const sdlWithoutComments = schemaComposer2.toSDL({
|
|
168
|
+
commentDescriptions: false,
|
|
169
|
+
omitDescriptions: true,
|
|
170
|
+
omitScalars: true
|
|
171
|
+
});
|
|
172
|
+
const sdlWithComments = schemaComposer2.toSDL({
|
|
173
|
+
omitScalars: true
|
|
174
|
+
});
|
|
175
|
+
graphql.validateSchema(schemaComposer2.buildSchema());
|
|
176
|
+
const resolveMethods = schemaComposer2.getResolveMethods();
|
|
177
|
+
const resolveMethodsEntries = Object.entries(resolveMethods).flatMap(([typeName, fieldResolvers]) => {
|
|
178
|
+
return Object.entries(fieldResolvers).map(([fieldName, resolver]) => {
|
|
179
|
+
if (typeof resolver !== "function") {
|
|
180
|
+
return void 0;
|
|
181
|
+
}
|
|
182
|
+
if (typeName.toLowerCase().includes("enum")) {
|
|
183
|
+
return void 0;
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
fieldName,
|
|
187
|
+
typeName
|
|
188
|
+
};
|
|
189
|
+
});
|
|
190
|
+
}).filter(Boolean);
|
|
191
|
+
const getGraphQLComposeDependenciesLambdaLayers = () => {
|
|
192
|
+
const { peerDependencies } = package_default;
|
|
193
|
+
const lambdaLayerStackNames = Object.entries(peerDependencies).map(
|
|
194
|
+
([dependencyName, dependencyVersion]) => {
|
|
195
|
+
return getPackageLambdaLayerStackName(
|
|
196
|
+
[dependencyName, dependencyVersion].join("@")
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
);
|
|
200
|
+
return lambdaLayerStackNames.map((lambdaLayerStackName) => {
|
|
201
|
+
return {
|
|
202
|
+
"Fn::ImportValue": lambdaLayerStackName
|
|
203
|
+
};
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
const template = {
|
|
207
|
+
AWSTemplateFormatVersion: "2010-09-09",
|
|
208
|
+
/**
|
|
209
|
+
* This is a workaround to use with build script.
|
|
210
|
+
*/
|
|
211
|
+
Metadata: {
|
|
212
|
+
Schema: {
|
|
213
|
+
Definition: sdlWithComments
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
Parameters: {
|
|
217
|
+
Environment: {
|
|
218
|
+
Default: "Staging",
|
|
219
|
+
Type: "String",
|
|
220
|
+
AllowedValues: ["Staging", "Production"]
|
|
221
|
+
},
|
|
222
|
+
LambdaS3Bucket: {
|
|
223
|
+
Type: "String"
|
|
224
|
+
},
|
|
225
|
+
LambdaS3Key: {
|
|
226
|
+
Type: "String"
|
|
227
|
+
},
|
|
228
|
+
LambdaS3ObjectVersion: {
|
|
229
|
+
Type: "String"
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
Resources: {
|
|
233
|
+
[AppSyncGraphQLApiLogicalId]: {
|
|
234
|
+
Type: "AWS::AppSync::GraphQLApi",
|
|
235
|
+
Properties: {
|
|
236
|
+
AuthenticationType: authenticationType,
|
|
237
|
+
Name: {
|
|
238
|
+
"Fn::Join": [
|
|
239
|
+
":",
|
|
240
|
+
[{ Ref: "AWS::StackName" }, AppSyncGraphQLApiLogicalId]
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
[AppSyncGraphQLSchemaLogicalId]: {
|
|
246
|
+
Type: "AWS::AppSync::GraphQLSchema",
|
|
247
|
+
Properties: {
|
|
248
|
+
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
249
|
+
Definition: sdlWithoutComments
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
[AppSyncLambdaFunctionLogicalId]: {
|
|
253
|
+
Type: "AWS::Lambda::Function",
|
|
254
|
+
Properties: {
|
|
255
|
+
Code: {
|
|
256
|
+
S3Bucket: { Ref: "LambdaS3Bucket" },
|
|
257
|
+
S3Key: { Ref: "LambdaS3Key" },
|
|
258
|
+
S3ObjectVersion: { Ref: "LambdaS3ObjectVersion" }
|
|
259
|
+
},
|
|
260
|
+
Handler: "index.handler",
|
|
261
|
+
Layers: getGraphQLComposeDependenciesLambdaLayers(),
|
|
262
|
+
MemorySize: 512,
|
|
263
|
+
Role: lambdaFunction.roleArn,
|
|
264
|
+
Runtime: "nodejs18.x",
|
|
265
|
+
/**
|
|
266
|
+
* https://docs.aws.amazon.com/general/latest/gr/appsync.html
|
|
267
|
+
* Request execution time for mutations, queries, and subscriptions: 30 seconds
|
|
268
|
+
*/
|
|
269
|
+
Timeout: 29
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
[AppSyncLambdaFunctionAppSyncDataSourceLogicalId]: {
|
|
273
|
+
Type: "AWS::AppSync::DataSource",
|
|
274
|
+
Properties: {
|
|
275
|
+
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
276
|
+
LambdaConfig: {
|
|
277
|
+
LambdaFunctionArn: {
|
|
278
|
+
"Fn::GetAtt": [AppSyncLambdaFunctionLogicalId, "Arn"]
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
Name: "AppSyncLambdaFunctionAppSyncDataSource",
|
|
282
|
+
ServiceRoleArn: dataSource.roleArn,
|
|
283
|
+
Type: "AWS_LAMBDA"
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
Outputs: {
|
|
288
|
+
AppSyncApiGraphQLUrl: {
|
|
289
|
+
Export: {
|
|
290
|
+
Name: {
|
|
291
|
+
"Fn::Join": [
|
|
292
|
+
":",
|
|
293
|
+
[{ Ref: "AWS::StackName" }, "AppSyncApiGraphQLUrl"]
|
|
294
|
+
]
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
Value: {
|
|
298
|
+
"Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "GraphQLUrl"]
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
AppSyncApiArn: {
|
|
302
|
+
Export: {
|
|
303
|
+
Name: {
|
|
304
|
+
"Fn::Join": [":", [{ Ref: "AWS::StackName" }, "AppSyncApiArn"]]
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
Value: {
|
|
308
|
+
"Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "Arn"]
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
resolveMethodsEntries.forEach(({ fieldName, typeName }) => {
|
|
314
|
+
template.Resources[`${fieldName}${typeName}AppSyncResolver`] = {
|
|
315
|
+
Type: "AWS::AppSync::Resolver",
|
|
316
|
+
DependsOn: AppSyncGraphQLSchemaLogicalId,
|
|
317
|
+
Properties: {
|
|
318
|
+
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
319
|
+
FieldName: fieldName,
|
|
320
|
+
TypeName: typeName,
|
|
321
|
+
DataSourceName: {
|
|
322
|
+
"Fn::GetAtt": [
|
|
323
|
+
AppSyncLambdaFunctionAppSyncDataSourceLogicalId,
|
|
324
|
+
"Name"
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
});
|
|
330
|
+
const apiKey = additionalAuthenticationProviders?.includes("API_KEY") || authenticationType === "API_KEY";
|
|
331
|
+
const cognitoUserPoolAuth = additionalAuthenticationProviders?.includes("AMAZON_COGNITO_USER_POOLS") || authenticationType === "AMAZON_COGNITO_USER_POOLS";
|
|
332
|
+
if (additionalAuthenticationProviders) {
|
|
333
|
+
template.Resources[AppSyncGraphQLApiLogicalId].Properties.AdditionalAuthenticationProviders = additionalAuthenticationProviders?.map((provider) => {
|
|
334
|
+
return {
|
|
335
|
+
AuthenticationType: provider
|
|
336
|
+
};
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
if (apiKey) {
|
|
340
|
+
template.Resources[AppSyncGraphQLApiKeyLogicalId] = {
|
|
341
|
+
Type: "AWS::AppSync::ApiKey",
|
|
342
|
+
Properties: {
|
|
343
|
+
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] }
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
if (!template.Outputs) {
|
|
347
|
+
template.Outputs = {};
|
|
348
|
+
}
|
|
349
|
+
template.Outputs[AppSyncGraphQLApiKeyLogicalId] = {
|
|
350
|
+
Value: {
|
|
351
|
+
"Fn::GetAtt": [AppSyncGraphQLApiKeyLogicalId, "ApiKey"]
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
if (cognitoUserPoolAuth) {
|
|
356
|
+
if (!userPoolConfig) {
|
|
357
|
+
throw new Error(
|
|
358
|
+
"userPoolConfig is required when using AMAZON_COGNITO_USER_POOLS authentication."
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
template.Resources[AppSyncGraphQLApiLogicalId].Properties.UserPoolConfig = {
|
|
362
|
+
AppIdClientRegex: userPoolConfig.appIdClientRegex,
|
|
363
|
+
AwsRegion: userPoolConfig.awsRegion,
|
|
364
|
+
DefaultAction: userPoolConfig.defaultAction,
|
|
365
|
+
UserPoolId: userPoolConfig.userPoolId
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
if (lambdaFunction.environment?.variables) {
|
|
369
|
+
template.Resources[AppSyncLambdaFunctionLogicalId].Properties.Environment = {
|
|
370
|
+
Variables: lambdaFunction.environment.variables
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
return template;
|
|
374
|
+
};
|
|
5
375
|
|
|
6
376
|
// src/createAppSyncResolverHandler.ts
|
|
7
377
|
var createAppSyncResolverHandler = ({
|
|
@@ -10,7 +380,8 @@ var createAppSyncResolverHandler = ({
|
|
|
10
380
|
return async (event, context) => {
|
|
11
381
|
const { info, arguments: args, source } = event;
|
|
12
382
|
const { parentTypeName, fieldName } = info;
|
|
13
|
-
const
|
|
383
|
+
const resolveMethods = schemaComposer2.getResolveMethods();
|
|
384
|
+
const resolver = resolveMethods[parentTypeName][fieldName];
|
|
14
385
|
return resolver(
|
|
15
386
|
source,
|
|
16
387
|
args,
|
package/dist/index.d.ts
CHANGED
|
@@ -3,25 +3,25 @@ import { AppSyncResolverHandler as AppSyncResolverHandler$1 } from 'aws-lambda';
|
|
|
3
3
|
export { AppSyncIdentityCognito } from 'aws-lambda';
|
|
4
4
|
export { default as composeWithConnection } from 'graphql-compose-connection';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
type Parameter = {
|
|
7
7
|
AllowedValues?: string[];
|
|
8
8
|
Default?: string | number;
|
|
9
9
|
Description?: string;
|
|
10
10
|
Type: string;
|
|
11
11
|
NoEcho?: boolean;
|
|
12
|
-
}
|
|
12
|
+
};
|
|
13
13
|
type Parameters = {
|
|
14
14
|
[key: string]: Parameter;
|
|
15
15
|
};
|
|
16
|
-
|
|
16
|
+
type Resource = {
|
|
17
17
|
Type: string;
|
|
18
18
|
DeletionPolicy?: 'Delete' | 'Retain';
|
|
19
19
|
Description?: string;
|
|
20
20
|
DependsOn?: string[] | string;
|
|
21
21
|
Condition?: string;
|
|
22
22
|
Properties: any;
|
|
23
|
-
}
|
|
24
|
-
|
|
23
|
+
};
|
|
24
|
+
type IAMRoleResource = Resource & {
|
|
25
25
|
Type: 'AWS::IAM::Role';
|
|
26
26
|
Properties: {
|
|
27
27
|
AssumeRolePolicyDocument: {
|
|
@@ -50,7 +50,7 @@ interface IAMRoleResource extends Resource {
|
|
|
50
50
|
};
|
|
51
51
|
}[];
|
|
52
52
|
};
|
|
53
|
-
}
|
|
53
|
+
};
|
|
54
54
|
type Resources = {
|
|
55
55
|
[key: string]: IAMRoleResource | Resource;
|
|
56
56
|
};
|
|
@@ -66,6 +66,7 @@ type Outputs = {
|
|
|
66
66
|
};
|
|
67
67
|
type CloudFormationTemplate = {
|
|
68
68
|
AWSTemplateFormatVersion: '2010-09-09';
|
|
69
|
+
Metadata?: any;
|
|
69
70
|
Description?: string;
|
|
70
71
|
Transform?: 'AWS::Serverless-2016-10-31';
|
|
71
72
|
Mappings?: any;
|
package/dist/index.js
CHANGED
|
@@ -119,7 +119,7 @@ var getPackageLambdaLayerStackName = (packageName) => {
|
|
|
119
119
|
// package.json
|
|
120
120
|
var package_default = {
|
|
121
121
|
name: "@ttoss/appsync-api",
|
|
122
|
-
version: "0.8.
|
|
122
|
+
version: "0.8.2",
|
|
123
123
|
description: "A library for building GraphQL APIs for AWS AppSync.",
|
|
124
124
|
license: "UNLICENSED",
|
|
125
125
|
author: "ttoss",
|
|
@@ -152,7 +152,7 @@ var package_default = {
|
|
|
152
152
|
sideEffects: false,
|
|
153
153
|
typings: "dist/index.d.ts",
|
|
154
154
|
dependencies: {
|
|
155
|
-
"@ttoss/cloudformation": "^0.5.
|
|
155
|
+
"@ttoss/cloudformation": "^0.5.2",
|
|
156
156
|
express: "^4.18.2",
|
|
157
157
|
"graphql-compose-connection": "^8.2.1",
|
|
158
158
|
"graphql-helix": "^1.13.0",
|
|
@@ -165,7 +165,7 @@ var package_default = {
|
|
|
165
165
|
devDependencies: {
|
|
166
166
|
"@ttoss/config": "^1.28.1",
|
|
167
167
|
"@types/aws-lambda": "^8.10.110",
|
|
168
|
-
carlin: "^1.23.
|
|
168
|
+
carlin: "^1.23.3",
|
|
169
169
|
graphql: "^16.6.0",
|
|
170
170
|
"graphql-compose": "^9.0.10"
|
|
171
171
|
},
|
|
@@ -204,23 +204,30 @@ var createApiTemplate = ({
|
|
|
204
204
|
lambdaFunction,
|
|
205
205
|
userPoolConfig
|
|
206
206
|
}) => {
|
|
207
|
-
const
|
|
207
|
+
const sdlWithoutComments = schemaComposer2.toSDL({
|
|
208
208
|
commentDescriptions: false,
|
|
209
209
|
omitDescriptions: true,
|
|
210
210
|
omitScalars: true
|
|
211
211
|
});
|
|
212
|
+
const sdlWithComments = schemaComposer2.toSDL({
|
|
213
|
+
omitScalars: true
|
|
214
|
+
});
|
|
212
215
|
import_graphql_compose.graphql.validateSchema(schemaComposer2.buildSchema());
|
|
213
216
|
const resolveMethods = schemaComposer2.getResolveMethods();
|
|
214
|
-
const resolveMethodsEntries = Object.entries(resolveMethods).flatMap(
|
|
215
|
-
([
|
|
216
|
-
|
|
217
|
-
return
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
217
|
+
const resolveMethodsEntries = Object.entries(resolveMethods).flatMap(([typeName, fieldResolvers]) => {
|
|
218
|
+
return Object.entries(fieldResolvers).map(([fieldName, resolver]) => {
|
|
219
|
+
if (typeof resolver !== "function") {
|
|
220
|
+
return void 0;
|
|
221
|
+
}
|
|
222
|
+
if (typeName.toLowerCase().includes("enum")) {
|
|
223
|
+
return void 0;
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
fieldName,
|
|
227
|
+
typeName
|
|
228
|
+
};
|
|
229
|
+
});
|
|
230
|
+
}).filter(Boolean);
|
|
224
231
|
const getGraphQLComposeDependenciesLambdaLayers = () => {
|
|
225
232
|
const { peerDependencies } = package_default;
|
|
226
233
|
const lambdaLayerStackNames = Object.entries(peerDependencies).map(
|
|
@@ -238,6 +245,14 @@ var createApiTemplate = ({
|
|
|
238
245
|
};
|
|
239
246
|
const template = {
|
|
240
247
|
AWSTemplateFormatVersion: "2010-09-09",
|
|
248
|
+
/**
|
|
249
|
+
* This is a workaround to use with build script.
|
|
250
|
+
*/
|
|
251
|
+
Metadata: {
|
|
252
|
+
Schema: {
|
|
253
|
+
Definition: sdlWithComments
|
|
254
|
+
}
|
|
255
|
+
},
|
|
241
256
|
Parameters: {
|
|
242
257
|
Environment: {
|
|
243
258
|
Default: "Staging",
|
|
@@ -271,7 +286,7 @@ var createApiTemplate = ({
|
|
|
271
286
|
Type: "AWS::AppSync::GraphQLSchema",
|
|
272
287
|
Properties: {
|
|
273
288
|
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
274
|
-
Definition:
|
|
289
|
+
Definition: sdlWithoutComments
|
|
275
290
|
}
|
|
276
291
|
},
|
|
277
292
|
[AppSyncLambdaFunctionLogicalId]: {
|
|
@@ -405,7 +420,8 @@ var createAppSyncResolverHandler = ({
|
|
|
405
420
|
return async (event, context) => {
|
|
406
421
|
const { info, arguments: args, source } = event;
|
|
407
422
|
const { parentTypeName, fieldName } = info;
|
|
408
|
-
const
|
|
423
|
+
const resolveMethods = schemaComposer2.getResolveMethods();
|
|
424
|
+
const resolver = resolveMethods[parentTypeName][fieldName];
|
|
409
425
|
return resolver(
|
|
410
426
|
source,
|
|
411
427
|
args,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/appsync-api",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "A library for building GraphQL APIs for AWS AppSync.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "ttoss",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"sideEffects": false,
|
|
34
34
|
"typings": "dist/index.d.ts",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@ttoss/cloudformation": "^0.5.
|
|
36
|
+
"@ttoss/cloudformation": "^0.5.2",
|
|
37
37
|
"express": "^4.18.2",
|
|
38
38
|
"graphql-compose-connection": "^8.2.1",
|
|
39
39
|
"graphql-helix": "^1.13.0",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@ttoss/config": "^1.28.1",
|
|
48
48
|
"@types/aws-lambda": "^8.10.110",
|
|
49
|
-
"carlin": "^1.23.
|
|
49
|
+
"carlin": "^1.23.3",
|
|
50
50
|
"graphql": "^16.6.0",
|
|
51
51
|
"graphql-compose": "^9.0.10"
|
|
52
52
|
},
|
|
@@ -69,5 +69,5 @@
|
|
|
69
69
|
]
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "01f9bfea6d10cb472b5bf024e3bbacb6fd7cd25c"
|
|
73
73
|
}
|
package/src/cli.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
|
-
import { AppSyncGraphQLSchemaLogicalId } from './createApiTemplate';
|
|
3
2
|
import { findAndReadCloudFormationTemplate } from '@ttoss/cloudformation';
|
|
4
3
|
import minimist from 'minimist';
|
|
5
4
|
|
|
@@ -8,8 +7,7 @@ const argv = minimist(process.argv.slice(2));
|
|
|
8
7
|
if (argv._.includes('build-schema')) {
|
|
9
8
|
const template = findAndReadCloudFormationTemplate({});
|
|
10
9
|
|
|
11
|
-
const sdl =
|
|
12
|
-
template.Resources[AppSyncGraphQLSchemaLogicalId].Properties.Definition;
|
|
10
|
+
const sdl = template.Metadata.Schema.Definition;
|
|
13
11
|
|
|
14
12
|
/**
|
|
15
13
|
* Save to schema/schema.graphql. schema folder might not exist.
|
package/src/createApiTemplate.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { type SchemaComposer, graphql } from 'graphql-compose';
|
|
2
2
|
import { getPackageLambdaLayerStackName } from 'carlin/src/deploy/lambdaLayer/getPackageLambdaLayerStackName';
|
|
3
3
|
import packageJson from '../package.json';
|
|
4
|
+
|
|
4
5
|
/**
|
|
5
6
|
* Absolute path to avoid:
|
|
6
7
|
* The inferred type of 'template' cannot be named without a reference to
|
|
7
8
|
* '@ttoss/appsync-api/node_modules/@ttoss/cloudformation'. This is likely not
|
|
8
9
|
* portable. A type annotation is necessary.ts(2742)
|
|
9
10
|
*/
|
|
10
|
-
import type { CloudFormationTemplate } from '../../cloudformation/src';
|
|
11
|
+
import type { CloudFormationTemplate } from '../../cloudformation/src/';
|
|
11
12
|
|
|
12
13
|
export const AppSyncGraphQLApiLogicalId = 'AppSyncGraphQLApi';
|
|
13
14
|
|
|
@@ -59,12 +60,16 @@ export const createApiTemplate = ({
|
|
|
59
60
|
* It should be on top of the file, otherwise it will have empty Mutation
|
|
60
61
|
* or Subscription if there are no resolvers for them.
|
|
61
62
|
*/
|
|
62
|
-
const
|
|
63
|
+
const sdlWithoutComments = schemaComposer.toSDL({
|
|
63
64
|
commentDescriptions: false,
|
|
64
65
|
omitDescriptions: true,
|
|
65
66
|
omitScalars: true,
|
|
66
67
|
});
|
|
67
68
|
|
|
69
|
+
const sdlWithComments = schemaComposer.toSDL({
|
|
70
|
+
omitScalars: true,
|
|
71
|
+
});
|
|
72
|
+
|
|
68
73
|
graphql.validateSchema(schemaComposer.buildSchema());
|
|
69
74
|
|
|
70
75
|
/**
|
|
@@ -73,16 +78,24 @@ export const createApiTemplate = ({
|
|
|
73
78
|
*/
|
|
74
79
|
const resolveMethods = schemaComposer.getResolveMethods();
|
|
75
80
|
|
|
76
|
-
const resolveMethodsEntries = Object.entries(resolveMethods)
|
|
77
|
-
([typeName, fieldResolvers]) => {
|
|
78
|
-
return Object.entries(fieldResolvers).map(([fieldName]) => {
|
|
81
|
+
const resolveMethodsEntries = Object.entries(resolveMethods)
|
|
82
|
+
.flatMap(([typeName, fieldResolvers]) => {
|
|
83
|
+
return Object.entries(fieldResolvers).map(([fieldName, resolver]) => {
|
|
84
|
+
if (typeof resolver !== 'function') {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (typeName.toLowerCase().includes('enum')) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
|
|
79
92
|
return {
|
|
80
93
|
fieldName,
|
|
81
94
|
typeName,
|
|
82
95
|
};
|
|
83
96
|
});
|
|
84
|
-
}
|
|
85
|
-
|
|
97
|
+
})
|
|
98
|
+
.filter(Boolean) as Array<{ fieldName: string; typeName: string }>;
|
|
86
99
|
|
|
87
100
|
const getGraphQLComposeDependenciesLambdaLayers = () => {
|
|
88
101
|
const { peerDependencies } = packageJson;
|
|
@@ -104,6 +117,14 @@ export const createApiTemplate = ({
|
|
|
104
117
|
|
|
105
118
|
const template: CloudFormationTemplate = {
|
|
106
119
|
AWSTemplateFormatVersion: '2010-09-09',
|
|
120
|
+
/**
|
|
121
|
+
* This is a workaround to use with build script.
|
|
122
|
+
*/
|
|
123
|
+
Metadata: {
|
|
124
|
+
Schema: {
|
|
125
|
+
Definition: sdlWithComments,
|
|
126
|
+
},
|
|
127
|
+
},
|
|
107
128
|
Parameters: {
|
|
108
129
|
Environment: {
|
|
109
130
|
Default: 'Staging',
|
|
@@ -137,7 +158,7 @@ export const createApiTemplate = ({
|
|
|
137
158
|
Type: 'AWS::AppSync::GraphQLSchema',
|
|
138
159
|
Properties: {
|
|
139
160
|
ApiId: { 'Fn::GetAtt': [AppSyncGraphQLApiLogicalId, 'ApiId'] },
|
|
140
|
-
Definition:
|
|
161
|
+
Definition: sdlWithoutComments,
|
|
141
162
|
},
|
|
142
163
|
},
|
|
143
164
|
[AppSyncLambdaFunctionLogicalId]: {
|
|
@@ -15,9 +15,8 @@ export const createAppSyncResolverHandler = ({
|
|
|
15
15
|
return async (event, context) => {
|
|
16
16
|
const { info, arguments: args, source } = event;
|
|
17
17
|
const { parentTypeName, fieldName } = info;
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
)[fieldName];
|
|
18
|
+
const resolveMethods = schemaComposer.getResolveMethods();
|
|
19
|
+
const resolver = (resolveMethods[parentTypeName] as any)[fieldName];
|
|
21
20
|
return resolver(
|
|
22
21
|
source,
|
|
23
22
|
args,
|
|
@@ -1,364 +0,0 @@
|
|
|
1
|
-
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
|
-
|
|
3
|
-
// src/createApiTemplate.ts
|
|
4
|
-
import { graphql } from "graphql-compose";
|
|
5
|
-
|
|
6
|
-
// ../../node_modules/tslib/tslib.es6.js
|
|
7
|
-
var __assign = function() {
|
|
8
|
-
__assign = Object.assign || function __assign2(t) {
|
|
9
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
10
|
-
s = arguments[i];
|
|
11
|
-
for (var p in s)
|
|
12
|
-
if (Object.prototype.hasOwnProperty.call(s, p))
|
|
13
|
-
t[p] = s[p];
|
|
14
|
-
}
|
|
15
|
-
return t;
|
|
16
|
-
};
|
|
17
|
-
return __assign.apply(this, arguments);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
// ../../node_modules/lower-case/dist.es2015/index.js
|
|
21
|
-
function lowerCase(str) {
|
|
22
|
-
return str.toLowerCase();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// ../../node_modules/no-case/dist.es2015/index.js
|
|
26
|
-
var DEFAULT_SPLIT_REGEXP = [/([a-z0-9])([A-Z])/g, /([A-Z])([A-Z][a-z])/g];
|
|
27
|
-
var DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;
|
|
28
|
-
function noCase(input, options) {
|
|
29
|
-
if (options === void 0) {
|
|
30
|
-
options = {};
|
|
31
|
-
}
|
|
32
|
-
var _a = options.splitRegexp, splitRegexp = _a === void 0 ? DEFAULT_SPLIT_REGEXP : _a, _b = options.stripRegexp, stripRegexp = _b === void 0 ? DEFAULT_STRIP_REGEXP : _b, _c = options.transform, transform = _c === void 0 ? lowerCase : _c, _d = options.delimiter, delimiter = _d === void 0 ? " " : _d;
|
|
33
|
-
var result = replace(replace(input, splitRegexp, "$1\0$2"), stripRegexp, "\0");
|
|
34
|
-
var start = 0;
|
|
35
|
-
var end = result.length;
|
|
36
|
-
while (result.charAt(start) === "\0")
|
|
37
|
-
start++;
|
|
38
|
-
while (result.charAt(end - 1) === "\0")
|
|
39
|
-
end--;
|
|
40
|
-
return result.slice(start, end).split("\0").map(transform).join(delimiter);
|
|
41
|
-
}
|
|
42
|
-
function replace(input, re, value) {
|
|
43
|
-
if (re instanceof RegExp)
|
|
44
|
-
return input.replace(re, value);
|
|
45
|
-
return re.reduce(function(input2, re2) {
|
|
46
|
-
return input2.replace(re2, value);
|
|
47
|
-
}, input);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// ../../node_modules/pascal-case/dist.es2015/index.js
|
|
51
|
-
function pascalCaseTransform(input, index) {
|
|
52
|
-
var firstChar = input.charAt(0);
|
|
53
|
-
var lowerChars = input.substr(1).toLowerCase();
|
|
54
|
-
if (index > 0 && firstChar >= "0" && firstChar <= "9") {
|
|
55
|
-
return "_" + firstChar + lowerChars;
|
|
56
|
-
}
|
|
57
|
-
return "" + firstChar.toUpperCase() + lowerChars;
|
|
58
|
-
}
|
|
59
|
-
function pascalCase(input, options) {
|
|
60
|
-
if (options === void 0) {
|
|
61
|
-
options = {};
|
|
62
|
-
}
|
|
63
|
-
return noCase(input, __assign({ delimiter: "", transform: pascalCaseTransform }, options));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ../carlin/src/deploy/lambdaLayer/getPackageLambdaLayerStackName.ts
|
|
67
|
-
var lambdaLayerStackNamePrefix = `LambdaLayer`;
|
|
68
|
-
var getPackageLambdaLayerStackName = (packageName) => {
|
|
69
|
-
const [scopedName, version] = packageName.split("@").filter((part) => {
|
|
70
|
-
return !!part;
|
|
71
|
-
});
|
|
72
|
-
return [
|
|
73
|
-
lambdaLayerStackNamePrefix,
|
|
74
|
-
pascalCase(scopedName),
|
|
75
|
-
version.replace(/[^0-9.]/g, "").replace(/\./g, "-")
|
|
76
|
-
].join("-");
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// package.json
|
|
80
|
-
var package_default = {
|
|
81
|
-
name: "@ttoss/appsync-api",
|
|
82
|
-
version: "0.8.1",
|
|
83
|
-
description: "A library for building GraphQL APIs for AWS AppSync.",
|
|
84
|
-
license: "UNLICENSED",
|
|
85
|
-
author: "ttoss",
|
|
86
|
-
contributors: [
|
|
87
|
-
"Pedro Arantes <pedro@arantespp.com> (https://arantespp.com)"
|
|
88
|
-
],
|
|
89
|
-
exports: {
|
|
90
|
-
".": {
|
|
91
|
-
import: "./dist/esm/index.js",
|
|
92
|
-
require: "./dist/index.js"
|
|
93
|
-
},
|
|
94
|
-
"./server": {
|
|
95
|
-
import: "./dist/esm/server.js",
|
|
96
|
-
require: "./dist/server.js"
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
main: "dist/index.js",
|
|
100
|
-
module: "dist/esm/index.js",
|
|
101
|
-
bin: {
|
|
102
|
-
"ttoss-appsync-api": "./bin/cli.js"
|
|
103
|
-
},
|
|
104
|
-
files: [
|
|
105
|
-
"dist",
|
|
106
|
-
"src"
|
|
107
|
-
],
|
|
108
|
-
scripts: {
|
|
109
|
-
build: "tsup",
|
|
110
|
-
test: "jest"
|
|
111
|
-
},
|
|
112
|
-
sideEffects: false,
|
|
113
|
-
typings: "dist/index.d.ts",
|
|
114
|
-
dependencies: {
|
|
115
|
-
"@ttoss/cloudformation": "^0.5.1",
|
|
116
|
-
express: "^4.18.2",
|
|
117
|
-
"graphql-compose-connection": "^8.2.1",
|
|
118
|
-
"graphql-helix": "^1.13.0",
|
|
119
|
-
minimist: "^1.2.8"
|
|
120
|
-
},
|
|
121
|
-
peerDependencies: {
|
|
122
|
-
graphql: "^16.6.0",
|
|
123
|
-
"graphql-compose": "^9.0.10"
|
|
124
|
-
},
|
|
125
|
-
devDependencies: {
|
|
126
|
-
"@ttoss/config": "^1.28.1",
|
|
127
|
-
"@types/aws-lambda": "^8.10.110",
|
|
128
|
-
carlin: "^1.23.2",
|
|
129
|
-
graphql: "^16.6.0",
|
|
130
|
-
"graphql-compose": "^9.0.10"
|
|
131
|
-
},
|
|
132
|
-
keywords: [
|
|
133
|
-
"api",
|
|
134
|
-
"appsync",
|
|
135
|
-
"aws",
|
|
136
|
-
"graphql"
|
|
137
|
-
],
|
|
138
|
-
publishConfig: {
|
|
139
|
-
access: "public"
|
|
140
|
-
},
|
|
141
|
-
typesVersions: {
|
|
142
|
-
"*": {
|
|
143
|
-
".": [
|
|
144
|
-
"./dist/index.d.ts"
|
|
145
|
-
],
|
|
146
|
-
server: [
|
|
147
|
-
"./dist/server.d.ts"
|
|
148
|
-
]
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
// src/createApiTemplate.ts
|
|
154
|
-
var AppSyncGraphQLApiLogicalId = "AppSyncGraphQLApi";
|
|
155
|
-
var AppSyncGraphQLSchemaLogicalId = "AppSyncGraphQLSchema";
|
|
156
|
-
var AppSyncLambdaFunctionLogicalId = "AppSyncLambdaFunction";
|
|
157
|
-
var AppSyncLambdaFunctionAppSyncDataSourceLogicalId = "AppSyncLambdaFunctionAppSyncDataSource";
|
|
158
|
-
var AppSyncGraphQLApiKeyLogicalId = "AppSyncGraphQLApiKey";
|
|
159
|
-
var createApiTemplate = ({
|
|
160
|
-
additionalAuthenticationProviders,
|
|
161
|
-
authenticationType = "AMAZON_COGNITO_USER_POOLS",
|
|
162
|
-
schemaComposer,
|
|
163
|
-
dataSource,
|
|
164
|
-
lambdaFunction,
|
|
165
|
-
userPoolConfig
|
|
166
|
-
}) => {
|
|
167
|
-
const sdl = schemaComposer.toSDL({
|
|
168
|
-
commentDescriptions: false,
|
|
169
|
-
omitDescriptions: true,
|
|
170
|
-
omitScalars: true
|
|
171
|
-
});
|
|
172
|
-
graphql.validateSchema(schemaComposer.buildSchema());
|
|
173
|
-
const resolveMethods = schemaComposer.getResolveMethods();
|
|
174
|
-
const resolveMethodsEntries = Object.entries(resolveMethods).flatMap(
|
|
175
|
-
([typeName, fieldResolvers]) => {
|
|
176
|
-
return Object.entries(fieldResolvers).map(([fieldName]) => {
|
|
177
|
-
return {
|
|
178
|
-
fieldName,
|
|
179
|
-
typeName
|
|
180
|
-
};
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
);
|
|
184
|
-
const getGraphQLComposeDependenciesLambdaLayers = () => {
|
|
185
|
-
const { peerDependencies } = package_default;
|
|
186
|
-
const lambdaLayerStackNames = Object.entries(peerDependencies).map(
|
|
187
|
-
([dependencyName, dependencyVersion]) => {
|
|
188
|
-
return getPackageLambdaLayerStackName(
|
|
189
|
-
[dependencyName, dependencyVersion].join("@")
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
);
|
|
193
|
-
return lambdaLayerStackNames.map((lambdaLayerStackName) => {
|
|
194
|
-
return {
|
|
195
|
-
"Fn::ImportValue": lambdaLayerStackName
|
|
196
|
-
};
|
|
197
|
-
});
|
|
198
|
-
};
|
|
199
|
-
const template = {
|
|
200
|
-
AWSTemplateFormatVersion: "2010-09-09",
|
|
201
|
-
Parameters: {
|
|
202
|
-
Environment: {
|
|
203
|
-
Default: "Staging",
|
|
204
|
-
Type: "String",
|
|
205
|
-
AllowedValues: ["Staging", "Production"]
|
|
206
|
-
},
|
|
207
|
-
LambdaS3Bucket: {
|
|
208
|
-
Type: "String"
|
|
209
|
-
},
|
|
210
|
-
LambdaS3Key: {
|
|
211
|
-
Type: "String"
|
|
212
|
-
},
|
|
213
|
-
LambdaS3ObjectVersion: {
|
|
214
|
-
Type: "String"
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
Resources: {
|
|
218
|
-
[AppSyncGraphQLApiLogicalId]: {
|
|
219
|
-
Type: "AWS::AppSync::GraphQLApi",
|
|
220
|
-
Properties: {
|
|
221
|
-
AuthenticationType: authenticationType,
|
|
222
|
-
Name: {
|
|
223
|
-
"Fn::Join": [
|
|
224
|
-
":",
|
|
225
|
-
[{ Ref: "AWS::StackName" }, AppSyncGraphQLApiLogicalId]
|
|
226
|
-
]
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
},
|
|
230
|
-
[AppSyncGraphQLSchemaLogicalId]: {
|
|
231
|
-
Type: "AWS::AppSync::GraphQLSchema",
|
|
232
|
-
Properties: {
|
|
233
|
-
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
234
|
-
Definition: sdl
|
|
235
|
-
}
|
|
236
|
-
},
|
|
237
|
-
[AppSyncLambdaFunctionLogicalId]: {
|
|
238
|
-
Type: "AWS::Lambda::Function",
|
|
239
|
-
Properties: {
|
|
240
|
-
Code: {
|
|
241
|
-
S3Bucket: { Ref: "LambdaS3Bucket" },
|
|
242
|
-
S3Key: { Ref: "LambdaS3Key" },
|
|
243
|
-
S3ObjectVersion: { Ref: "LambdaS3ObjectVersion" }
|
|
244
|
-
},
|
|
245
|
-
Handler: "index.handler",
|
|
246
|
-
Layers: getGraphQLComposeDependenciesLambdaLayers(),
|
|
247
|
-
MemorySize: 512,
|
|
248
|
-
Role: lambdaFunction.roleArn,
|
|
249
|
-
Runtime: "nodejs18.x",
|
|
250
|
-
/**
|
|
251
|
-
* https://docs.aws.amazon.com/general/latest/gr/appsync.html
|
|
252
|
-
* Request execution time for mutations, queries, and subscriptions: 30 seconds
|
|
253
|
-
*/
|
|
254
|
-
Timeout: 29
|
|
255
|
-
}
|
|
256
|
-
},
|
|
257
|
-
[AppSyncLambdaFunctionAppSyncDataSourceLogicalId]: {
|
|
258
|
-
Type: "AWS::AppSync::DataSource",
|
|
259
|
-
Properties: {
|
|
260
|
-
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
261
|
-
LambdaConfig: {
|
|
262
|
-
LambdaFunctionArn: {
|
|
263
|
-
"Fn::GetAtt": [AppSyncLambdaFunctionLogicalId, "Arn"]
|
|
264
|
-
}
|
|
265
|
-
},
|
|
266
|
-
Name: "AppSyncLambdaFunctionAppSyncDataSource",
|
|
267
|
-
ServiceRoleArn: dataSource.roleArn,
|
|
268
|
-
Type: "AWS_LAMBDA"
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
Outputs: {
|
|
273
|
-
AppSyncApiGraphQLUrl: {
|
|
274
|
-
Export: {
|
|
275
|
-
Name: {
|
|
276
|
-
"Fn::Join": [
|
|
277
|
-
":",
|
|
278
|
-
[{ Ref: "AWS::StackName" }, "AppSyncApiGraphQLUrl"]
|
|
279
|
-
]
|
|
280
|
-
}
|
|
281
|
-
},
|
|
282
|
-
Value: {
|
|
283
|
-
"Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "GraphQLUrl"]
|
|
284
|
-
}
|
|
285
|
-
},
|
|
286
|
-
AppSyncApiArn: {
|
|
287
|
-
Export: {
|
|
288
|
-
Name: {
|
|
289
|
-
"Fn::Join": [":", [{ Ref: "AWS::StackName" }, "AppSyncApiArn"]]
|
|
290
|
-
}
|
|
291
|
-
},
|
|
292
|
-
Value: {
|
|
293
|
-
"Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "Arn"]
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
|
-
resolveMethodsEntries.forEach(({ fieldName, typeName }) => {
|
|
299
|
-
template.Resources[`${fieldName}${typeName}AppSyncResolver`] = {
|
|
300
|
-
Type: "AWS::AppSync::Resolver",
|
|
301
|
-
DependsOn: AppSyncGraphQLSchemaLogicalId,
|
|
302
|
-
Properties: {
|
|
303
|
-
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
304
|
-
FieldName: fieldName,
|
|
305
|
-
TypeName: typeName,
|
|
306
|
-
DataSourceName: {
|
|
307
|
-
"Fn::GetAtt": [
|
|
308
|
-
AppSyncLambdaFunctionAppSyncDataSourceLogicalId,
|
|
309
|
-
"Name"
|
|
310
|
-
]
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
});
|
|
315
|
-
const apiKey = additionalAuthenticationProviders?.includes("API_KEY") || authenticationType === "API_KEY";
|
|
316
|
-
const cognitoUserPoolAuth = additionalAuthenticationProviders?.includes("AMAZON_COGNITO_USER_POOLS") || authenticationType === "AMAZON_COGNITO_USER_POOLS";
|
|
317
|
-
if (additionalAuthenticationProviders) {
|
|
318
|
-
template.Resources[AppSyncGraphQLApiLogicalId].Properties.AdditionalAuthenticationProviders = additionalAuthenticationProviders?.map((provider) => {
|
|
319
|
-
return {
|
|
320
|
-
AuthenticationType: provider
|
|
321
|
-
};
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
if (apiKey) {
|
|
325
|
-
template.Resources[AppSyncGraphQLApiKeyLogicalId] = {
|
|
326
|
-
Type: "AWS::AppSync::ApiKey",
|
|
327
|
-
Properties: {
|
|
328
|
-
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] }
|
|
329
|
-
}
|
|
330
|
-
};
|
|
331
|
-
if (!template.Outputs) {
|
|
332
|
-
template.Outputs = {};
|
|
333
|
-
}
|
|
334
|
-
template.Outputs[AppSyncGraphQLApiKeyLogicalId] = {
|
|
335
|
-
Value: {
|
|
336
|
-
"Fn::GetAtt": [AppSyncGraphQLApiKeyLogicalId, "ApiKey"]
|
|
337
|
-
}
|
|
338
|
-
};
|
|
339
|
-
}
|
|
340
|
-
if (cognitoUserPoolAuth) {
|
|
341
|
-
if (!userPoolConfig) {
|
|
342
|
-
throw new Error(
|
|
343
|
-
"userPoolConfig is required when using AMAZON_COGNITO_USER_POOLS authentication."
|
|
344
|
-
);
|
|
345
|
-
}
|
|
346
|
-
template.Resources[AppSyncGraphQLApiLogicalId].Properties.UserPoolConfig = {
|
|
347
|
-
AppIdClientRegex: userPoolConfig.appIdClientRegex,
|
|
348
|
-
AwsRegion: userPoolConfig.awsRegion,
|
|
349
|
-
DefaultAction: userPoolConfig.defaultAction,
|
|
350
|
-
UserPoolId: userPoolConfig.userPoolId
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
if (lambdaFunction.environment?.variables) {
|
|
354
|
-
template.Resources[AppSyncLambdaFunctionLogicalId].Properties.Environment = {
|
|
355
|
-
Variables: lambdaFunction.environment.variables
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
return template;
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
export {
|
|
362
|
-
AppSyncGraphQLSchemaLogicalId,
|
|
363
|
-
createApiTemplate
|
|
364
|
-
};
|