@ttoss/appsync-api 0.7.4 → 0.8.0
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/README.md +33 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +4 -0
- package/dist/esm/chunk-Y27A2LBZ.js +360 -0
- package/dist/esm/cli.js +1 -2
- package/dist/esm/index.js +162 -5
- package/dist/esm/server.js +0 -1
- package/dist/index.d.ts +20 -2
- package/dist/index.js +195 -485
- package/dist/server.js +4 -0
- package/package.json +7 -6
- package/src/composeWithRelay/composeWithRelay.ts +67 -0
- package/src/composeWithRelay/globalId.ts +32 -0
- package/src/composeWithRelay/index.ts +7 -0
- package/src/composeWithRelay/nodeFieldConfig.ts +82 -0
- package/src/composeWithRelay/nodeInterface.ts +31 -0
- package/src/index.ts +2 -0
- package/dist/esm/chunk-NQOARNEJ.js +0 -27
- package/dist/esm/chunk-Z4Y6MT22.js +0 -815
package/README.md
CHANGED
|
@@ -77,3 +77,36 @@ server.listen(4000, () => {
|
|
|
77
77
|
);
|
|
78
78
|
});
|
|
79
79
|
```
|
|
80
|
+
|
|
81
|
+
## Schema Composer
|
|
82
|
+
|
|
83
|
+
The `schemaComposer` object is a [`graphql-compose`](https://graphql-compose.github.io/docs/intro/quick-start.html) object that defines your API's schema and handle resolvers. You can use `schemaComposer` to create types, queries, mutations, and subscriptions.
|
|
84
|
+
|
|
85
|
+
### Connections
|
|
86
|
+
|
|
87
|
+
This packages provides the method `composeWithConnection` to create a connection type and queries for a given type, based on [graphql-compose-connection](https://graphql-compose.github.io/docs/plugins/plugin-connection.html) plugin and following the [Relay Connection Specification](https://facebook.github.io/relay/graphql/connections.htm).
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { composeWithConnection } from '@ttoss/appsync-api';
|
|
91
|
+
|
|
92
|
+
composeWithConnection(AuthorTC, {
|
|
93
|
+
findManyResolver: AuthorTC.getResolver('findMany'),
|
|
94
|
+
countResolver: AuthorTC.getResolver('count'),
|
|
95
|
+
sort: {
|
|
96
|
+
ASC: {
|
|
97
|
+
value: {
|
|
98
|
+
scanIndexForward: true,
|
|
99
|
+
},
|
|
100
|
+
cursorFields: ['id'],
|
|
101
|
+
beforeCursorQuery: (rawQuery, cursorData, resolveParams) => {
|
|
102
|
+
if (!rawQuery.id) rawQuery.id = {};
|
|
103
|
+
rawQuery.id.$lt = cursorData.id;
|
|
104
|
+
},
|
|
105
|
+
afterCursorQuery: (rawQuery, cursorData, resolveParams) => {
|
|
106
|
+
if (!rawQuery.id) rawQuery.id = {};
|
|
107
|
+
rawQuery.id.$gt = cursorData.id;
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
```
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
15
|
return to;
|
|
16
16
|
};
|
|
17
17
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
18
22
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
19
23
|
mod
|
|
20
24
|
));
|
|
@@ -0,0 +1,360 @@
|
|
|
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
|
+
};
|
package/dist/esm/cli.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
import {
|
|
3
3
|
AppSyncGraphQLSchemaLogicalId
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-NQOARNEJ.js";
|
|
4
|
+
} from "./chunk-Y27A2LBZ.js";
|
|
6
5
|
|
|
7
6
|
// src/cli.ts
|
|
8
7
|
import * as fs from "fs";
|
package/dist/esm/index.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
/** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
|
|
2
2
|
import {
|
|
3
3
|
createApiTemplate
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-NQOARNEJ.js";
|
|
4
|
+
} from "./chunk-Y27A2LBZ.js";
|
|
6
5
|
|
|
7
6
|
// src/createAppSyncResolverHandler.ts
|
|
8
7
|
var createAppSyncResolverHandler = ({
|
|
9
|
-
schemaComposer
|
|
8
|
+
schemaComposer: schemaComposer2
|
|
10
9
|
}) => {
|
|
11
10
|
return async (event, context) => {
|
|
12
11
|
const { info, arguments: args, source } = event;
|
|
13
12
|
const { parentTypeName, fieldName } = info;
|
|
14
|
-
const resolver =
|
|
13
|
+
const resolver = schemaComposer2.getResolveMethods()[parentTypeName][fieldName];
|
|
15
14
|
return resolver(
|
|
16
15
|
source,
|
|
17
16
|
args,
|
|
@@ -20,7 +19,165 @@ var createAppSyncResolverHandler = ({
|
|
|
20
19
|
);
|
|
21
20
|
};
|
|
22
21
|
};
|
|
22
|
+
|
|
23
|
+
// src/composeWithRelay/composeWithRelay.ts
|
|
24
|
+
import { ObjectTypeComposer } from "graphql-compose";
|
|
25
|
+
|
|
26
|
+
// src/composeWithRelay/nodeFieldConfig.ts
|
|
27
|
+
import {
|
|
28
|
+
getProjectionFromAST
|
|
29
|
+
} from "graphql-compose";
|
|
30
|
+
|
|
31
|
+
// src/composeWithRelay/globalId.ts
|
|
32
|
+
var base64 = (i) => {
|
|
33
|
+
return Buffer.from(i, "ascii").toString("base64");
|
|
34
|
+
};
|
|
35
|
+
var unbase64 = (i) => {
|
|
36
|
+
return Buffer.from(i, "base64").toString("ascii");
|
|
37
|
+
};
|
|
38
|
+
var toGlobalId = (type, id) => {
|
|
39
|
+
return base64([type, id].join(":"));
|
|
40
|
+
};
|
|
41
|
+
var fromGlobalId = (globalId) => {
|
|
42
|
+
const unbasedGlobalId = unbase64(globalId);
|
|
43
|
+
const [type, id] = unbasedGlobalId.split(":");
|
|
44
|
+
return { type, id };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/composeWithRelay/nodeFieldConfig.ts
|
|
48
|
+
var getNodeFieldConfig = (typeMapForRelayNode, nodeInterface) => {
|
|
49
|
+
return {
|
|
50
|
+
description: "Fetches an object that has globally unique ID among all types",
|
|
51
|
+
type: nodeInterface,
|
|
52
|
+
args: {
|
|
53
|
+
id: {
|
|
54
|
+
type: "ID!",
|
|
55
|
+
description: "The globally unique ID among all types"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
resolve: (source, args, context, info) => {
|
|
59
|
+
if (!args.id || !(typeof args.id === "string")) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const { type } = fromGlobalId(args.id);
|
|
63
|
+
if (!typeMapForRelayNode[type]) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const { tc, resolver: findById } = typeMapForRelayNode[type];
|
|
67
|
+
if (findById && findById.resolve && tc) {
|
|
68
|
+
const graphqlType = tc.getType();
|
|
69
|
+
let projection;
|
|
70
|
+
if (info) {
|
|
71
|
+
projection = getProjectionFromAST({
|
|
72
|
+
...info,
|
|
73
|
+
returnType: graphqlType
|
|
74
|
+
});
|
|
75
|
+
} else {
|
|
76
|
+
projection = {};
|
|
77
|
+
}
|
|
78
|
+
const idArgName = Object.keys(findById.args)[0];
|
|
79
|
+
return findById.resolve({
|
|
80
|
+
source,
|
|
81
|
+
args: { [idArgName]: args.id },
|
|
82
|
+
// eg. mongoose has _id fieldname, so should map
|
|
83
|
+
context,
|
|
84
|
+
info,
|
|
85
|
+
projection
|
|
86
|
+
}).then((res) => {
|
|
87
|
+
if (!res)
|
|
88
|
+
return res;
|
|
89
|
+
res.__nodeType = graphqlType;
|
|
90
|
+
return res;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// src/composeWithRelay/nodeInterface.ts
|
|
99
|
+
import { InterfaceTypeComposer } from "graphql-compose";
|
|
100
|
+
var NodeTC = InterfaceTypeComposer.createTemp({
|
|
101
|
+
name: "Node",
|
|
102
|
+
description: "An object, that can be fetched by the globally unique ID among all types.",
|
|
103
|
+
fields: {
|
|
104
|
+
id: {
|
|
105
|
+
type: "ID!",
|
|
106
|
+
description: "The globally unique ID among all types."
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
resolveType: (payload) => {
|
|
110
|
+
return payload.__nodeType.name ? payload.__nodeType.name : null;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
var NodeInterface = NodeTC.getType();
|
|
114
|
+
var getNodeInterface = (sc) => {
|
|
115
|
+
if (sc.hasInstance("Node", InterfaceTypeComposer)) {
|
|
116
|
+
return sc.get("Node");
|
|
117
|
+
}
|
|
118
|
+
sc.set("Node", NodeTC);
|
|
119
|
+
return NodeTC;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// src/composeWithRelay/composeWithRelay.ts
|
|
123
|
+
var TypeMapForRelayNode = {};
|
|
124
|
+
var composeWithRelay = (tc) => {
|
|
125
|
+
if (!(tc instanceof ObjectTypeComposer)) {
|
|
126
|
+
throw new Error(
|
|
127
|
+
"You should provide ObjectTypeComposer instance to composeWithRelay method"
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
const nodeInterface = getNodeInterface(tc.schemaComposer);
|
|
131
|
+
const nodeFieldConfig = getNodeFieldConfig(
|
|
132
|
+
TypeMapForRelayNode,
|
|
133
|
+
nodeInterface
|
|
134
|
+
);
|
|
135
|
+
if (tc.getTypeName() === "Query" || tc.getTypeName() === "RootQuery") {
|
|
136
|
+
tc.setField("node", nodeFieldConfig);
|
|
137
|
+
return tc;
|
|
138
|
+
}
|
|
139
|
+
if (tc.getTypeName() === "Mutation" || tc.getTypeName() === "RootMutation") {
|
|
140
|
+
return tc;
|
|
141
|
+
}
|
|
142
|
+
if (!tc.hasRecordIdFn()) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
`ObjectTypeComposer(${tc.getTypeName()}) should have recordIdFn. This function returns ID from provided object.`
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
const findById = tc.getResolver("findById");
|
|
148
|
+
if (!findById) {
|
|
149
|
+
throw new Error(
|
|
150
|
+
`ObjectTypeComposer(${tc.getTypeName()}) provided to composeWithRelay should have findById resolver.`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
TypeMapForRelayNode[tc.getTypeName()] = {
|
|
154
|
+
resolver: findById,
|
|
155
|
+
tc
|
|
156
|
+
};
|
|
157
|
+
tc.addFields({
|
|
158
|
+
id: {
|
|
159
|
+
type: "ID!",
|
|
160
|
+
description: "The globally unique ID among all types",
|
|
161
|
+
resolve: (source) => {
|
|
162
|
+
return toGlobalId(tc.getTypeName(), tc.getRecordId(source));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
tc.addInterface(nodeInterface);
|
|
167
|
+
return tc;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// src/composeWithRelay/index.ts
|
|
171
|
+
import { schemaComposer } from "graphql-compose";
|
|
172
|
+
composeWithRelay(schemaComposer.Query);
|
|
173
|
+
|
|
174
|
+
// src/index.ts
|
|
175
|
+
import { default as default2 } from "graphql-compose-connection";
|
|
23
176
|
export {
|
|
177
|
+
default2 as composeWithConnection,
|
|
178
|
+
composeWithRelay,
|
|
24
179
|
createApiTemplate,
|
|
25
|
-
createAppSyncResolverHandler
|
|
180
|
+
createAppSyncResolverHandler,
|
|
181
|
+
fromGlobalId,
|
|
182
|
+
toGlobalId
|
|
26
183
|
};
|
package/dist/esm/server.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { SchemaComposer } from 'graphql-compose';
|
|
1
|
+
import { SchemaComposer, ObjectTypeComposer } from 'graphql-compose';
|
|
2
2
|
import { CloudFormationTemplate } from '@ttoss/cloudformation';
|
|
3
3
|
import { AppSyncResolverHandler as AppSyncResolverHandler$1 } from 'aws-lambda';
|
|
4
4
|
export { AppSyncIdentityCognito } from 'aws-lambda';
|
|
5
|
+
export { default as composeWithConnection } from 'graphql-compose-connection';
|
|
5
6
|
|
|
6
7
|
type StringOrImport = string | {
|
|
7
8
|
'Fn::ImportValue': string;
|
|
@@ -33,4 +34,21 @@ declare const createAppSyncResolverHandler: ({ schemaComposer, }: {
|
|
|
33
34
|
schemaComposer: SchemaComposer<any>;
|
|
34
35
|
}) => AppSyncResolverHandler<any, any, any>;
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
declare const composeWithRelay: <TContext>(tc: ObjectTypeComposer<any, TContext>) => ObjectTypeComposer<any, TContext>;
|
|
38
|
+
|
|
39
|
+
type ResolvedGlobalId = {
|
|
40
|
+
type: string;
|
|
41
|
+
id: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Takes a type name and an ID specific to that type name, and returns a
|
|
45
|
+
* "global ID" that is unique among all types.
|
|
46
|
+
*/
|
|
47
|
+
declare const toGlobalId: (type: string, id: string | number) => string;
|
|
48
|
+
/**
|
|
49
|
+
* Takes the "global ID" created by toGlobalID, and returns the type name and ID
|
|
50
|
+
* used to create it.
|
|
51
|
+
*/
|
|
52
|
+
declare const fromGlobalId: (globalId: string) => ResolvedGlobalId;
|
|
53
|
+
|
|
54
|
+
export { AppSyncResolverHandler, composeWithRelay, createApiTemplate, createAppSyncResolverHandler, fromGlobalId, toGlobalId };
|