Skip to content

Commit e4be7c6

Browse files
authored
Merge pull request #63 from bboure/feat/reload-vtl
2 parents 9c1eda7 + 15f87dc commit e4be7c6

File tree

13 files changed

+2571
-198
lines changed

13 files changed

+2571
-198
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,7 @@ jobs:
1414
- name: Install dependencies
1515
run: |
1616
yarn install --frozen-lockfile
17-
- name: Run tests
17+
- name: Run lint
1818
run: yarn run lint
19+
- name: Run tests
20+
run: yarn run tests

README.md

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -53,21 +53,22 @@ Serverless: GraphiQl: http://localhost:20002
5353

5454
Put options under `custom.appsync-simulator` in your `serverless.yml` file
5555

56-
| option | default | description |
57-
| ------------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
58-
| apiKey | `0123456789` | When using `API_KEY` as authentication type, the key to authenticate to the endpoint. |
59-
| port | 20002 | AppSync operations port |
60-
| wsPort | 20003 | AppSync subscriptions port |
61-
| location | . (base directory) | Location of the lambda functions handlers. |
62-
| lambda.loadLocalEnv | false | If `true`, all environment variables (`$ env`) will be accessible from the resolver function. Read more in section [Environment variables](#environment-variables). |
63-
| refMap | {} | A mapping of [resource resolutions](#resource-cloudformation-functions-resolution) for the `Ref` function |
64-
| getAttMap | {} | A mapping of [resource resolutions](#resource-cloudformation-functions-resolution) for the `GetAtt` function |
65-
| importValueMap | {} | A mapping of [resource resolutions](#resource-cloudformation-functions-resolution) for the `ImportValue` function |
66-
| functions | {} | A mapping of [external functions](#functions) for providing invoke url for external fucntions |
67-
| dynamoDb.endpoint | http://localhost:8000 | Dynamodb endpoint. Specify it if you're not using serverless-dynamodb-local. Otherwise, port is taken from dynamodb-local conf |
68-
| dynamoDb.region | localhost | Dynamodb region. Specify it if you're connecting to a remote Dynamodb intance. |
69-
| dynamoDb.accessKeyId | DEFAULT_ACCESS_KEY | AWS Access Key ID to access DynamoDB |
70-
| dynamoDb.secretAccessKey | DEFAULT_SECRET | AWS Secret Key to access DynamoDB |
56+
| option | default | description |
57+
| ------------------------ | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
58+
| apiKey | `0123456789` | When using `API_KEY` as authentication type, the key to authenticate to the endpoint. |
59+
| port | 20002 | AppSync operations port |
60+
| wsPort | 20003 | AppSync subscriptions port |
61+
| location | . (base directory) | Location of the lambda functions handlers. |
62+
| lambda.loadLocalEnv | false | If `true`, all environment variables (`$ env`) will be accessible from the resolver function. Read more in section [Environment variables](#environment-variables). |
63+
| refMap | {} | A mapping of [resource resolutions](#resource-cloudformation-functions-resolution) for the `Ref` function |
64+
| getAttMap | {} | A mapping of [resource resolutions](#resource-cloudformation-functions-resolution) for the `GetAtt` function |
65+
| importValueMap | {} | A mapping of [resource resolutions](#resource-cloudformation-functions-resolution) for the `ImportValue` function |
66+
| functions | {} | A mapping of [external functions](#functions) for providing invoke url for external fucntions |
67+
| dynamoDb.endpoint | http://localhost:8000 | Dynamodb endpoint. Specify it if you're not using serverless-dynamodb-local. Otherwise, port is taken from dynamodb-local conf |
68+
| dynamoDb.region | localhost | Dynamodb region. Specify it if you're connecting to a remote Dynamodb intance. |
69+
| dynamoDb.accessKeyId | DEFAULT_ACCESS_KEY | AWS Access Key ID to access DynamoDB |
70+
| dynamoDb.secretAccessKey | DEFAULT_SECRET | AWS Secret Key to access DynamoDB |
71+
| watch | - \*.graphql<br/> - \*.vtl | Array of glob patterns to watch for hot-reloading. |
7172

7273
Example:
7374

@@ -79,6 +80,18 @@ custom:
7980
endpoint: 'http://my-custom-dynamo:8000'
8081
```
8182

83+
# Hot-reloading
84+
85+
By default, the simulator will hot-relad when changes to `*.graphql` or `*.vtl` files are detected.
86+
Changes to `*.yml` files are not supported (yet? - this is a Serverless Framework limitation). You will need to restart the simulator each time you change yml files.
87+
88+
Hot-reloading relies on [watchman](https://facebook.github.io/watchman). Make sure it is [installed](https://facebook.github.io/watchman/docs/install.html) on your system.
89+
90+
You can change the files being watched with the `watch` option.
91+
Or you can opt-out by leaving an emptry array or set the option to `false`.
92+
93+
Note: Functions should not require hot-reloading, unless you are using a transpiler or a bundler (such as webpack, babel or typescript), un which case you should delegate hot-reloading to that instead.
94+
8295
# Resource CloudFormation functions resolution
8396

8497
This plugin supports _some_ resources resolution from the `Ref`, `Fn::GetAtt` and `Fn::ImportValue` functions

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
},
1313
"scripts": {
1414
"lint": "eslint",
15-
"build": "babel src/ -d lib/ --delete-dir-on-start",
15+
"tests": "jest",
16+
"build": "babel src/ -d lib/ --delete-dir-on-start --ignore '**/__tests__'",
1617
"prepare": "yarn run build",
1718
"start-dev": "yarn run build -w --verbose"
1819
},
@@ -24,8 +25,11 @@
2425
"amplify-nodejs-function-runtime-provider": "^1.1.6",
2526
"aws-sdk": "^2.792.0",
2627
"axios": "^0.21.0",
28+
"babel-jest": "^26.6.3",
2729
"cfn-resolver-lib": "^1.1.7",
2830
"dataloader": "^2.0.0",
31+
"fb-watchman": "^2.0.1",
32+
"jest": "^26.6.3",
2933
"lodash": "^4.17.20",
3034
"merge-graphql-schemas": "^1.5.8"
3135
},
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`getAppSyncConfig should generate a valid config 1`] = `
4+
Object {
5+
"additionalAuthenticationProviders": Array [],
6+
"apiKey": "123456789",
7+
"defaultAuthenticationType": Object {
8+
"authenticationType": "API_KEY",
9+
},
10+
"name": "myAPI",
11+
}
12+
`;
13+
14+
exports[`getAppSyncConfig should generate a valid config 2`] = `
15+
Object {
16+
"content": "type Post {
17+
userId: Int!
18+
id: Int!
19+
title: String!
20+
body: String!
21+
}
22+
23+
type Query {
24+
getPost: Post
25+
getPosts: [Post]!
26+
}
27+
28+
schema {
29+
query: Query
30+
}
31+
",
32+
"path": "schema.graphql",
33+
}
34+
`;
35+
36+
exports[`getAppSyncConfig should generate a valid config 3`] = `
37+
Array [
38+
Object {
39+
"dataSourceName": "lambda",
40+
"fieldName": "templates",
41+
"functions": undefined,
42+
"kind": "UNIT",
43+
"requestMappingTemplate": "{
44+
\\"version\\": \\"2018-05-29\\",
45+
\\"operation\\": \\"Invoke\\",
46+
\\"payload\\": {
47+
\\"substitution\\": \\"lambda\\",
48+
\\"args\\": $utils.toJson($context.arguments)
49+
}
50+
}
51+
",
52+
"responseMappingTemplate": "$utils.toJson($context.result.lambda)
53+
",
54+
"typeName": "Query",
55+
},
56+
Object {
57+
"dataSourceName": "lambda",
58+
"fieldName": "default",
59+
"functions": undefined,
60+
"kind": "UNIT",
61+
"requestMappingTemplate": "{
62+
\\"version\\": \\"2018-05-29\\",
63+
\\"operation\\": \\"Invoke\\",
64+
\\"payload\\": {
65+
\\"substitution\\": \\"default\\",
66+
\\"type\\": \\"default\\"
67+
}
68+
}
69+
",
70+
"responseMappingTemplate": "$utils.toJson($context.result.default)
71+
",
72+
"typeName": "Query",
73+
},
74+
Object {
75+
"dataSourceName": "lambda",
76+
"fieldName": "directLambda",
77+
"functions": undefined,
78+
"kind": "UNIT",
79+
"requestMappingTemplate": "## Direct lambda request
80+
{
81+
\\"version\\": \\"2018-05-29\\",
82+
\\"operation\\": \\"Invoke\\",
83+
\\"payload\\": $utils.toJson($context)
84+
}
85+
",
86+
"responseMappingTemplate": "## Direct lambda response
87+
#if($ctx.error)
88+
$util.error($ctx.error.message, $ctx.error.type, $ctx.result)
89+
#end
90+
$util.toJson($ctx.result)
91+
",
92+
"typeName": "Query",
93+
},
94+
Object {
95+
"dataSourceName": undefined,
96+
"fieldName": "pipeline",
97+
"functions": Array [
98+
"func",
99+
"func-default",
100+
],
101+
"kind": "PIPELINE",
102+
"requestMappingTemplate": "{
103+
\\"version\\": \\"2018-05-29\\",
104+
\\"operation\\": \\"Invoke\\",
105+
\\"payload\\": {
106+
\\"substitution\\": \\"pipeline\\",
107+
\\"type\\": \\"default\\"
108+
}
109+
}
110+
",
111+
"responseMappingTemplate": "$utils.toJson($context.result.default)
112+
",
113+
"typeName": "Query",
114+
},
115+
]
116+
`;
117+
118+
exports[`getAppSyncConfig should generate a valid config 4`] = `
119+
Array [
120+
Object {
121+
"invoke": [Function],
122+
"name": "lambda",
123+
"type": "AWS_LAMBDA",
124+
},
125+
Object {
126+
"config": Object {
127+
"accessKeyId": "DEFAULT_ACCESS_KEY",
128+
"endpoint": "http://localhost:8000",
129+
"region": "localhost",
130+
"secretAccessKey": "DEFAULT_SECRET",
131+
"tableName": "myTable",
132+
},
133+
"name": "dynamodb",
134+
"type": "AMAZON_DYNAMODB",
135+
},
136+
Object {
137+
"endpoint": "http://127.0.0.1",
138+
"name": "http",
139+
"type": "HTTP",
140+
},
141+
]
142+
`;
143+
144+
exports[`getAppSyncConfig should generate a valid config 5`] = `
145+
Array [
146+
Object {
147+
"dataSourceName": "lambda",
148+
"name": "func",
149+
"requestMappingTemplate": "{
150+
\\"version\\": \\"2018-05-29\\",
151+
\\"operation\\": \\"Invoke\\",
152+
\\"payload\\": {
153+
\\"substitution\\": \\"template-function\\",
154+
\\"args\\": $utils.toJson($context.arguments)
155+
}
156+
}
157+
",
158+
"responseMappingTemplate": "$utils.toJson($context.result.lambda)
159+
",
160+
},
161+
Object {
162+
"dataSourceName": "lambda",
163+
"name": "func-default",
164+
"requestMappingTemplate": "{
165+
\\"version\\": \\"2018-05-29\\",
166+
\\"operation\\": \\"Invoke\\",
167+
\\"payload\\": {
168+
\\"substitution\\": \\"default-function\\",
169+
\\"type\\": \\"default\\"
170+
}
171+
}
172+
",
173+
"responseMappingTemplate": "$utils.toJson($context.result.default)
174+
",
175+
},
176+
Object {
177+
"dataSourceName": "lambda",
178+
"name": "func-direct",
179+
"requestMappingTemplate": "## Direct lambda request
180+
{
181+
\\"version\\": \\"2018-05-29\\",
182+
\\"operation\\": \\"Invoke\\",
183+
\\"payload\\": $utils.toJson($context)
184+
}
185+
",
186+
"responseMappingTemplate": "## Direct lambda response
187+
#if($ctx.error)
188+
$util.error($ctx.error.message, $ctx.error.type, $ctx.result)
189+
#end
190+
$util.toJson($ctx.result)
191+
",
192+
},
193+
]
194+
`;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"version": "2018-05-29",
3+
"operation": "Invoke",
4+
"payload": {
5+
"substitution": "$mySubVar",
6+
"type": "default"
7+
}
8+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$utils.toJson($context.result.default)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"version": "2018-05-29",
3+
"operation": "Invoke",
4+
"payload": {
5+
"substitution": "$mySubVar",
6+
"args": $utils.toJson($context.arguments)
7+
}
8+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$utils.toJson($context.result.lambda)

src/__tests__/files/schema.graphql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
type Post {
2+
userId: Int!
3+
id: Int!
4+
title: String!
5+
body: String!
6+
}
7+
8+
type Query {
9+
getPost: Post
10+
getPosts: [Post]!
11+
}
12+
13+
schema {
14+
query: Query
15+
}

0 commit comments

Comments
 (0)