@ttoss/appsync-api 0.4.4 → 0.5.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.
@@ -0,0 +1,8 @@
1
+ import * as express_serve_static_core from 'express-serve-static-core';
2
+ import { SchemaComposer } from 'graphql-compose';
3
+
4
+ declare const createServer: ({ schemaComposer, }: {
5
+ schemaComposer: SchemaComposer<any>;
6
+ }) => express_serve_static_core.Express;
7
+
8
+ export { createServer };
package/dist/server.js ADDED
@@ -0,0 +1,66 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
26
+
27
+ // src/server.ts
28
+ var server_exports = {};
29
+ __export(server_exports, {
30
+ createServer: () => createServer
31
+ });
32
+ module.exports = __toCommonJS(server_exports);
33
+ var import_graphql_helix = require("graphql-helix");
34
+ var import_express = __toESM(require("express"));
35
+ var createServer = ({
36
+ schemaComposer
37
+ }) => {
38
+ const server = (0, import_express.default)();
39
+ server.use(import_express.default.json());
40
+ server.use("/graphql", async (req, res) => {
41
+ const request = {
42
+ body: req.body,
43
+ headers: req.headers,
44
+ method: req.method,
45
+ query: req.query
46
+ };
47
+ if ((0, import_graphql_helix.shouldRenderGraphiQL)(request)) {
48
+ res.send((0, import_graphql_helix.renderGraphiQL)());
49
+ return;
50
+ }
51
+ const { operationName, query, variables } = (0, import_graphql_helix.getGraphQLParameters)(request);
52
+ const result = await (0, import_graphql_helix.processRequest)({
53
+ operationName,
54
+ query,
55
+ variables,
56
+ request,
57
+ schema: schemaComposer.buildSchema()
58
+ });
59
+ (0, import_graphql_helix.sendResult)(result, res);
60
+ });
61
+ return server;
62
+ };
63
+ // Annotate the CommonJS export names for ESM import in node:
64
+ 0 && (module.exports = {
65
+ createServer
66
+ });
package/package.json CHANGED
@@ -1,12 +1,22 @@
1
1
  {
2
2
  "name": "@ttoss/appsync-api",
3
- "version": "0.4.4",
4
- "description": "",
3
+ "version": "0.5.1",
4
+ "description": "A library for building GraphQL APIs for AWS AppSync.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "ttoss",
7
7
  "contributors": [
8
8
  "Pedro Arantes <pedro@arantespp.com> (https://arantespp.com)"
9
9
  ],
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/esm/index.js",
13
+ "require": "./dist/index.js"
14
+ },
15
+ "./server": {
16
+ "import": "./dist/esm/server.js",
17
+ "require": "./dist/server.js"
18
+ }
19
+ },
10
20
  "main": "dist/index.js",
11
21
  "module": "dist/esm/index.js",
12
22
  "bin": {
@@ -20,21 +30,43 @@
20
30
  "build": "tsup",
21
31
  "test": "jest"
22
32
  },
33
+ "sideEffects": false,
23
34
  "typings": "dist/index.d.ts",
24
35
  "dependencies": {
25
- "@ttoss/cloudformation": "^0.3.0",
26
- "graphql": "^16.6.0",
27
- "graphql-compose": "^9.0.10",
36
+ "@ttoss/cloudformation": "^0.4.0",
37
+ "express": "^4.18.2",
38
+ "graphql-helix": "^1.13.0",
28
39
  "minimist": "^1.2.7"
29
40
  },
41
+ "peerDependencies": {
42
+ "graphql": "^16.6.0",
43
+ "graphql-compose": "^9.0.10"
44
+ },
30
45
  "devDependencies": {
31
- "@ttoss/config": "^1.26.0",
46
+ "@ttoss/config": "^1.27.0",
32
47
  "@types/aws-lambda": "^8.10.109",
33
- "carlin": "^1.21.4"
48
+ "carlin": "^1.22.0",
49
+ "graphql": "^16.6.0",
50
+ "graphql-compose": "^9.0.10"
34
51
  },
35
- "keywords": [],
52
+ "keywords": [
53
+ "api",
54
+ "appsync",
55
+ "aws",
56
+ "graphql"
57
+ ],
36
58
  "publishConfig": {
37
59
  "access": "public"
38
60
  },
39
- "gitHead": "f7fcb1caa22adf045f0ec7d15a678bfe48a3913d"
61
+ "typesVersions": {
62
+ "*": {
63
+ ".": [
64
+ "./dist/index.d.ts"
65
+ ],
66
+ "server": [
67
+ "./dist/server.d.ts"
68
+ ]
69
+ }
70
+ },
71
+ "gitHead": "2bf304efc726a34b95859bb9b6fe8749c1a16844"
40
72
  }
package/src/cli.ts CHANGED
@@ -11,9 +11,6 @@ if (argv._.includes('build-schema')) {
11
11
  const sdl =
12
12
  template.Resources[AppSyncGraphQLSchemaLogicalId].Properties.Definition;
13
13
 
14
- // eslint-disable-next-line no-console
15
- console.log(sdl);
16
-
17
14
  /**
18
15
  * Save to schema/schema.graphql. schema folder might not exist.
19
16
  */
@@ -1,27 +1,35 @@
1
1
  import { type SchemaComposer, graphql } from 'graphql-compose';
2
2
  import { getPackageLambdaLayerStackName } from 'carlin/src/deploy/lambdaLayer/getPackageLambdaLayerStackName';
3
- import { readPackageJson } from 'carlin/src/utils/packageJson';
4
3
  import packageJson from '../package.json';
5
- import type { CloudFormationTemplate } from 'carlin/src/utils/cloudFormationTemplate';
4
+ import type { CloudFormationTemplate } from '@ttoss/cloudformation';
6
5
 
7
6
  const AppSyncGraphQLApiLogicalId = 'AppSyncGraphQLApi';
8
7
 
9
8
  export const AppSyncGraphQLSchemaLogicalId = 'AppSyncGraphQLSchema';
10
9
 
11
- const AppSyncLambdaFunctionIAMRoleLogicalId = 'AppSyncLambdaFunctionIAMRole';
12
-
13
10
  export const AppSyncLambdaFunctionLogicalId = 'AppSyncLambdaFunction';
14
11
 
15
- const AppSyncLambdaFunctionAppSyncDataSourceIAMRoleLogicalId =
16
- 'AppSyncLambdaFunctionAppSyncDataSourceIAMRole';
17
-
18
12
  const AppSyncLambdaFunctionAppSyncDataSourceLogicalId =
19
13
  'AppSyncLambdaFunctionAppSyncDataSource';
20
14
 
15
+ type Role =
16
+ | string
17
+ | {
18
+ 'Fn::ImportValue': string;
19
+ };
20
+
21
21
  export const createApiTemplate = ({
22
22
  schemaComposer,
23
+ dataSource,
24
+ lambdaFunction,
23
25
  }: {
24
26
  schemaComposer: SchemaComposer<any>;
27
+ dataSource: {
28
+ roleArn: Role;
29
+ };
30
+ lambdaFunction: {
31
+ roleArn: Role;
32
+ };
25
33
  }): CloudFormationTemplate => {
26
34
  /**
27
35
  * It should be on top of the file, otherwise it will have empty Mutation
@@ -48,21 +56,23 @@ export const createApiTemplate = ({
48
56
  }
49
57
  );
50
58
 
51
- const { name } = packageJson;
52
-
53
- const { dependencies } = readPackageJson();
54
-
55
- const dependencyVersion = dependencies[name];
59
+ const getGraphQLComposeDependenciesLambdaLayers = () => {
60
+ const { peerDependencies } = packageJson;
56
61
 
57
- if (!dependencyVersion) {
58
- throw new Error(
59
- `The package ${name} is not installed in the project. Please install it with "yarn add ${name}".`
62
+ const lambdaLayerStackNames = Object.entries(peerDependencies).map(
63
+ ([dependencyName, dependencyVersion]) => {
64
+ return getPackageLambdaLayerStackName(
65
+ [dependencyName, dependencyVersion].join('@')
66
+ );
67
+ }
60
68
  );
61
- }
62
69
 
63
- const lambdaLayerStackName = getPackageLambdaLayerStackName(
64
- [name, dependencyVersion].join('@')
65
- );
70
+ return lambdaLayerStackNames.map((lambdaLayerStackName) => {
71
+ return {
72
+ 'Fn::ImportValue': lambdaLayerStackName,
73
+ };
74
+ });
75
+ };
66
76
 
67
77
  const template: CloudFormationTemplate = {
68
78
  AWSTemplateFormatVersion: '2010-09-09',
@@ -102,27 +112,6 @@ export const createApiTemplate = ({
102
112
  Definition: sdl,
103
113
  },
104
114
  },
105
- [AppSyncLambdaFunctionIAMRoleLogicalId]: {
106
- Type: 'AWS::IAM::Role',
107
- Properties: {
108
- AssumeRolePolicyDocument: {
109
- Version: '2012-10-17',
110
- Statement: [
111
- {
112
- Effect: 'Allow',
113
- Action: 'sts:AssumeRole',
114
- Principal: {
115
- Service: 'lambda.amazonaws.com',
116
- },
117
- },
118
- ],
119
- },
120
- ManagedPolicyArns: [
121
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole',
122
- ],
123
- Path: '/custom-iam/',
124
- },
125
- },
126
115
  [AppSyncLambdaFunctionLogicalId]: {
127
116
  Type: 'AWS::Lambda::Function',
128
117
  Properties: {
@@ -132,15 +121,9 @@ export const createApiTemplate = ({
132
121
  S3ObjectVersion: { Ref: 'LambdaS3ObjectVersion' },
133
122
  },
134
123
  Handler: 'index.handler',
135
- Layers: [
136
- {
137
- 'Fn::ImportValue': lambdaLayerStackName,
138
- },
139
- ],
124
+ Layers: getGraphQLComposeDependenciesLambdaLayers(),
140
125
  MemorySize: 512,
141
- Role: {
142
- 'Fn::GetAtt': [AppSyncLambdaFunctionIAMRoleLogicalId, 'Arn'],
143
- },
126
+ Role: lambdaFunction.roleArn,
144
127
  Runtime: 'nodejs18.x',
145
128
  /**
146
129
  * https://docs.aws.amazon.com/general/latest/gr/appsync.html
@@ -149,44 +132,6 @@ export const createApiTemplate = ({
149
132
  Timeout: 29,
150
133
  },
151
134
  },
152
- [AppSyncLambdaFunctionAppSyncDataSourceIAMRoleLogicalId]: {
153
- Type: 'AWS::IAM::Role',
154
- Properties: {
155
- AssumeRolePolicyDocument: {
156
- Version: '2012-10-17',
157
- Statement: [
158
- {
159
- Effect: 'Allow',
160
- Action: 'sts:AssumeRole',
161
- Principal: {
162
- Service: 'appsync.amazonaws.com',
163
- },
164
- },
165
- ],
166
- },
167
- ManagedPolicyArns: [
168
- 'arn:aws:iam::aws:policy/service-role/AWSAppSyncPushToCloudWatchLogs',
169
- ],
170
- Path: '/custom-iam/',
171
- Policies: [
172
- {
173
- PolicyName: 'AppSyncGraphQLApiIAMRolePolicyName',
174
- PolicyDocument: {
175
- Version: '2012-10-17',
176
- Statement: [
177
- {
178
- Effect: 'Allow',
179
- Action: ['lambda:InvokeFunction'],
180
- Resource: [
181
- { 'Fn::GetAtt': [AppSyncLambdaFunctionLogicalId, 'Arn'] },
182
- ],
183
- },
184
- ],
185
- },
186
- },
187
- ],
188
- },
189
- },
190
135
  [AppSyncLambdaFunctionAppSyncDataSourceLogicalId]: {
191
136
  Type: 'AWS::AppSync::DataSource',
192
137
  Properties: {
@@ -197,12 +142,7 @@ export const createApiTemplate = ({
197
142
  },
198
143
  },
199
144
  Name: 'AppSyncLambdaFunctionAppSyncDataSource',
200
- ServiceRoleArn: {
201
- 'Fn::GetAtt': [
202
- AppSyncLambdaFunctionAppSyncDataSourceIAMRoleLogicalId,
203
- 'Arn',
204
- ],
205
- },
145
+ ServiceRoleArn: dataSource.roleArn,
206
146
  Type: 'AWS_LAMBDA',
207
147
  },
208
148
  },
@@ -1,7 +1,13 @@
1
- import type { AppSyncResolverHandler } from 'aws-lambda';
1
+ import type { AppSyncResolverHandler as AwsAppSyncResolverHandler } from 'aws-lambda';
2
2
  import type { SchemaComposer } from 'graphql-compose';
3
3
 
4
- export const appSyncResolverHandler = ({
4
+ export type AppSyncResolverHandler<
5
+ TArguments,
6
+ TResult,
7
+ TSource = Record<string, any> | null
8
+ > = AwsAppSyncResolverHandler<TArguments, TResult, TSource>;
9
+
10
+ export const createAppSyncResolverHandler = ({
5
11
  schemaComposer,
6
12
  }: {
7
13
  schemaComposer: SchemaComposer<any>;
package/src/index.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  export { type ResolverResolveParams, schemaComposer } from 'graphql-compose';
2
2
  export { createApiTemplate } from './createApiTemplate';
3
- export { appSyncResolverHandler } from './appSyncResolverHandler';
3
+ export {
4
+ type AppSyncResolverHandler,
5
+ createAppSyncResolverHandler,
6
+ } from './createAppSyncResolverHandler';
package/src/server.ts ADDED
@@ -0,0 +1,47 @@
1
+ import { type SchemaComposer } from 'graphql-compose';
2
+ import {
3
+ getGraphQLParameters,
4
+ processRequest,
5
+ renderGraphiQL,
6
+ sendResult,
7
+ shouldRenderGraphiQL,
8
+ } from 'graphql-helix';
9
+ import express from 'express';
10
+
11
+ export const createServer = ({
12
+ schemaComposer,
13
+ }: {
14
+ schemaComposer: SchemaComposer<any>;
15
+ }) => {
16
+ const server = express();
17
+
18
+ server.use(express.json());
19
+
20
+ server.use('/graphql', async (req, res) => {
21
+ const request = {
22
+ body: req.body,
23
+ headers: req.headers,
24
+ method: req.method,
25
+ query: req.query,
26
+ };
27
+
28
+ if (shouldRenderGraphiQL(request)) {
29
+ res.send(renderGraphiQL());
30
+ return;
31
+ }
32
+
33
+ const { operationName, query, variables } = getGraphQLParameters(request);
34
+
35
+ const result = await processRequest({
36
+ operationName,
37
+ query,
38
+ variables,
39
+ request,
40
+ schema: schemaComposer.buildSchema(),
41
+ });
42
+
43
+ sendResult(result, res);
44
+ });
45
+
46
+ return server;
47
+ };