@ttoss/appsync-api 0.14.0 → 0.15.1

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 CHANGED
@@ -18,7 +18,7 @@ You can create and deploy an AppSync API in four steps:
18
18
 
19
19
  ```typescript
20
20
  import { createApiTemplate } from '@ttoss/appsync-api';
21
- import { schemaComposer } from '@ttoss/graphql-api';
21
+ import { schemaComposer } from './schemaComposer';
22
22
 
23
23
  const template = createApiTemplate({
24
24
  schemaComposer,
@@ -41,7 +41,7 @@ export default template;
41
41
 
42
42
  ```typescript
43
43
  import { createAppSyncResolverHandler } from '@ttoss/appsync-api';
44
- import { schemaComposer } from '@ttoss/graphql-api';
44
+ import { schemaComposer } from './schemaComposer';
45
45
 
46
46
  export const handler = createAppSyncResolverHandler({ schemaComposer });
47
47
  ```
@@ -58,3 +58,43 @@ Now you can deploy your API using `carlin deploy`:
58
58
  ```bash
59
59
  carlin deploy
60
60
  ```
61
+
62
+ ## Advanced Usage
63
+
64
+ ### Middlewares
65
+
66
+ You can add middlewares compatible with [`graphql-middleware`](https://github.com/dimatill/graphql-middleware) to the server using the `middlewares` option.
67
+
68
+ ```ts
69
+ import { createAppSyncResolverHandler } from '@ttoss/appsync-api';
70
+ import { schemaComposer } from './schemaComposer';
71
+ import { allow, deny, shield } from 'graphql-shield';
72
+
73
+ const NotAuthorizedError = new Error('Not authorized!');
74
+ /**
75
+ * The error name is the same value `errorType` on GraphQL errors response.
76
+ */
77
+ NotAuthorizedError.name = 'NotAuthorizedError';
78
+
79
+ const permissions = shield(
80
+ {
81
+ Query: {
82
+ '*': deny,
83
+ author: allow,
84
+ },
85
+ Author: {
86
+ id: allow,
87
+ name: allow,
88
+ },
89
+ },
90
+ {
91
+ fallbackRule: deny,
92
+ fallbackError: NotAuthorizedError,
93
+ }
94
+ );
95
+
96
+ export const handler = createAppSyncResolverHandler({
97
+ schemaComposer,
98
+ middlewares: [permissions],
99
+ });
100
+ ```
package/dist/esm/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
2
 
3
3
  // src/createApiTemplate.ts
4
- import { graphql } from "graphql-compose";
4
+ import { graphql } from "@ttoss/graphql-api";
5
5
 
6
6
  // ../../node_modules/.pnpm/tslib@2.5.0/node_modules/tslib/tslib.es6.js
7
7
  var __assign = function () {
@@ -80,7 +80,7 @@ var getPackageLambdaLayerStackName = packageName => {
80
80
  // package.json
81
81
  var package_default = {
82
82
  name: "@ttoss/appsync-api",
83
- version: "0.14.0",
83
+ version: "0.15.1",
84
84
  description: "A library for building GraphQL APIs for AWS AppSync.",
85
85
  license: "UNLICENSED",
86
86
  author: "ttoss",
@@ -95,32 +95,26 @@ var package_default = {
95
95
  sideEffects: false,
96
96
  typings: "dist/index.d.ts",
97
97
  dependencies: {
98
- "@ttoss/cloudformation": "workspace:^",
99
- "@ttoss/graphql-api": "workspace:^"
98
+ "@ttoss/cloudformation": "workspace:^"
100
99
  },
101
100
  peerDependencies: {
102
- graphql: "^16.6.0",
103
- "graphql-compose": "^9.0.10"
101
+ "@ttoss/graphql-api": "workspace:^",
102
+ graphql: "^16.6.0"
104
103
  },
105
104
  devDependencies: {
106
105
  "@ttoss/config": "workspace:^",
106
+ "@ttoss/graphql-api": "workspace:^",
107
107
  "@ttoss/relay-amplify": "workspace:^",
108
108
  "@types/aws-lambda": "^8.10.115",
109
109
  carlin: "workspace:^",
110
110
  graphql: "^16.6.0",
111
- "graphql-compose": "^9.0.10",
111
+ "graphql-shield": "^7.6.5",
112
112
  jest: "^29.5.0",
113
113
  tsup: "^6.7.0"
114
114
  },
115
115
  keywords: ["api", "appsync", "aws", "graphql"],
116
116
  publishConfig: {
117
117
  access: "public"
118
- },
119
- typesVersions: {
120
- "*": {
121
- ".": ["./dist/index.d.ts"],
122
- server: ["./dist/server.d.ts"]
123
- }
124
118
  }
125
119
  };
126
120
 
@@ -159,11 +153,13 @@ var createApiTemplate = ({
159
153
  };
160
154
  });
161
155
  }).filter(Boolean);
162
- const getGraphQLComposeDependenciesLambdaLayers = () => {
156
+ const getPeerDependenciesLambdaLayers = () => {
163
157
  const {
164
158
  peerDependencies
165
159
  } = package_default;
166
- const lambdaLayerStackNames = Object.entries(peerDependencies).map(([dependencyName, dependencyVersion]) => {
160
+ const lambdaLayerStackNames = Object.entries(peerDependencies).filter(([dependencyName]) => {
161
+ return ["graphql"].includes(dependencyName);
162
+ }).map(([dependencyName, dependencyVersion]) => {
167
163
  return getPackageLambdaLayerStackName([dependencyName, dependencyVersion].join("@"));
168
164
  });
169
165
  return lambdaLayerStackNames.map(lambdaLayerStackName => {
@@ -226,7 +222,7 @@ var createApiTemplate = ({
226
222
  }
227
223
  },
228
224
  Handler: "index.handler",
229
- Layers: getGraphQLComposeDependenciesLambdaLayers(),
225
+ Layers: getPeerDependenciesLambdaLayers(),
230
226
  MemorySize: 512,
231
227
  Role: lambdaFunction.roleArn,
232
228
  Runtime: "nodejs18.x",
@@ -346,6 +342,9 @@ var createApiTemplate = ({
346
342
  return template;
347
343
  };
348
344
 
345
+ // src/createAppSyncResolverHandler.ts
346
+ import { buildSchema } from "@ttoss/graphql-api";
347
+
349
348
  // ../relay-amplify/src/encodeCredentials.ts
350
349
  var decodeCredentials = credentials => {
351
350
  return JSON.parse(Buffer.from(credentials, "base64").toString("utf8"));
@@ -353,7 +352,7 @@ var decodeCredentials = credentials => {
353
352
 
354
353
  // src/createAppSyncResolverHandler.ts
355
354
  var createAppSyncResolverHandler = ({
356
- schemaComposer
355
+ ...buildSchemaInput
357
356
  }) => {
358
357
  return async (event, context) => {
359
358
  const {
@@ -374,14 +373,26 @@ var createAppSyncResolverHandler = ({
374
373
  }
375
374
  return decodeCredentials(headersCredentials);
376
375
  })();
377
- const resolveMethods = schemaComposer.getResolveMethods();
378
- const resolver = resolveMethods[parentTypeName][fieldName];
379
- return resolver(source, args, {
376
+ const schema = buildSchema(buildSchemaInput);
377
+ const parentType = schema.getType(parentTypeName);
378
+ if (!parentType) {
379
+ throw new Error(`Type ${parentTypeName} not found`);
380
+ }
381
+ const field = parentType.getFields()[fieldName];
382
+ const resolver = field?.resolve;
383
+ if (!resolver) {
384
+ throw new Error(`Resolver for ${parentTypeName}.${fieldName} not found`);
385
+ }
386
+ const response = await resolver(source, args, {
380
387
  ...context,
381
388
  identity: event.identity,
382
389
  credentials,
383
390
  headers
384
391
  }, info);
392
+ if (response instanceof Error) {
393
+ throw response;
394
+ }
395
+ return response;
385
396
  };
386
397
  };
387
398
  export { createApiTemplate, createAppSyncResolverHandler };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SchemaComposer } from 'graphql-compose';
1
+ import { SchemaComposer, BuildSchemaInput } from '@ttoss/graphql-api';
2
2
  import { AppSyncResolverHandler as AppSyncResolverHandler$1 } from 'aws-lambda';
3
3
  export { AppSyncIdentityCognito } from 'aws-lambda';
4
4
 
@@ -109,8 +109,6 @@ declare const createApiTemplate: ({ additionalAuthenticationProviders, authentic
109
109
  }) => CloudFormationTemplate;
110
110
 
111
111
  type AppSyncResolverHandler<TArguments, TResult, TSource = Record<string, any> | null> = AppSyncResolverHandler$1<TArguments, TResult, TSource>;
112
- declare const createAppSyncResolverHandler: ({ schemaComposer, }: {
113
- schemaComposer: SchemaComposer<any>;
114
- }) => AppSyncResolverHandler<any, any, any>;
112
+ declare const createAppSyncResolverHandler: ({ ...buildSchemaInput }: BuildSchemaInput) => AppSyncResolverHandler<any, any, any>;
115
113
 
116
114
  export { AppSyncResolverHandler, createApiTemplate, createAppSyncResolverHandler };
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ __export(src_exports, {
33
33
  module.exports = __toCommonJS(src_exports);
34
34
 
35
35
  // src/createApiTemplate.ts
36
- var import_graphql_compose = require("graphql-compose");
36
+ var import_graphql_api = require("@ttoss/graphql-api");
37
37
 
38
38
  // ../../node_modules/.pnpm/tslib@2.5.0/node_modules/tslib/tslib.es6.js
39
39
  var __assign = function () {
@@ -112,7 +112,7 @@ var getPackageLambdaLayerStackName = packageName => {
112
112
  // package.json
113
113
  var package_default = {
114
114
  name: "@ttoss/appsync-api",
115
- version: "0.14.0",
115
+ version: "0.15.1",
116
116
  description: "A library for building GraphQL APIs for AWS AppSync.",
117
117
  license: "UNLICENSED",
118
118
  author: "ttoss",
@@ -127,32 +127,26 @@ var package_default = {
127
127
  sideEffects: false,
128
128
  typings: "dist/index.d.ts",
129
129
  dependencies: {
130
- "@ttoss/cloudformation": "workspace:^",
131
- "@ttoss/graphql-api": "workspace:^"
130
+ "@ttoss/cloudformation": "workspace:^"
132
131
  },
133
132
  peerDependencies: {
134
- graphql: "^16.6.0",
135
- "graphql-compose": "^9.0.10"
133
+ "@ttoss/graphql-api": "workspace:^",
134
+ graphql: "^16.6.0"
136
135
  },
137
136
  devDependencies: {
138
137
  "@ttoss/config": "workspace:^",
138
+ "@ttoss/graphql-api": "workspace:^",
139
139
  "@ttoss/relay-amplify": "workspace:^",
140
140
  "@types/aws-lambda": "^8.10.115",
141
141
  carlin: "workspace:^",
142
142
  graphql: "^16.6.0",
143
- "graphql-compose": "^9.0.10",
143
+ "graphql-shield": "^7.6.5",
144
144
  jest: "^29.5.0",
145
145
  tsup: "^6.7.0"
146
146
  },
147
147
  keywords: ["api", "appsync", "aws", "graphql"],
148
148
  publishConfig: {
149
149
  access: "public"
150
- },
151
- typesVersions: {
152
- "*": {
153
- ".": ["./dist/index.d.ts"],
154
- server: ["./dist/server.d.ts"]
155
- }
156
150
  }
157
151
  };
158
152
 
@@ -175,7 +169,7 @@ var createApiTemplate = ({
175
169
  omitDescriptions: true,
176
170
  omitScalars: true
177
171
  });
178
- import_graphql_compose.graphql.validateSchema(schemaComposer.buildSchema());
172
+ import_graphql_api.graphql.validateSchema(schemaComposer.buildSchema());
179
173
  const resolveMethods = schemaComposer.getResolveMethods();
180
174
  const resolveMethodsEntries = Object.entries(resolveMethods).flatMap(([typeName, fieldResolvers]) => {
181
175
  return Object.entries(fieldResolvers).map(([fieldName, resolver]) => {
@@ -191,11 +185,13 @@ var createApiTemplate = ({
191
185
  };
192
186
  });
193
187
  }).filter(Boolean);
194
- const getGraphQLComposeDependenciesLambdaLayers = () => {
188
+ const getPeerDependenciesLambdaLayers = () => {
195
189
  const {
196
190
  peerDependencies
197
191
  } = package_default;
198
- const lambdaLayerStackNames = Object.entries(peerDependencies).map(([dependencyName, dependencyVersion]) => {
192
+ const lambdaLayerStackNames = Object.entries(peerDependencies).filter(([dependencyName]) => {
193
+ return ["graphql"].includes(dependencyName);
194
+ }).map(([dependencyName, dependencyVersion]) => {
199
195
  return getPackageLambdaLayerStackName([dependencyName, dependencyVersion].join("@"));
200
196
  });
201
197
  return lambdaLayerStackNames.map(lambdaLayerStackName => {
@@ -258,7 +254,7 @@ var createApiTemplate = ({
258
254
  }
259
255
  },
260
256
  Handler: "index.handler",
261
- Layers: getGraphQLComposeDependenciesLambdaLayers(),
257
+ Layers: getPeerDependenciesLambdaLayers(),
262
258
  MemorySize: 512,
263
259
  Role: lambdaFunction.roleArn,
264
260
  Runtime: "nodejs18.x",
@@ -378,6 +374,9 @@ var createApiTemplate = ({
378
374
  return template;
379
375
  };
380
376
 
377
+ // src/createAppSyncResolverHandler.ts
378
+ var import_graphql_api2 = require("@ttoss/graphql-api");
379
+
381
380
  // ../relay-amplify/src/encodeCredentials.ts
382
381
  var decodeCredentials = credentials => {
383
382
  return JSON.parse(Buffer.from(credentials, "base64").toString("utf8"));
@@ -385,7 +384,7 @@ var decodeCredentials = credentials => {
385
384
 
386
385
  // src/createAppSyncResolverHandler.ts
387
386
  var createAppSyncResolverHandler = ({
388
- schemaComposer
387
+ ...buildSchemaInput
389
388
  }) => {
390
389
  return async (event, context) => {
391
390
  const {
@@ -406,14 +405,26 @@ var createAppSyncResolverHandler = ({
406
405
  }
407
406
  return decodeCredentials(headersCredentials);
408
407
  })();
409
- const resolveMethods = schemaComposer.getResolveMethods();
410
- const resolver = resolveMethods[parentTypeName][fieldName];
411
- return resolver(source, args, {
408
+ const schema = (0, import_graphql_api2.buildSchema)(buildSchemaInput);
409
+ const parentType = schema.getType(parentTypeName);
410
+ if (!parentType) {
411
+ throw new Error(`Type ${parentTypeName} not found`);
412
+ }
413
+ const field = parentType.getFields()[fieldName];
414
+ const resolver = field?.resolve;
415
+ if (!resolver) {
416
+ throw new Error(`Resolver for ${parentTypeName}.${fieldName} not found`);
417
+ }
418
+ const response = await resolver(source, args, {
412
419
  ...context,
413
420
  identity: event.identity,
414
421
  credentials,
415
422
  headers
416
423
  }, info);
424
+ if (response instanceof Error) {
425
+ throw response;
426
+ }
427
+ return response;
417
428
  };
418
429
  };
419
430
  // Annotate the CommonJS export names for ESM import in node:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/appsync-api",
3
- "version": "0.14.0",
3
+ "version": "0.15.1",
4
4
  "description": "A library for building GraphQL APIs for AWS AppSync.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "ttoss",
@@ -16,22 +16,22 @@
16
16
  "sideEffects": false,
17
17
  "typings": "dist/index.d.ts",
18
18
  "dependencies": {
19
- "@ttoss/cloudformation": "^0.7.2",
20
- "@ttoss/graphql-api": "^0.2.0"
19
+ "@ttoss/cloudformation": "^0.7.3"
21
20
  },
22
21
  "peerDependencies": {
23
22
  "graphql": "^16.6.0",
24
- "graphql-compose": "^9.0.10"
23
+ "@ttoss/graphql-api": "^0.3.1"
25
24
  },
26
25
  "devDependencies": {
27
26
  "@types/aws-lambda": "^8.10.115",
28
27
  "graphql": "^16.6.0",
29
- "graphql-compose": "^9.0.10",
28
+ "graphql-shield": "^7.6.5",
30
29
  "jest": "^29.5.0",
31
30
  "tsup": "^6.7.0",
32
- "@ttoss/config": "^1.30.0",
33
- "@ttoss/relay-amplify": "^0.4.8",
34
- "carlin": "^1.29.1"
31
+ "@ttoss/config": "^1.30.1",
32
+ "@ttoss/graphql-api": "^0.3.1",
33
+ "@ttoss/relay-amplify": "^0.4.9",
34
+ "carlin": "^1.29.2"
35
35
  },
36
36
  "keywords": [
37
37
  "api",
@@ -42,16 +42,6 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "typesVersions": {
46
- "*": {
47
- ".": [
48
- "./dist/index.d.ts"
49
- ],
50
- "server": [
51
- "./dist/server.d.ts"
52
- ]
53
- }
54
- },
55
45
  "scripts": {
56
46
  "build": "tsup",
57
47
  "test": "jest"
@@ -1,4 +1,4 @@
1
- import { type SchemaComposer, graphql } from 'graphql-compose';
1
+ import { type SchemaComposer, graphql } from '@ttoss/graphql-api';
2
2
  import { getPackageLambdaLayerStackName } from 'carlin/src/deploy/lambdaLayer/getPackageLambdaLayerStackName';
3
3
  import packageJson from '../package.json';
4
4
 
@@ -101,16 +101,18 @@ export const createApiTemplate = ({
101
101
  })
102
102
  .filter(Boolean) as Array<{ fieldName: string; typeName: string }>;
103
103
 
104
- const getGraphQLComposeDependenciesLambdaLayers = () => {
104
+ const getPeerDependenciesLambdaLayers = () => {
105
105
  const { peerDependencies } = packageJson;
106
106
 
107
- const lambdaLayerStackNames = Object.entries(peerDependencies).map(
108
- ([dependencyName, dependencyVersion]) => {
107
+ const lambdaLayerStackNames = Object.entries(peerDependencies)
108
+ .filter(([dependencyName]) => {
109
+ return ['graphql'].includes(dependencyName);
110
+ })
111
+ .map(([dependencyName, dependencyVersion]) => {
109
112
  return getPackageLambdaLayerStackName(
110
113
  [dependencyName, dependencyVersion].join('@')
111
114
  );
112
- }
113
- );
115
+ });
114
116
 
115
117
  return lambdaLayerStackNames.map((lambdaLayerStackName) => {
116
118
  return {
@@ -166,7 +168,7 @@ export const createApiTemplate = ({
166
168
  S3ObjectVersion: { Ref: 'LambdaS3ObjectVersion' },
167
169
  },
168
170
  Handler: 'index.handler',
169
- Layers: getGraphQLComposeDependenciesLambdaLayers(),
171
+ Layers: getPeerDependenciesLambdaLayers(),
170
172
  MemorySize: 512,
171
173
  Role: lambdaFunction.roleArn,
172
174
  Runtime: 'nodejs18.x',
@@ -1,6 +1,7 @@
1
+ import { BuildSchemaInput, buildSchema } from '@ttoss/graphql-api';
2
+ import { type GraphQLObjectType } from 'graphql';
1
3
  import { decodeCredentials } from '@ttoss/relay-amplify/src/encodeCredentials';
2
4
  import type { AppSyncResolverHandler as AwsAppSyncResolverHandler } from 'aws-lambda';
3
- import type { SchemaComposer } from 'graphql-compose';
4
5
 
5
6
  export type AppSyncResolverHandler<
6
7
  TArguments,
@@ -9,10 +10,8 @@ export type AppSyncResolverHandler<
9
10
  > = AwsAppSyncResolverHandler<TArguments, TResult, TSource>;
10
11
 
11
12
  export const createAppSyncResolverHandler = ({
12
- schemaComposer,
13
- }: {
14
- schemaComposer: SchemaComposer<any>;
15
- }): AppSyncResolverHandler<any, any, any> => {
13
+ ...buildSchemaInput
14
+ }: BuildSchemaInput): AppSyncResolverHandler<any, any, any> => {
16
15
  return async (event, context) => {
17
16
  const { info, arguments: args, source, request } = event;
18
17
 
@@ -30,15 +29,33 @@ export const createAppSyncResolverHandler = ({
30
29
  return decodeCredentials(headersCredentials);
31
30
  })();
32
31
 
33
- const resolveMethods = schemaComposer.getResolveMethods();
32
+ const schema = buildSchema(buildSchemaInput);
34
33
 
35
- const resolver = (resolveMethods[parentTypeName] as any)[fieldName];
34
+ const parentType = schema.getType(parentTypeName) as GraphQLObjectType;
36
35
 
37
- return resolver(
36
+ if (!parentType) {
37
+ throw new Error(`Type ${parentTypeName} not found`);
38
+ }
39
+
40
+ const field = parentType.getFields()[fieldName];
41
+
42
+ const resolver = field?.resolve;
43
+
44
+ if (!resolver) {
45
+ throw new Error(`Resolver for ${parentTypeName}.${fieldName} not found`);
46
+ }
47
+
48
+ const response = await resolver(
38
49
  source,
39
50
  args,
40
51
  { ...context, identity: event.identity, credentials, headers },
41
- info
52
+ info as any
42
53
  );
54
+
55
+ if (response instanceof Error) {
56
+ throw response;
57
+ }
58
+
59
+ return response;
43
60
  };
44
61
  };