@ttoss/appsync-api 0.8.0 → 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 +73 -1
- package/dist/index.js +36 -16
- package/package.json +4 -4
- package/src/cli.ts +1 -3
- package/src/createApiTemplate.ts +39 -8
- package/src/createAppSyncResolverHandler.ts +2 -3
- package/dist/esm/chunk-Y27A2LBZ.js +0 -360
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-Y27A2LBZ.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
|
@@ -1,9 +1,81 @@
|
|
|
1
1
|
import { SchemaComposer, ObjectTypeComposer } from 'graphql-compose';
|
|
2
|
-
import { CloudFormationTemplate } from '@ttoss/cloudformation';
|
|
3
2
|
import { AppSyncResolverHandler as AppSyncResolverHandler$1 } from 'aws-lambda';
|
|
4
3
|
export { AppSyncIdentityCognito } from 'aws-lambda';
|
|
5
4
|
export { default as composeWithConnection } from 'graphql-compose-connection';
|
|
6
5
|
|
|
6
|
+
type Parameter = {
|
|
7
|
+
AllowedValues?: string[];
|
|
8
|
+
Default?: string | number;
|
|
9
|
+
Description?: string;
|
|
10
|
+
Type: string;
|
|
11
|
+
NoEcho?: boolean;
|
|
12
|
+
};
|
|
13
|
+
type Parameters = {
|
|
14
|
+
[key: string]: Parameter;
|
|
15
|
+
};
|
|
16
|
+
type Resource = {
|
|
17
|
+
Type: string;
|
|
18
|
+
DeletionPolicy?: 'Delete' | 'Retain';
|
|
19
|
+
Description?: string;
|
|
20
|
+
DependsOn?: string[] | string;
|
|
21
|
+
Condition?: string;
|
|
22
|
+
Properties: any;
|
|
23
|
+
};
|
|
24
|
+
type IAMRoleResource = Resource & {
|
|
25
|
+
Type: 'AWS::IAM::Role';
|
|
26
|
+
Properties: {
|
|
27
|
+
AssumeRolePolicyDocument: {
|
|
28
|
+
Version: '2012-10-17';
|
|
29
|
+
Statement: {
|
|
30
|
+
Effect: 'Allow' | 'Deny';
|
|
31
|
+
Action: string;
|
|
32
|
+
Principal: any;
|
|
33
|
+
}[];
|
|
34
|
+
};
|
|
35
|
+
ManagedPolicyArns?: string[];
|
|
36
|
+
Path?: string;
|
|
37
|
+
Policies?: {
|
|
38
|
+
PolicyName: string;
|
|
39
|
+
PolicyDocument: {
|
|
40
|
+
Version: '2012-10-17';
|
|
41
|
+
Statement: {
|
|
42
|
+
Effect: 'Allow' | 'Deny';
|
|
43
|
+
Action: string | string[];
|
|
44
|
+
Resource: string | string[] | {
|
|
45
|
+
[key: string]: string;
|
|
46
|
+
} | {
|
|
47
|
+
[key: string]: string;
|
|
48
|
+
}[];
|
|
49
|
+
}[];
|
|
50
|
+
};
|
|
51
|
+
}[];
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
type Resources = {
|
|
55
|
+
[key: string]: IAMRoleResource | Resource;
|
|
56
|
+
};
|
|
57
|
+
type Output = {
|
|
58
|
+
Description?: string;
|
|
59
|
+
Value: string | any;
|
|
60
|
+
Export?: {
|
|
61
|
+
Name: string | any;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
type Outputs = {
|
|
65
|
+
[key: string]: Output;
|
|
66
|
+
};
|
|
67
|
+
type CloudFormationTemplate = {
|
|
68
|
+
AWSTemplateFormatVersion: '2010-09-09';
|
|
69
|
+
Metadata?: any;
|
|
70
|
+
Description?: string;
|
|
71
|
+
Transform?: 'AWS::Serverless-2016-10-31';
|
|
72
|
+
Mappings?: any;
|
|
73
|
+
Conditions?: any;
|
|
74
|
+
Parameters?: Parameters;
|
|
75
|
+
Resources: Resources;
|
|
76
|
+
Outputs?: Outputs;
|
|
77
|
+
};
|
|
78
|
+
|
|
7
79
|
type StringOrImport = string | {
|
|
8
80
|
'Fn::ImportValue': string;
|
|
9
81
|
};
|
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,19 +204,30 @@ var createApiTemplate = ({
|
|
|
204
204
|
lambdaFunction,
|
|
205
205
|
userPoolConfig
|
|
206
206
|
}) => {
|
|
207
|
-
const
|
|
207
|
+
const sdlWithoutComments = schemaComposer2.toSDL({
|
|
208
|
+
commentDescriptions: false,
|
|
209
|
+
omitDescriptions: true,
|
|
210
|
+
omitScalars: true
|
|
211
|
+
});
|
|
212
|
+
const sdlWithComments = schemaComposer2.toSDL({
|
|
213
|
+
omitScalars: true
|
|
214
|
+
});
|
|
208
215
|
import_graphql_compose.graphql.validateSchema(schemaComposer2.buildSchema());
|
|
209
216
|
const resolveMethods = schemaComposer2.getResolveMethods();
|
|
210
|
-
const resolveMethodsEntries = Object.entries(resolveMethods).flatMap(
|
|
211
|
-
([
|
|
212
|
-
|
|
213
|
-
return
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
|
|
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);
|
|
220
231
|
const getGraphQLComposeDependenciesLambdaLayers = () => {
|
|
221
232
|
const { peerDependencies } = package_default;
|
|
222
233
|
const lambdaLayerStackNames = Object.entries(peerDependencies).map(
|
|
@@ -234,6 +245,14 @@ var createApiTemplate = ({
|
|
|
234
245
|
};
|
|
235
246
|
const template = {
|
|
236
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
|
+
},
|
|
237
256
|
Parameters: {
|
|
238
257
|
Environment: {
|
|
239
258
|
Default: "Staging",
|
|
@@ -267,7 +286,7 @@ var createApiTemplate = ({
|
|
|
267
286
|
Type: "AWS::AppSync::GraphQLSchema",
|
|
268
287
|
Properties: {
|
|
269
288
|
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
270
|
-
Definition:
|
|
289
|
+
Definition: sdlWithoutComments
|
|
271
290
|
}
|
|
272
291
|
},
|
|
273
292
|
[AppSyncLambdaFunctionLogicalId]: {
|
|
@@ -401,7 +420,8 @@ var createAppSyncResolverHandler = ({
|
|
|
401
420
|
return async (event, context) => {
|
|
402
421
|
const { info, arguments: args, source } = event;
|
|
403
422
|
const { parentTypeName, fieldName } = info;
|
|
404
|
-
const
|
|
423
|
+
const resolveMethods = schemaComposer2.getResolveMethods();
|
|
424
|
+
const resolver = resolveMethods[parentTypeName][fieldName];
|
|
405
425
|
return resolver(
|
|
406
426
|
source,
|
|
407
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,7 +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
|
+
/**
|
|
6
|
+
* Absolute path to avoid:
|
|
7
|
+
* The inferred type of 'template' cannot be named without a reference to
|
|
8
|
+
* '@ttoss/appsync-api/node_modules/@ttoss/cloudformation'. This is likely not
|
|
9
|
+
* portable. A type annotation is necessary.ts(2742)
|
|
10
|
+
*/
|
|
11
|
+
import type { CloudFormationTemplate } from '../../cloudformation/src/';
|
|
5
12
|
|
|
6
13
|
export const AppSyncGraphQLApiLogicalId = 'AppSyncGraphQLApi';
|
|
7
14
|
|
|
@@ -53,7 +60,15 @@ export const createApiTemplate = ({
|
|
|
53
60
|
* It should be on top of the file, otherwise it will have empty Mutation
|
|
54
61
|
* or Subscription if there are no resolvers for them.
|
|
55
62
|
*/
|
|
56
|
-
const
|
|
63
|
+
const sdlWithoutComments = schemaComposer.toSDL({
|
|
64
|
+
commentDescriptions: false,
|
|
65
|
+
omitDescriptions: true,
|
|
66
|
+
omitScalars: true,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const sdlWithComments = schemaComposer.toSDL({
|
|
70
|
+
omitScalars: true,
|
|
71
|
+
});
|
|
57
72
|
|
|
58
73
|
graphql.validateSchema(schemaComposer.buildSchema());
|
|
59
74
|
|
|
@@ -63,16 +78,24 @@ export const createApiTemplate = ({
|
|
|
63
78
|
*/
|
|
64
79
|
const resolveMethods = schemaComposer.getResolveMethods();
|
|
65
80
|
|
|
66
|
-
const resolveMethodsEntries = Object.entries(resolveMethods)
|
|
67
|
-
([typeName, fieldResolvers]) => {
|
|
68
|
-
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
|
+
|
|
69
92
|
return {
|
|
70
93
|
fieldName,
|
|
71
94
|
typeName,
|
|
72
95
|
};
|
|
73
96
|
});
|
|
74
|
-
}
|
|
75
|
-
|
|
97
|
+
})
|
|
98
|
+
.filter(Boolean) as Array<{ fieldName: string; typeName: string }>;
|
|
76
99
|
|
|
77
100
|
const getGraphQLComposeDependenciesLambdaLayers = () => {
|
|
78
101
|
const { peerDependencies } = packageJson;
|
|
@@ -94,6 +117,14 @@ export const createApiTemplate = ({
|
|
|
94
117
|
|
|
95
118
|
const template: CloudFormationTemplate = {
|
|
96
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
|
+
},
|
|
97
128
|
Parameters: {
|
|
98
129
|
Environment: {
|
|
99
130
|
Default: 'Staging',
|
|
@@ -127,7 +158,7 @@ export const createApiTemplate = ({
|
|
|
127
158
|
Type: 'AWS::AppSync::GraphQLSchema',
|
|
128
159
|
Properties: {
|
|
129
160
|
ApiId: { 'Fn::GetAtt': [AppSyncGraphQLApiLogicalId, 'ApiId'] },
|
|
130
|
-
Definition:
|
|
161
|
+
Definition: sdlWithoutComments,
|
|
131
162
|
},
|
|
132
163
|
},
|
|
133
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,360 +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.0",
|
|
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
|
-
graphql.validateSchema(schemaComposer.buildSchema());
|
|
169
|
-
const resolveMethods = schemaComposer.getResolveMethods();
|
|
170
|
-
const resolveMethodsEntries = Object.entries(resolveMethods).flatMap(
|
|
171
|
-
([typeName, fieldResolvers]) => {
|
|
172
|
-
return Object.entries(fieldResolvers).map(([fieldName]) => {
|
|
173
|
-
return {
|
|
174
|
-
fieldName,
|
|
175
|
-
typeName
|
|
176
|
-
};
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
);
|
|
180
|
-
const getGraphQLComposeDependenciesLambdaLayers = () => {
|
|
181
|
-
const { peerDependencies } = package_default;
|
|
182
|
-
const lambdaLayerStackNames = Object.entries(peerDependencies).map(
|
|
183
|
-
([dependencyName, dependencyVersion]) => {
|
|
184
|
-
return getPackageLambdaLayerStackName(
|
|
185
|
-
[dependencyName, dependencyVersion].join("@")
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
);
|
|
189
|
-
return lambdaLayerStackNames.map((lambdaLayerStackName) => {
|
|
190
|
-
return {
|
|
191
|
-
"Fn::ImportValue": lambdaLayerStackName
|
|
192
|
-
};
|
|
193
|
-
});
|
|
194
|
-
};
|
|
195
|
-
const template = {
|
|
196
|
-
AWSTemplateFormatVersion: "2010-09-09",
|
|
197
|
-
Parameters: {
|
|
198
|
-
Environment: {
|
|
199
|
-
Default: "Staging",
|
|
200
|
-
Type: "String",
|
|
201
|
-
AllowedValues: ["Staging", "Production"]
|
|
202
|
-
},
|
|
203
|
-
LambdaS3Bucket: {
|
|
204
|
-
Type: "String"
|
|
205
|
-
},
|
|
206
|
-
LambdaS3Key: {
|
|
207
|
-
Type: "String"
|
|
208
|
-
},
|
|
209
|
-
LambdaS3ObjectVersion: {
|
|
210
|
-
Type: "String"
|
|
211
|
-
}
|
|
212
|
-
},
|
|
213
|
-
Resources: {
|
|
214
|
-
[AppSyncGraphQLApiLogicalId]: {
|
|
215
|
-
Type: "AWS::AppSync::GraphQLApi",
|
|
216
|
-
Properties: {
|
|
217
|
-
AuthenticationType: authenticationType,
|
|
218
|
-
Name: {
|
|
219
|
-
"Fn::Join": [
|
|
220
|
-
":",
|
|
221
|
-
[{ Ref: "AWS::StackName" }, AppSyncGraphQLApiLogicalId]
|
|
222
|
-
]
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
},
|
|
226
|
-
[AppSyncGraphQLSchemaLogicalId]: {
|
|
227
|
-
Type: "AWS::AppSync::GraphQLSchema",
|
|
228
|
-
Properties: {
|
|
229
|
-
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
230
|
-
Definition: sdl
|
|
231
|
-
}
|
|
232
|
-
},
|
|
233
|
-
[AppSyncLambdaFunctionLogicalId]: {
|
|
234
|
-
Type: "AWS::Lambda::Function",
|
|
235
|
-
Properties: {
|
|
236
|
-
Code: {
|
|
237
|
-
S3Bucket: { Ref: "LambdaS3Bucket" },
|
|
238
|
-
S3Key: { Ref: "LambdaS3Key" },
|
|
239
|
-
S3ObjectVersion: { Ref: "LambdaS3ObjectVersion" }
|
|
240
|
-
},
|
|
241
|
-
Handler: "index.handler",
|
|
242
|
-
Layers: getGraphQLComposeDependenciesLambdaLayers(),
|
|
243
|
-
MemorySize: 512,
|
|
244
|
-
Role: lambdaFunction.roleArn,
|
|
245
|
-
Runtime: "nodejs18.x",
|
|
246
|
-
/**
|
|
247
|
-
* https://docs.aws.amazon.com/general/latest/gr/appsync.html
|
|
248
|
-
* Request execution time for mutations, queries, and subscriptions: 30 seconds
|
|
249
|
-
*/
|
|
250
|
-
Timeout: 29
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
[AppSyncLambdaFunctionAppSyncDataSourceLogicalId]: {
|
|
254
|
-
Type: "AWS::AppSync::DataSource",
|
|
255
|
-
Properties: {
|
|
256
|
-
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
257
|
-
LambdaConfig: {
|
|
258
|
-
LambdaFunctionArn: {
|
|
259
|
-
"Fn::GetAtt": [AppSyncLambdaFunctionLogicalId, "Arn"]
|
|
260
|
-
}
|
|
261
|
-
},
|
|
262
|
-
Name: "AppSyncLambdaFunctionAppSyncDataSource",
|
|
263
|
-
ServiceRoleArn: dataSource.roleArn,
|
|
264
|
-
Type: "AWS_LAMBDA"
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
},
|
|
268
|
-
Outputs: {
|
|
269
|
-
AppSyncApiGraphQLUrl: {
|
|
270
|
-
Export: {
|
|
271
|
-
Name: {
|
|
272
|
-
"Fn::Join": [
|
|
273
|
-
":",
|
|
274
|
-
[{ Ref: "AWS::StackName" }, "AppSyncApiGraphQLUrl"]
|
|
275
|
-
]
|
|
276
|
-
}
|
|
277
|
-
},
|
|
278
|
-
Value: {
|
|
279
|
-
"Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "GraphQLUrl"]
|
|
280
|
-
}
|
|
281
|
-
},
|
|
282
|
-
AppSyncApiArn: {
|
|
283
|
-
Export: {
|
|
284
|
-
Name: {
|
|
285
|
-
"Fn::Join": [":", [{ Ref: "AWS::StackName" }, "AppSyncApiArn"]]
|
|
286
|
-
}
|
|
287
|
-
},
|
|
288
|
-
Value: {
|
|
289
|
-
"Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "Arn"]
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
resolveMethodsEntries.forEach(({ fieldName, typeName }) => {
|
|
295
|
-
template.Resources[`${fieldName}${typeName}AppSyncResolver`] = {
|
|
296
|
-
Type: "AWS::AppSync::Resolver",
|
|
297
|
-
DependsOn: AppSyncGraphQLSchemaLogicalId,
|
|
298
|
-
Properties: {
|
|
299
|
-
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] },
|
|
300
|
-
FieldName: fieldName,
|
|
301
|
-
TypeName: typeName,
|
|
302
|
-
DataSourceName: {
|
|
303
|
-
"Fn::GetAtt": [
|
|
304
|
-
AppSyncLambdaFunctionAppSyncDataSourceLogicalId,
|
|
305
|
-
"Name"
|
|
306
|
-
]
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
};
|
|
310
|
-
});
|
|
311
|
-
const apiKey = additionalAuthenticationProviders?.includes("API_KEY") || authenticationType === "API_KEY";
|
|
312
|
-
const cognitoUserPoolAuth = additionalAuthenticationProviders?.includes("AMAZON_COGNITO_USER_POOLS") || authenticationType === "AMAZON_COGNITO_USER_POOLS";
|
|
313
|
-
if (additionalAuthenticationProviders) {
|
|
314
|
-
template.Resources[AppSyncGraphQLApiLogicalId].Properties.AdditionalAuthenticationProviders = additionalAuthenticationProviders?.map((provider) => {
|
|
315
|
-
return {
|
|
316
|
-
AuthenticationType: provider
|
|
317
|
-
};
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
if (apiKey) {
|
|
321
|
-
template.Resources[AppSyncGraphQLApiKeyLogicalId] = {
|
|
322
|
-
Type: "AWS::AppSync::ApiKey",
|
|
323
|
-
Properties: {
|
|
324
|
-
ApiId: { "Fn::GetAtt": [AppSyncGraphQLApiLogicalId, "ApiId"] }
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
if (!template.Outputs) {
|
|
328
|
-
template.Outputs = {};
|
|
329
|
-
}
|
|
330
|
-
template.Outputs[AppSyncGraphQLApiKeyLogicalId] = {
|
|
331
|
-
Value: {
|
|
332
|
-
"Fn::GetAtt": [AppSyncGraphQLApiKeyLogicalId, "ApiKey"]
|
|
333
|
-
}
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
if (cognitoUserPoolAuth) {
|
|
337
|
-
if (!userPoolConfig) {
|
|
338
|
-
throw new Error(
|
|
339
|
-
"userPoolConfig is required when using AMAZON_COGNITO_USER_POOLS authentication."
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
template.Resources[AppSyncGraphQLApiLogicalId].Properties.UserPoolConfig = {
|
|
343
|
-
AppIdClientRegex: userPoolConfig.appIdClientRegex,
|
|
344
|
-
AwsRegion: userPoolConfig.awsRegion,
|
|
345
|
-
DefaultAction: userPoolConfig.defaultAction,
|
|
346
|
-
UserPoolId: userPoolConfig.userPoolId
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
if (lambdaFunction.environment?.variables) {
|
|
350
|
-
template.Resources[AppSyncLambdaFunctionLogicalId].Properties.Environment = {
|
|
351
|
-
Variables: lambdaFunction.environment.variables
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
return template;
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
export {
|
|
358
|
-
AppSyncGraphQLSchemaLogicalId,
|
|
359
|
-
createApiTemplate
|
|
360
|
-
};
|