@mapbox/cloudfriend 7.0.0 → 7.0.1-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.
Files changed (21) hide show
  1. package/.nyc_output/5173def1-e652-48eb-b821-68e4c28e98bf.json +1 -0
  2. package/.nyc_output/da9b250c-7fe3-4849-a7b9-5dcb7ad608aa.json +1 -0
  3. package/.nyc_output/processinfo/{2c9b3698-f822-47f6-a941-eea13e638ffc.json → 5173def1-e652-48eb-b821-68e4c28e98bf.json} +1 -1
  4. package/.nyc_output/processinfo/{1983e39b-fcbb-4618-a9dd-36f2ec3b1532.json → da9b250c-7fe3-4849-a7b9-5dcb7ad608aa.json} +1 -1
  5. package/.nyc_output/processinfo/index.json +1 -1
  6. package/lib/shortcuts/hookshot.js +23 -12
  7. package/package.json +1 -1
  8. package/test/fixtures/shortcuts/hookshot-github-compatible-legacy-node-runtimes.json +423 -0
  9. package/test/fixtures/shortcuts/hookshot-github-secret-ref.json +3 -3
  10. package/test/fixtures/shortcuts/hookshot-github-secret-string.json +3 -3
  11. package/test/fixtures/shortcuts/hookshot-github.json +3 -3
  12. package/test/fixtures/shortcuts/hookshot-passthrough-access-log-format.json +3 -3
  13. package/test/fixtures/shortcuts/hookshot-passthrough-alarms.json +3 -3
  14. package/test/fixtures/shortcuts/hookshot-passthrough-compatible-legacy-node-runtimes.json +411 -0
  15. package/test/fixtures/shortcuts/hookshot-passthrough-enhanced-logging.json +3 -3
  16. package/test/fixtures/shortcuts/hookshot-passthrough-full-blown-logging.json +3 -3
  17. package/test/fixtures/shortcuts/hookshot-passthrough-logging.json +3 -3
  18. package/test/fixtures/shortcuts/hookshot-passthrough.json +3 -3
  19. package/test/shortcuts.test.js +46 -0
  20. package/.nyc_output/1983e39b-fcbb-4618-a9dd-36f2ec3b1532.json +0 -1
  21. package/.nyc_output/2c9b3698-f822-47f6-a941-eea13e638ffc.json +0 -1
@@ -0,0 +1,411 @@
1
+ {
2
+ "AWSTemplateFormatVersion": "2010-09-09",
3
+ "Metadata": {},
4
+ "Parameters": {},
5
+ "Rules": {},
6
+ "Mappings": {},
7
+ "Conditions": {},
8
+ "Resources": {
9
+ "PassApi": {
10
+ "Type": "AWS::ApiGateway::RestApi",
11
+ "Properties": {
12
+ "Name": {
13
+ "Fn::Sub": "${AWS::StackName}-webhook"
14
+ },
15
+ "FailOnWarnings": true,
16
+ "EndpointConfiguration": {
17
+ "Types": [
18
+ "REGIONAL"
19
+ ]
20
+ }
21
+ }
22
+ },
23
+ "PassStage": {
24
+ "Type": "AWS::ApiGateway::Stage",
25
+ "Properties": {
26
+ "DeploymentId": {
27
+ "Ref": "PassDeployment5dcf4ca7"
28
+ },
29
+ "StageName": "hookshot",
30
+ "RestApiId": {
31
+ "Ref": "PassApi"
32
+ },
33
+ "MethodSettings": [
34
+ {
35
+ "HttpMethod": "*",
36
+ "ResourcePath": "/*",
37
+ "ThrottlingBurstLimit": 20,
38
+ "ThrottlingRateLimit": 5,
39
+ "LoggingLevel": "OFF",
40
+ "DataTraceEnabled": false,
41
+ "MetricsEnabled": false
42
+ }
43
+ ]
44
+ }
45
+ },
46
+ "PassDeployment5dcf4ca7": {
47
+ "Type": "AWS::ApiGateway::Deployment",
48
+ "DependsOn": "PassMethod",
49
+ "Properties": {
50
+ "RestApiId": {
51
+ "Ref": "PassApi"
52
+ },
53
+ "StageName": "unused"
54
+ }
55
+ },
56
+ "PassResource": {
57
+ "Type": "AWS::ApiGateway::Resource",
58
+ "Properties": {
59
+ "ParentId": {
60
+ "Fn::GetAtt": [
61
+ "PassApi",
62
+ "RootResourceId"
63
+ ]
64
+ },
65
+ "RestApiId": {
66
+ "Ref": "PassApi"
67
+ },
68
+ "PathPart": "webhook"
69
+ }
70
+ },
71
+ "PassOptionsMethod": {
72
+ "Type": "AWS::ApiGateway::Method",
73
+ "Properties": {
74
+ "RestApiId": {
75
+ "Ref": "PassApi"
76
+ },
77
+ "ResourceId": {
78
+ "Ref": "PassResource"
79
+ },
80
+ "ApiKeyRequired": false,
81
+ "AuthorizationType": "NONE",
82
+ "HttpMethod": "OPTIONS",
83
+ "Integration": {
84
+ "Type": "AWS_PROXY",
85
+ "IntegrationHttpMethod": "POST",
86
+ "Uri": {
87
+ "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PassFunction.Arn}/invocations"
88
+ }
89
+ }
90
+ }
91
+ },
92
+ "PassMethod": {
93
+ "Type": "AWS::ApiGateway::Method",
94
+ "Properties": {
95
+ "RestApiId": {
96
+ "Ref": "PassApi"
97
+ },
98
+ "ResourceId": {
99
+ "Ref": "PassResource"
100
+ },
101
+ "ApiKeyRequired": false,
102
+ "AuthorizationType": "NONE",
103
+ "HttpMethod": "POST",
104
+ "Integration": {
105
+ "Type": "AWS_PROXY",
106
+ "IntegrationHttpMethod": "POST",
107
+ "Uri": {
108
+ "Fn::Sub": "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PassFunction.Arn}/invocations"
109
+ }
110
+ }
111
+ }
112
+ },
113
+ "PassPermission": {
114
+ "Type": "AWS::Lambda::Permission",
115
+ "Properties": {
116
+ "FunctionName": {
117
+ "Ref": "PassFunction"
118
+ },
119
+ "Action": "lambda:InvokeFunction",
120
+ "Principal": "apigateway.amazonaws.com",
121
+ "SourceArn": {
122
+ "Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${PassApi}/*"
123
+ }
124
+ }
125
+ },
126
+ "PassSecret": {
127
+ "Type": "AWS::ApiGateway::ApiKey",
128
+ "Properties": {
129
+ "Enabled": false
130
+ }
131
+ },
132
+ "PassFunctionLogs": {
133
+ "Type": "AWS::Logs::LogGroup",
134
+ "Properties": {
135
+ "LogGroupName": {
136
+ "Fn::Sub": [
137
+ "/aws/lambda/${name}",
138
+ {
139
+ "name": {
140
+ "Fn::Sub": "${AWS::StackName}-Pass"
141
+ }
142
+ }
143
+ ]
144
+ },
145
+ "RetentionInDays": 14
146
+ }
147
+ },
148
+ "PassFunction": {
149
+ "Type": "AWS::Lambda::Function",
150
+ "Properties": {
151
+ "Code": {
152
+ "ZipFile": {
153
+ "Fn::Sub": "const { InvokeCommand, LambdaClient } = require('@aws-sdk/client-lambda');\nconst client = new LambdaClient();\n\nmodule.exports.lambda = (event, context, callback) => {\n if (event.httpMethod === 'OPTIONS') {\n const requestHeaders = event.headers['Access-Control-Request-Headers'] || event.headers['access-control-request-headers'];\n const response = {\n statusCode: 200,\n body: '',\n headers: {\n 'Access-Control-Allow-Headers': requestHeaders,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Origin': '*'\n }\n };\n return callback(null, response);\n }\n\n const command = new InvokeCommand({\n FunctionName: '${Destination}',\n Payload: JSON.stringify(event)\n };\n\n lambda.invoke(lambdaParams).promise()\n .then((response) => {\n if (!response || !response.Payload)\n return callback(new Error('Your Lambda function Destination did not provide a payload'));\n\n var payload = JSON.parse(response.Payload);\n payload.headers = payload.headers || {};\n payload.headers['Access-Control-Allow-Origin'] = '*';\n callback(null, payload);\n })\n .catch((err) => callback(err));\n};"
154
+ }
155
+ },
156
+ "Description": {
157
+ "Fn::Sub": "Passthrough function for ${AWS::StackName}"
158
+ },
159
+ "FunctionName": {
160
+ "Fn::Sub": "${AWS::StackName}-Pass"
161
+ },
162
+ "Handler": "index.lambda",
163
+ "MemorySize": 128,
164
+ "Runtime": "nodejs16.x",
165
+ "Timeout": 30,
166
+ "Role": {
167
+ "Fn::GetAtt": [
168
+ "PassFunctionRole",
169
+ "Arn"
170
+ ]
171
+ }
172
+ }
173
+ },
174
+ "PassFunctionErrorAlarm": {
175
+ "Type": "AWS::CloudWatch::Alarm",
176
+ "Properties": {
177
+ "AlarmName": {
178
+ "Fn::Sub": "${AWS::StackName}-PassFunction-Errors-${AWS::Region}"
179
+ },
180
+ "AlarmDescription": {
181
+ "Fn::Sub": [
182
+ "Error alarm for ${name} lambda function in ${AWS::StackName} stack",
183
+ {
184
+ "name": {
185
+ "Fn::Sub": "${AWS::StackName}-Pass"
186
+ }
187
+ }
188
+ ]
189
+ },
190
+ "AlarmActions": [],
191
+ "Period": 60,
192
+ "EvaluationPeriods": 1,
193
+ "DatapointsToAlarm": 1,
194
+ "Statistic": "Sum",
195
+ "Threshold": 0,
196
+ "ComparisonOperator": "GreaterThanThreshold",
197
+ "TreatMissingData": "notBreaching",
198
+ "Namespace": "AWS/Lambda",
199
+ "Dimensions": [
200
+ {
201
+ "Name": "FunctionName",
202
+ "Value": {
203
+ "Ref": "PassFunction"
204
+ }
205
+ }
206
+ ],
207
+ "MetricName": "Errors"
208
+ }
209
+ },
210
+ "PassFunctionLogPolicy": {
211
+ "Type": "AWS::IAM::Policy",
212
+ "DependsOn": "PassFunctionRole",
213
+ "Properties": {
214
+ "PolicyName": "lambda-log-access",
215
+ "Roles": [
216
+ {
217
+ "Ref": "PassFunctionRole"
218
+ }
219
+ ],
220
+ "PolicyDocument": {
221
+ "Version": "2012-10-17",
222
+ "Statement": [
223
+ {
224
+ "Effect": "Allow",
225
+ "Action": "logs:*",
226
+ "Resource": {
227
+ "Fn::GetAtt": [
228
+ "PassFunctionLogs",
229
+ "Arn"
230
+ ]
231
+ }
232
+ }
233
+ ]
234
+ }
235
+ }
236
+ },
237
+ "PassFunctionRole": {
238
+ "Type": "AWS::IAM::Role",
239
+ "Properties": {
240
+ "AssumeRolePolicyDocument": {
241
+ "Statement": [
242
+ {
243
+ "Effect": "Allow",
244
+ "Action": "sts:AssumeRole",
245
+ "Principal": {
246
+ "Service": {
247
+ "Fn::Sub": "lambda.amazonaws.com"
248
+ }
249
+ }
250
+ }
251
+ ]
252
+ },
253
+ "Policies": [
254
+ {
255
+ "PolicyName": "main",
256
+ "PolicyDocument": {
257
+ "Version": "2012-10-17",
258
+ "Statement": [
259
+ {
260
+ "Effect": "Allow",
261
+ "Action": "lambda:InvokeFunction",
262
+ "Resource": {
263
+ "Fn::GetAtt": [
264
+ "Destination",
265
+ "Arn"
266
+ ]
267
+ }
268
+ }
269
+ ]
270
+ }
271
+ }
272
+ ]
273
+ }
274
+ },
275
+ "DestinationLogs": {
276
+ "Type": "AWS::Logs::LogGroup",
277
+ "Properties": {
278
+ "LogGroupName": {
279
+ "Fn::Sub": [
280
+ "/aws/lambda/${name}",
281
+ {
282
+ "name": {
283
+ "Fn::Sub": "${AWS::StackName}-Destination"
284
+ }
285
+ }
286
+ ]
287
+ },
288
+ "RetentionInDays": 14
289
+ }
290
+ },
291
+ "Destination": {
292
+ "Type": "AWS::Lambda::Function",
293
+ "Properties": {
294
+ "Code": {
295
+ "ZipFile": "module.exports.handler = (e, c, cb) => cb();"
296
+ },
297
+ "Description": {
298
+ "Fn::Sub": "Destination in the ${AWS::StackName} stack"
299
+ },
300
+ "FunctionName": {
301
+ "Fn::Sub": "${AWS::StackName}-Destination"
302
+ },
303
+ "Handler": "index.handler",
304
+ "MemorySize": 128,
305
+ "Runtime": "nodejs18.x",
306
+ "Timeout": 300,
307
+ "Role": {
308
+ "Fn::GetAtt": [
309
+ "DestinationRole",
310
+ "Arn"
311
+ ]
312
+ }
313
+ }
314
+ },
315
+ "DestinationErrorAlarm": {
316
+ "Type": "AWS::CloudWatch::Alarm",
317
+ "Properties": {
318
+ "AlarmName": {
319
+ "Fn::Sub": "${AWS::StackName}-Destination-Errors-${AWS::Region}"
320
+ },
321
+ "AlarmDescription": {
322
+ "Fn::Sub": [
323
+ "Error alarm for ${name} lambda function in ${AWS::StackName} stack",
324
+ {
325
+ "name": {
326
+ "Fn::Sub": "${AWS::StackName}-Destination"
327
+ }
328
+ }
329
+ ]
330
+ },
331
+ "AlarmActions": [],
332
+ "Period": 60,
333
+ "EvaluationPeriods": 5,
334
+ "DatapointsToAlarm": 1,
335
+ "Statistic": "Sum",
336
+ "Threshold": 0,
337
+ "ComparisonOperator": "GreaterThanThreshold",
338
+ "TreatMissingData": "notBreaching",
339
+ "Namespace": "AWS/Lambda",
340
+ "Dimensions": [
341
+ {
342
+ "Name": "FunctionName",
343
+ "Value": {
344
+ "Ref": "Destination"
345
+ }
346
+ }
347
+ ],
348
+ "MetricName": "Errors"
349
+ }
350
+ },
351
+ "DestinationLogPolicy": {
352
+ "Type": "AWS::IAM::Policy",
353
+ "DependsOn": "DestinationRole",
354
+ "Properties": {
355
+ "PolicyName": "lambda-log-access",
356
+ "Roles": [
357
+ {
358
+ "Ref": "DestinationRole"
359
+ }
360
+ ],
361
+ "PolicyDocument": {
362
+ "Version": "2012-10-17",
363
+ "Statement": [
364
+ {
365
+ "Effect": "Allow",
366
+ "Action": "logs:*",
367
+ "Resource": {
368
+ "Fn::GetAtt": [
369
+ "DestinationLogs",
370
+ "Arn"
371
+ ]
372
+ }
373
+ }
374
+ ]
375
+ }
376
+ }
377
+ },
378
+ "DestinationRole": {
379
+ "Type": "AWS::IAM::Role",
380
+ "Properties": {
381
+ "AssumeRolePolicyDocument": {
382
+ "Statement": [
383
+ {
384
+ "Effect": "Allow",
385
+ "Action": "sts:AssumeRole",
386
+ "Principal": {
387
+ "Service": {
388
+ "Fn::Sub": "lambda.amazonaws.com"
389
+ }
390
+ }
391
+ }
392
+ ]
393
+ }
394
+ }
395
+ }
396
+ },
397
+ "Outputs": {
398
+ "PassEndpointOutput": {
399
+ "Description": "The HTTPS endpoint used to send github webhooks",
400
+ "Value": {
401
+ "Fn::Sub": "https://${PassApi}.execute-api.${AWS::Region}.amazonaws.com/hookshot/webhook"
402
+ }
403
+ },
404
+ "PassSecretOutput": {
405
+ "Description": "A secret key to give Github to use when signing webhook requests",
406
+ "Value": {
407
+ "Ref": "PassSecret"
408
+ }
409
+ }
410
+ }
411
+ }
@@ -24,7 +24,7 @@
24
24
  "Type": "AWS::ApiGateway::Stage",
25
25
  "Properties": {
26
26
  "DeploymentId": {
27
- "Ref": "PassDeployment0e352c83"
27
+ "Ref": "PassDeployment467809dc"
28
28
  },
29
29
  "StageName": "hookshot",
30
30
  "RestApiId": {
@@ -43,7 +43,7 @@
43
43
  ]
44
44
  }
45
45
  },
46
- "PassDeployment0e352c83": {
46
+ "PassDeployment467809dc": {
47
47
  "Type": "AWS::ApiGateway::Deployment",
48
48
  "DependsOn": "PassMethod",
49
49
  "Properties": {
@@ -150,7 +150,7 @@
150
150
  "Properties": {
151
151
  "Code": {
152
152
  "ZipFile": {
153
- "Fn::Sub": "'use strict';\n\nconst AWS = require('aws-sdk');\nconst lambda = new AWS.Lambda();\n\nmodule.exports.lambda = (event, context, callback) => {\n if (event.httpMethod === 'OPTIONS') {\n const requestHeaders = event.headers['Access-Control-Request-Headers'] || event.headers['access-control-request-headers'];\n const response = {\n statusCode: 200,\n body: '',\n headers: {\n 'Access-Control-Allow-Headers': requestHeaders,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Origin': '*'\n }\n };\n return callback(null, response);\n }\n\n const lambdaParams = {\n FunctionName: '${Destination}',\n Payload: JSON.stringify(event)\n };\n\n lambda.invoke(lambdaParams).promise()\n .then((response) => {\n if (!response || !response.Payload)\n return callback(new Error('Your Lambda function Destination did not provide a payload'));\n\n var payload = JSON.parse(response.Payload);\n payload.headers = payload.headers || {};\n payload.headers['Access-Control-Allow-Origin'] = '*';\n callback(null, payload);\n })\n .catch((err) => callback(err));\n};"
153
+ "Fn::Sub": "const { InvokeCommand, LambdaClient } = require('@aws-sdk/client-lambda');\nconst client = new LambdaClient();\n\nmodule.exports.lambda = (event, context, callback) => {\n if (event.httpMethod === 'OPTIONS') {\n const requestHeaders = event.headers['Access-Control-Request-Headers'] || event.headers['access-control-request-headers'];\n const response = {\n statusCode: 200,\n body: '',\n headers: {\n 'Access-Control-Allow-Headers': requestHeaders,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Origin': '*'\n }\n };\n return callback(null, response);\n }\n\n const command = new InvokeCommand({\n FunctionName: '${Destination}',\n Payload: JSON.stringify(event)\n });\n\n client.send(command)\n .then((response) => {\n if (!response || !response.Payload)\n return callback(new Error('Your Lambda function Destination did not provide a payload'));\n\n var payload = JSON.parse(Buffer.from(response.Payload).toString());\n payload.headers = payload.headers || {};\n payload.headers['Access-Control-Allow-Origin'] = '*';\n callback(null, payload);\n })\n .catch((err) => callback(err));\n};"
154
154
  }
155
155
  },
156
156
  "Description": {
@@ -24,7 +24,7 @@
24
24
  "Type": "AWS::ApiGateway::Stage",
25
25
  "Properties": {
26
26
  "DeploymentId": {
27
- "Ref": "PassDeployment0e352c83"
27
+ "Ref": "PassDeployment467809dc"
28
28
  },
29
29
  "StageName": "hookshot",
30
30
  "RestApiId": {
@@ -43,7 +43,7 @@
43
43
  ]
44
44
  }
45
45
  },
46
- "PassDeployment0e352c83": {
46
+ "PassDeployment467809dc": {
47
47
  "Type": "AWS::ApiGateway::Deployment",
48
48
  "DependsOn": "PassMethod",
49
49
  "Properties": {
@@ -150,7 +150,7 @@
150
150
  "Properties": {
151
151
  "Code": {
152
152
  "ZipFile": {
153
- "Fn::Sub": "'use strict';\n\nconst AWS = require('aws-sdk');\nconst lambda = new AWS.Lambda();\n\nmodule.exports.lambda = (event, context, callback) => {\n if (event.httpMethod === 'OPTIONS') {\n const requestHeaders = event.headers['Access-Control-Request-Headers'] || event.headers['access-control-request-headers'];\n const response = {\n statusCode: 200,\n body: '',\n headers: {\n 'Access-Control-Allow-Headers': requestHeaders,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Origin': '*'\n }\n };\n return callback(null, response);\n }\n\n const lambdaParams = {\n FunctionName: '${Destination}',\n Payload: JSON.stringify(event)\n };\n\n lambda.invoke(lambdaParams).promise()\n .then((response) => {\n if (!response || !response.Payload)\n return callback(new Error('Your Lambda function Destination did not provide a payload'));\n\n var payload = JSON.parse(response.Payload);\n payload.headers = payload.headers || {};\n payload.headers['Access-Control-Allow-Origin'] = '*';\n callback(null, payload);\n })\n .catch((err) => callback(err));\n};"
153
+ "Fn::Sub": "const { InvokeCommand, LambdaClient } = require('@aws-sdk/client-lambda');\nconst client = new LambdaClient();\n\nmodule.exports.lambda = (event, context, callback) => {\n if (event.httpMethod === 'OPTIONS') {\n const requestHeaders = event.headers['Access-Control-Request-Headers'] || event.headers['access-control-request-headers'];\n const response = {\n statusCode: 200,\n body: '',\n headers: {\n 'Access-Control-Allow-Headers': requestHeaders,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Origin': '*'\n }\n };\n return callback(null, response);\n }\n\n const command = new InvokeCommand({\n FunctionName: '${Destination}',\n Payload: JSON.stringify(event)\n });\n\n client.send(command)\n .then((response) => {\n if (!response || !response.Payload)\n return callback(new Error('Your Lambda function Destination did not provide a payload'));\n\n var payload = JSON.parse(Buffer.from(response.Payload).toString());\n payload.headers = payload.headers || {};\n payload.headers['Access-Control-Allow-Origin'] = '*';\n callback(null, payload);\n })\n .catch((err) => callback(err));\n};"
154
154
  }
155
155
  },
156
156
  "Description": {
@@ -24,7 +24,7 @@
24
24
  "Type": "AWS::ApiGateway::Stage",
25
25
  "Properties": {
26
26
  "DeploymentId": {
27
- "Ref": "PassDeployment0e352c83"
27
+ "Ref": "PassDeployment467809dc"
28
28
  },
29
29
  "StageName": "hookshot",
30
30
  "RestApiId": {
@@ -43,7 +43,7 @@
43
43
  ]
44
44
  }
45
45
  },
46
- "PassDeployment0e352c83": {
46
+ "PassDeployment467809dc": {
47
47
  "Type": "AWS::ApiGateway::Deployment",
48
48
  "DependsOn": "PassMethod",
49
49
  "Properties": {
@@ -150,7 +150,7 @@
150
150
  "Properties": {
151
151
  "Code": {
152
152
  "ZipFile": {
153
- "Fn::Sub": "'use strict';\n\nconst AWS = require('aws-sdk');\nconst lambda = new AWS.Lambda();\n\nmodule.exports.lambda = (event, context, callback) => {\n if (event.httpMethod === 'OPTIONS') {\n const requestHeaders = event.headers['Access-Control-Request-Headers'] || event.headers['access-control-request-headers'];\n const response = {\n statusCode: 200,\n body: '',\n headers: {\n 'Access-Control-Allow-Headers': requestHeaders,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Origin': '*'\n }\n };\n return callback(null, response);\n }\n\n const lambdaParams = {\n FunctionName: '${Destination}',\n Payload: JSON.stringify(event)\n };\n\n lambda.invoke(lambdaParams).promise()\n .then((response) => {\n if (!response || !response.Payload)\n return callback(new Error('Your Lambda function Destination did not provide a payload'));\n\n var payload = JSON.parse(response.Payload);\n payload.headers = payload.headers || {};\n payload.headers['Access-Control-Allow-Origin'] = '*';\n callback(null, payload);\n })\n .catch((err) => callback(err));\n};"
153
+ "Fn::Sub": "const { InvokeCommand, LambdaClient } = require('@aws-sdk/client-lambda');\nconst client = new LambdaClient();\n\nmodule.exports.lambda = (event, context, callback) => {\n if (event.httpMethod === 'OPTIONS') {\n const requestHeaders = event.headers['Access-Control-Request-Headers'] || event.headers['access-control-request-headers'];\n const response = {\n statusCode: 200,\n body: '',\n headers: {\n 'Access-Control-Allow-Headers': requestHeaders,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Origin': '*'\n }\n };\n return callback(null, response);\n }\n\n const command = new InvokeCommand({\n FunctionName: '${Destination}',\n Payload: JSON.stringify(event)\n });\n\n client.send(command)\n .then((response) => {\n if (!response || !response.Payload)\n return callback(new Error('Your Lambda function Destination did not provide a payload'));\n\n var payload = JSON.parse(Buffer.from(response.Payload).toString());\n payload.headers = payload.headers || {};\n payload.headers['Access-Control-Allow-Origin'] = '*';\n callback(null, payload);\n })\n .catch((err) => callback(err));\n};"
154
154
  }
155
155
  },
156
156
  "Description": {
@@ -24,7 +24,7 @@
24
24
  "Type": "AWS::ApiGateway::Stage",
25
25
  "Properties": {
26
26
  "DeploymentId": {
27
- "Ref": "PassDeployment0e352c83"
27
+ "Ref": "PassDeployment467809dc"
28
28
  },
29
29
  "StageName": "hookshot",
30
30
  "RestApiId": {
@@ -43,7 +43,7 @@
43
43
  ]
44
44
  }
45
45
  },
46
- "PassDeployment0e352c83": {
46
+ "PassDeployment467809dc": {
47
47
  "Type": "AWS::ApiGateway::Deployment",
48
48
  "DependsOn": "PassMethod",
49
49
  "Properties": {
@@ -150,7 +150,7 @@
150
150
  "Properties": {
151
151
  "Code": {
152
152
  "ZipFile": {
153
- "Fn::Sub": "'use strict';\n\nconst AWS = require('aws-sdk');\nconst lambda = new AWS.Lambda();\n\nmodule.exports.lambda = (event, context, callback) => {\n if (event.httpMethod === 'OPTIONS') {\n const requestHeaders = event.headers['Access-Control-Request-Headers'] || event.headers['access-control-request-headers'];\n const response = {\n statusCode: 200,\n body: '',\n headers: {\n 'Access-Control-Allow-Headers': requestHeaders,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Origin': '*'\n }\n };\n return callback(null, response);\n }\n\n const lambdaParams = {\n FunctionName: '${Destination}',\n Payload: JSON.stringify(event)\n };\n\n lambda.invoke(lambdaParams).promise()\n .then((response) => {\n if (!response || !response.Payload)\n return callback(new Error('Your Lambda function Destination did not provide a payload'));\n\n var payload = JSON.parse(response.Payload);\n payload.headers = payload.headers || {};\n payload.headers['Access-Control-Allow-Origin'] = '*';\n callback(null, payload);\n })\n .catch((err) => callback(err));\n};"
153
+ "Fn::Sub": "const { InvokeCommand, LambdaClient } = require('@aws-sdk/client-lambda');\nconst client = new LambdaClient();\n\nmodule.exports.lambda = (event, context, callback) => {\n if (event.httpMethod === 'OPTIONS') {\n const requestHeaders = event.headers['Access-Control-Request-Headers'] || event.headers['access-control-request-headers'];\n const response = {\n statusCode: 200,\n body: '',\n headers: {\n 'Access-Control-Allow-Headers': requestHeaders,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Origin': '*'\n }\n };\n return callback(null, response);\n }\n\n const command = new InvokeCommand({\n FunctionName: '${Destination}',\n Payload: JSON.stringify(event)\n });\n\n client.send(command)\n .then((response) => {\n if (!response || !response.Payload)\n return callback(new Error('Your Lambda function Destination did not provide a payload'));\n\n var payload = JSON.parse(Buffer.from(response.Payload).toString());\n payload.headers = payload.headers || {};\n payload.headers['Access-Control-Allow-Origin'] = '*';\n callback(null, payload);\n })\n .catch((err) => callback(err));\n};"
154
154
  }
155
155
  },
156
156
  "Description": {
@@ -1442,6 +1442,30 @@ test('[shortcuts] hookshot passthrough', (assert) => {
1442
1442
  'throws with invalid LoggingLevel'
1443
1443
  );
1444
1444
 
1445
+ assert.throws(
1446
+ () =>
1447
+ new cf.shortcuts.hookshot.Passthrough({
1448
+ Prefix: 'Pass',
1449
+ PassthroughTo: 'Destination',
1450
+ LoggingLevel: 'INFO',
1451
+ Runtime: 'python3.7'
1452
+ }),
1453
+ /Only valid nodejs runtimes are supported for hookshot lambdas, received: 'python3.7'/,
1454
+ 'throws with invalid lambda Runtime python3.7'
1455
+ );
1456
+
1457
+ assert.throws(
1458
+ () =>
1459
+ new cf.shortcuts.hookshot.Passthrough({
1460
+ Prefix: 'Pass',
1461
+ PassthroughTo: 'Destination',
1462
+ LoggingLevel: 'INFO',
1463
+ Runtime: 'nodejs16.x'
1464
+ }),
1465
+ /Only nodejs runtimes >= 18 are supported for hookshot lambdas, received: 'nodejs16.x'/,
1466
+ 'throws with invalid lambda Runtime nodejs16.x'
1467
+ );
1468
+
1445
1469
  const to = new cf.shortcuts.Lambda({
1446
1470
  LogicalName: 'Destination',
1447
1471
  Code: {
@@ -1550,6 +1574,28 @@ test('[shortcuts] hookshot github', (assert) => {
1550
1574
  'throws without required parameters'
1551
1575
  );
1552
1576
 
1577
+ assert.throws(
1578
+ () =>
1579
+ new cf.shortcuts.hookshot.Github({
1580
+ Prefix: 'Pass',
1581
+ PassthroughTo: 'Destination',
1582
+ Runtime: 'python3.7'
1583
+ }),
1584
+ /Only valid nodejs runtimes are supported for hookshot lambdas, received: 'python3.7'/,
1585
+ 'throws with invalid lambda Runtime python3.7'
1586
+ );
1587
+
1588
+ assert.throws(
1589
+ () =>
1590
+ new cf.shortcuts.hookshot.Github({
1591
+ Prefix: 'Pass',
1592
+ PassthroughTo: 'Destination',
1593
+ Runtime: 'nodejs16.x'
1594
+ }),
1595
+ /Only nodejs runtimes >= 18 are supported for hookshot lambdas, received: 'nodejs16.x'/,
1596
+ 'throws with invalid lambda Runtime nodejs16.x'
1597
+ );
1598
+
1553
1599
  const to = new cf.shortcuts.Lambda({
1554
1600
  LogicalName: 'Destination',
1555
1601
  Code: {