serverless-offline 11.1.1 → 11.1.3
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/package.json +6 -6
- package/src/ServerlessOffline.js +66 -50
- package/src/events/http/Http.js +15 -1
- package/src/events/http/HttpServer.js +4 -7
- package/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js +2 -0
- package/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +2 -0
- package/src/events/schedule/ScheduleEventDefinition.js +1 -1
- package/src/lambda/routes/invocations/invocationsRoute.js +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dedicatedTo": "Blue, a great migrating bird.",
|
|
3
3
|
"name": "serverless-offline",
|
|
4
|
-
"version": "11.1.
|
|
4
|
+
"version": "11.1.3",
|
|
5
5
|
"description": "Emulate AWS λ and API Gateway locally when developing your Serverless project",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"exports": {
|
|
@@ -85,10 +85,10 @@
|
|
|
85
85
|
"@hapi/boom": "^10.0.0",
|
|
86
86
|
"@hapi/h2o2": "^10.0.0",
|
|
87
87
|
"@hapi/hapi": "^20.2.2",
|
|
88
|
-
"@serverless/utils": "^6.
|
|
89
|
-
"aws-sdk": "^2.
|
|
88
|
+
"@serverless/utils": "^6.8.0",
|
|
89
|
+
"aws-sdk": "^2.1233.0",
|
|
90
90
|
"boxen": "^7.0.0",
|
|
91
|
-
"chalk": "^5.1.
|
|
91
|
+
"chalk": "^5.1.2",
|
|
92
92
|
"execa": "^6.1.0",
|
|
93
93
|
"fs-extra": "^10.1.0",
|
|
94
94
|
"java-invoke-local": "0.0.6",
|
|
@@ -117,10 +117,10 @@
|
|
|
117
117
|
"git-list-updated": "^1.2.1",
|
|
118
118
|
"husky": "^8.0.1",
|
|
119
119
|
"lint-staged": "^13.0.3",
|
|
120
|
-
"mocha": "^10.
|
|
120
|
+
"mocha": "^10.1.0",
|
|
121
121
|
"nyc": "^15.1.0",
|
|
122
122
|
"prettier": "^2.7.1",
|
|
123
|
-
"serverless": "^3.
|
|
123
|
+
"serverless": "^3.23.0",
|
|
124
124
|
"standard-version": "^9.5.0"
|
|
125
125
|
},
|
|
126
126
|
"peerDependencies": {
|
package/src/ServerlessOffline.js
CHANGED
|
@@ -61,8 +61,13 @@ export default class ServerlessOffline {
|
|
|
61
61
|
async start() {
|
|
62
62
|
this.#mergeOptions()
|
|
63
63
|
|
|
64
|
-
const {
|
|
65
|
-
|
|
64
|
+
const {
|
|
65
|
+
httpEvents,
|
|
66
|
+
httpApiEvents,
|
|
67
|
+
lambdas,
|
|
68
|
+
scheduleEvents,
|
|
69
|
+
webSocketEvents,
|
|
70
|
+
} = this.#getEvents()
|
|
66
71
|
|
|
67
72
|
if (lambdas.length > 0) {
|
|
68
73
|
await this.#createLambda(lambdas)
|
|
@@ -70,8 +75,8 @@ export default class ServerlessOffline {
|
|
|
70
75
|
|
|
71
76
|
const eventModules = []
|
|
72
77
|
|
|
73
|
-
if (httpEvents.length > 0) {
|
|
74
|
-
eventModules.push(this.#createHttp(httpEvents))
|
|
78
|
+
if (httpApiEvents.length > 0 || httpEvents.length > 0) {
|
|
79
|
+
eventModules.push(this.#createHttp([...httpApiEvents, ...httpEvents]))
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
if (scheduleEvents.length > 0) {
|
|
@@ -259,6 +264,7 @@ export default class ServerlessOffline {
|
|
|
259
264
|
const { service } = this.#serverless
|
|
260
265
|
|
|
261
266
|
const httpEvents = []
|
|
267
|
+
const httpApiEvents = []
|
|
262
268
|
const lambdas = []
|
|
263
269
|
const scheduleEvents = []
|
|
264
270
|
const webSocketEvents = []
|
|
@@ -275,66 +281,75 @@ export default class ServerlessOffline {
|
|
|
275
281
|
events.forEach((event) => {
|
|
276
282
|
const { http, httpApi, schedule, websocket } = event
|
|
277
283
|
|
|
278
|
-
if (
|
|
284
|
+
if (http && functionDefinition.handler) {
|
|
279
285
|
const httpEvent = {
|
|
280
286
|
functionKey,
|
|
281
287
|
handler: functionDefinition.handler,
|
|
282
|
-
http
|
|
288
|
+
http,
|
|
283
289
|
}
|
|
284
290
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
} else {
|
|
305
|
-
const resolvedMethod =
|
|
306
|
-
httpEvent.http.method === '*'
|
|
307
|
-
? 'ANY'
|
|
308
|
-
: httpEvent.http.method.toUpperCase()
|
|
309
|
-
httpEvent.http.routeKey = `${resolvedMethod} ${httpEvent.http.path}`
|
|
310
|
-
}
|
|
311
|
-
// Clear these properties to avoid confusion (they will be derived from the routeKey
|
|
312
|
-
// when needed later)
|
|
313
|
-
delete httpEvent.http.method
|
|
314
|
-
delete httpEvent.http.path
|
|
315
|
-
} else {
|
|
291
|
+
httpEvents.push(httpEvent)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (httpApi && functionDefinition.handler) {
|
|
295
|
+
const httpApiEvent = {
|
|
296
|
+
functionKey,
|
|
297
|
+
handler: functionDefinition.handler,
|
|
298
|
+
http: httpApi,
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Ensure definitions for 'httpApi' events are objects so that they can be marked
|
|
302
|
+
// with an 'isHttpApi' property (they are handled differently to 'http' events)
|
|
303
|
+
if (typeof httpApiEvent.http === 'string') {
|
|
304
|
+
httpApiEvent.http = {
|
|
305
|
+
routeKey:
|
|
306
|
+
httpApiEvent.http === '*' ? '$default' : httpApiEvent.http,
|
|
307
|
+
}
|
|
308
|
+
} else if (typeof httpApiEvent.http === 'object') {
|
|
309
|
+
if (!httpApiEvent.http.method) {
|
|
316
310
|
log.warning(
|
|
317
|
-
`Event definition
|
|
311
|
+
`Event definition is missing a method for function "${functionKey}"`,
|
|
318
312
|
)
|
|
319
|
-
|
|
313
|
+
httpApiEvent.http.method = ''
|
|
320
314
|
}
|
|
321
|
-
|
|
322
|
-
httpEvent.http.isHttpApi = true
|
|
323
|
-
|
|
324
315
|
if (
|
|
325
|
-
|
|
326
|
-
|
|
316
|
+
httpApiEvent.http.method === '*' &&
|
|
317
|
+
httpApiEvent.http.path === '*'
|
|
327
318
|
) {
|
|
328
|
-
|
|
319
|
+
httpApiEvent.http.routeKey = '$default'
|
|
329
320
|
} else {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
?
|
|
333
|
-
:
|
|
321
|
+
const resolvedMethod =
|
|
322
|
+
httpApiEvent.http.method === '*'
|
|
323
|
+
? 'ANY'
|
|
324
|
+
: httpApiEvent.http.method.toUpperCase()
|
|
325
|
+
httpApiEvent.http.routeKey = `${resolvedMethod} ${httpApiEvent.http.path}`
|
|
334
326
|
}
|
|
327
|
+
// Clear these properties to avoid confusion (they will be derived from the routeKey
|
|
328
|
+
// when needed later)
|
|
329
|
+
delete httpApiEvent.http.method
|
|
330
|
+
delete httpApiEvent.http.path
|
|
331
|
+
} else {
|
|
332
|
+
log.warning(
|
|
333
|
+
`Event definition must be a string or object but received ${typeof httpApiEvent.http} for function "${functionKey}"`,
|
|
334
|
+
)
|
|
335
|
+
httpApiEvent.http.routeKey = ''
|
|
335
336
|
}
|
|
336
337
|
|
|
337
|
-
|
|
338
|
+
httpApiEvent.http.isHttpApi = true
|
|
339
|
+
|
|
340
|
+
if (
|
|
341
|
+
functionDefinition.httpApi &&
|
|
342
|
+
functionDefinition.httpApi.payload
|
|
343
|
+
) {
|
|
344
|
+
httpApiEvent.http.payload = functionDefinition.httpApi.payload
|
|
345
|
+
} else {
|
|
346
|
+
httpApiEvent.http.payload =
|
|
347
|
+
service.provider.httpApi && service.provider.httpApi.payload
|
|
348
|
+
? service.provider.httpApi.payload
|
|
349
|
+
: '2.0'
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
httpApiEvents.push(httpApiEvent)
|
|
338
353
|
}
|
|
339
354
|
|
|
340
355
|
if (schedule) {
|
|
@@ -354,6 +369,7 @@ export default class ServerlessOffline {
|
|
|
354
369
|
})
|
|
355
370
|
|
|
356
371
|
return {
|
|
372
|
+
httpApiEvents,
|
|
357
373
|
httpEvents,
|
|
358
374
|
lambdas,
|
|
359
375
|
scheduleEvents,
|
package/src/events/http/Http.js
CHANGED
|
@@ -4,8 +4,16 @@ import HttpServer from './HttpServer.js'
|
|
|
4
4
|
export default class Http {
|
|
5
5
|
#httpServer = null
|
|
6
6
|
|
|
7
|
+
#lambda = null
|
|
8
|
+
|
|
9
|
+
#options = null
|
|
10
|
+
|
|
11
|
+
#serverless = null
|
|
12
|
+
|
|
7
13
|
constructor(serverless, options, lambda) {
|
|
8
|
-
this.#
|
|
14
|
+
this.#lambda = lambda
|
|
15
|
+
this.#options = options
|
|
16
|
+
this.#serverless = serverless
|
|
9
17
|
}
|
|
10
18
|
|
|
11
19
|
start() {
|
|
@@ -18,6 +26,12 @@ export default class Http {
|
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
async createServer() {
|
|
29
|
+
this.#httpServer = new HttpServer(
|
|
30
|
+
this.#serverless,
|
|
31
|
+
this.#options,
|
|
32
|
+
this.#lambda,
|
|
33
|
+
)
|
|
34
|
+
|
|
21
35
|
await this.#httpServer.createServer()
|
|
22
36
|
}
|
|
23
37
|
|
|
@@ -459,12 +459,12 @@ export default class HttpServer {
|
|
|
459
459
|
|
|
460
460
|
// default request template to '' if we don't have a definition pushed in from serverless or endpoint
|
|
461
461
|
const requestTemplate =
|
|
462
|
-
|
|
462
|
+
requestTemplates !== undefined && integration === 'AWS'
|
|
463
463
|
? requestTemplates[contentType]
|
|
464
464
|
: ''
|
|
465
465
|
|
|
466
466
|
const schemas =
|
|
467
|
-
|
|
467
|
+
endpoint?.request?.schemas !== undefined
|
|
468
468
|
? endpoint.request.schemas[contentType]
|
|
469
469
|
: ''
|
|
470
470
|
|
|
@@ -647,10 +647,7 @@ export default class HttpServer {
|
|
|
647
647
|
headerValue = valueArray[3]
|
|
648
648
|
? jsonPath(result, valueArray.slice(3).join('.'))
|
|
649
649
|
: result
|
|
650
|
-
if (
|
|
651
|
-
typeof headerValue === 'undefined' ||
|
|
652
|
-
headerValue === null
|
|
653
|
-
) {
|
|
650
|
+
if (headerValue === undefined || headerValue === null) {
|
|
654
651
|
headerValue = ''
|
|
655
652
|
} else {
|
|
656
653
|
headerValue = headerValue.toString()
|
|
@@ -857,7 +854,7 @@ export default class HttpServer {
|
|
|
857
854
|
|
|
858
855
|
if (typeof result === 'string') {
|
|
859
856
|
response.source = stringify(result)
|
|
860
|
-
} else if (result &&
|
|
857
|
+
} else if (result && result.body !== undefined) {
|
|
861
858
|
if (result.isBase64Encoded) {
|
|
862
859
|
response.encoding = 'binary'
|
|
863
860
|
response.source = Buffer.from(result.body, 'base64')
|
|
@@ -9,7 +9,7 @@ export default class ScheduleEventDefinition {
|
|
|
9
9
|
if (typeof rawHttpEventDefinition === 'string') {
|
|
10
10
|
rate = rawHttpEventDefinition
|
|
11
11
|
} else {
|
|
12
|
-
;({
|
|
12
|
+
;({ enabled, rate, ...rest } = rawHttpEventDefinition)
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
// enabled: true (default)
|
|
@@ -43,7 +43,7 @@ export default function invocationsRoute(lambda, options) {
|
|
|
43
43
|
let statusCode = 200
|
|
44
44
|
let functionError = null
|
|
45
45
|
if (invokeResults) {
|
|
46
|
-
const isPayloadDefined =
|
|
46
|
+
const isPayloadDefined = invokeResults.Payload !== undefined
|
|
47
47
|
resultPayload = isPayloadDefined ? invokeResults.Payload : ''
|
|
48
48
|
statusCode = invokeResults.StatusCode || 200
|
|
49
49
|
functionError = invokeResults.FunctionError || null
|