serverless-offline 9.1.4 → 9.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "dedicatedTo": "Blue, a great migrating bird.",
3
3
  "name": "serverless-offline",
4
- "version": "9.1.4",
4
+ "version": "9.1.7",
5
5
  "description": "Emulate AWS λ and API Gateway locally when developing your Serverless project",
6
6
  "license": "MIT",
7
7
  "main": "./src/index.js",
@@ -23,38 +23,38 @@ export default class ServerlessOffline {
23
23
 
24
24
  #webSocket = null
25
25
 
26
- constructor(serverless, cliOptions) {
27
- this.#cliOptions = cliOptions
28
- this.#serverless = serverless
29
-
30
- this.commands = {
31
- offline: {
32
- // add start nested options
33
- commands: {
34
- functionsUpdated: {
35
- lifecycleEvents: ['cleanup'],
36
- type: 'entrypoint',
37
- },
38
- start: {
39
- lifecycleEvents: ['init', 'ready', 'end'],
40
- options: commandOptions,
41
- usage:
42
- 'Simulates API Gateway to call your lambda functions offline using backward compatible initialization.',
43
- },
26
+ commands = {
27
+ offline: {
28
+ // add start nested options
29
+ commands: {
30
+ functionsUpdated: {
31
+ lifecycleEvents: ['cleanup'],
32
+ type: 'entrypoint',
33
+ },
34
+ start: {
35
+ lifecycleEvents: ['init', 'ready', 'end'],
36
+ options: commandOptions,
37
+ usage:
38
+ 'Simulates API Gateway to call your lambda functions offline using backward compatible initialization.',
44
39
  },
45
- lifecycleEvents: ['start'],
46
- options: commandOptions,
47
- usage: 'Simulates API Gateway to call your lambda functions offline.',
48
40
  },
49
- }
41
+ lifecycleEvents: ['start'],
42
+ options: commandOptions,
43
+ usage: 'Simulates API Gateway to call your lambda functions offline.',
44
+ },
45
+ }
50
46
 
51
- this.hooks = {
52
- 'offline:functionsUpdated:cleanup': this.#cleanupFunctions.bind(this),
53
- 'offline:start': this.#startWithExplicitEnd.bind(this),
54
- 'offline:start:end': this.end.bind(this),
55
- 'offline:start:init': this.start.bind(this),
56
- 'offline:start:ready': this.#ready.bind(this),
57
- }
47
+ hooks = {
48
+ 'offline:functionsUpdated:cleanup': this.#cleanupFunctions.bind(this),
49
+ 'offline:start': this.#startWithExplicitEnd.bind(this),
50
+ 'offline:start:end': this.end.bind(this),
51
+ 'offline:start:init': this.start.bind(this),
52
+ 'offline:start:ready': this.#ready.bind(this),
53
+ }
54
+
55
+ constructor(serverless, cliOptions) {
56
+ this.#cliOptions = cliOptions
57
+ this.#serverless = serverless
58
58
  }
59
59
 
60
60
  // Entry point for the plugin (sls offline) when running 'sls offline start'
@@ -17,7 +17,7 @@ export default {
17
17
  hideStackTraces: false,
18
18
  host: 'localhost',
19
19
  httpPort: 3000,
20
- httpsProtocol: '',
20
+ httpsProtocol: null,
21
21
  lambdaPort: 3002,
22
22
  layersDir: null,
23
23
  localEnvironment: false,
@@ -49,6 +49,18 @@ export default class HttpServer {
49
49
  this.#serverless = serverless
50
50
  }
51
51
 
52
+ async #loadCerts(httpsProtocol) {
53
+ const [cert, key] = await Promise.all([
54
+ readFile(resolve(httpsProtocol, 'cert.pem'), 'utf-8'),
55
+ readFile(resolve(httpsProtocol, 'key.pem'), 'utf-8'),
56
+ ])
57
+
58
+ return {
59
+ cert,
60
+ key,
61
+ }
62
+ }
63
+
52
64
  async createServer() {
53
65
  const {
54
66
  enforceSecureCookies,
@@ -77,14 +89,10 @@ export default class HttpServer {
77
89
  isSameSite: false,
78
90
  isSecure: false,
79
91
  },
80
- }
81
-
82
- // HTTPS support
83
- if (typeof httpsProtocol === 'string' && httpsProtocol.length > 0) {
84
- serverOptions.tls = {
85
- cert: readFile(resolve(httpsProtocol, 'cert.pem'), 'ascii'),
86
- key: readFile(resolve(httpsProtocol, 'key.pem'), 'ascii'),
87
- }
92
+ // https support
93
+ ...(httpsProtocol != null && {
94
+ tls: await this.#loadCerts(httpsProtocol),
95
+ }),
88
96
  }
89
97
 
90
98
  // Hapijs server creation
@@ -103,7 +111,9 @@ export default class HttpServer {
103
111
  ? request.response.output
104
112
  : request.response
105
113
 
106
- const explicitlySetHeaders = { ...response.headers }
114
+ const explicitlySetHeaders = {
115
+ ...response.headers,
116
+ }
107
117
 
108
118
  if (
109
119
  this.#serverless.service.provider.httpApi &&
@@ -1010,7 +1020,9 @@ export default class HttpServer {
1010
1020
  auth: authStrategyName,
1011
1021
  cors,
1012
1022
  state,
1013
- timeout: { socket: false },
1023
+ timeout: {
1024
+ socket: false,
1025
+ },
1014
1026
  }
1015
1027
 
1016
1028
  // skip HEAD routes as hapi will fail with 'Method name not allowed: HEAD ...'
@@ -146,7 +146,10 @@ export default class LambdaProxyIntegrationEvent {
146
146
  const httpMethod = method.toUpperCase()
147
147
  const requestTime = formatToClfTime(received)
148
148
  const requestTimeEpoch = received
149
- const resource = this.#routeKey || route.path.replace(`/${this.#stage}`, '')
149
+ // NOTE replace * added by generateHapiPath util so api gateway event is accurate
150
+ const resource =
151
+ this.#routeKey ||
152
+ route.path.replace(`/${this.#stage}`, '').replace('*', '+')
150
153
 
151
154
  return {
152
155
  body,
@@ -1,18 +1,26 @@
1
1
  import { createUniqueId } from '../../utils/index.js'
2
2
 
3
3
  export default class ScheduleEvent {
4
- constructor(region) {
5
- // format of aws displaying the time, e.g.: 2020-02-09T14:13:57Z
6
- const time = new Date().toISOString().replace(/\.(.*)(?=Z)/g, '')
4
+ account = createUniqueId()
5
+
6
+ detail = {};
7
+
8
+ ['detail-type'] = 'Scheduled Event'
9
+
10
+ id = createUniqueId()
11
+
12
+ region = null
7
13
 
8
- this.account = createUniqueId()
9
- this.detail = {}
10
- this['detail-type'] = 'Scheduled Event'
11
- this.id = createUniqueId()
14
+ resources = []
15
+
16
+ source = 'aws.events'
17
+
18
+ // format of aws displaying the time, e.g.: 2020-02-09T14:13:57Z
19
+ time = new Date().toISOString().replace(/\.(.*)(?=Z)/g, '')
20
+
21
+ version = '0'
22
+
23
+ constructor(region) {
12
24
  this.region = region
13
- this.resources = []
14
- this.source = 'aws.events'
15
- this.time = time
16
- this.version = '0'
17
25
  }
18
26
  }
@@ -50,8 +50,8 @@ export default class HttpServer {
50
50
  }
51
51
 
52
52
  log.notice(
53
- `Offline [http for websocket] listening on http${
54
- httpsProtocol ? 's' : ''
53
+ `Offline [http for websocket] listening on ${
54
+ httpsProtocol ? 'https' : 'http'
55
55
  }://${host}:${websocketPort}`,
56
56
  )
57
57
  }
@@ -58,8 +58,8 @@ export default class WebSocketServer {
58
58
  const { host, httpsProtocol, websocketPort } = this.#options
59
59
 
60
60
  log.notice(
61
- `Offline [websocket] listening on ws${
62
- httpsProtocol ? 's' : ''
61
+ `Offline [websocket] listening on ${
62
+ httpsProtocol ? 'wss' : 'ws'
63
63
  }://${host}:${websocketPort}`,
64
64
  )
65
65
  }
@@ -37,7 +37,7 @@ export default class WebSocketConnectEvent {
37
37
  // 'X-Amzn-Trace-Id': `Root=${createUniqueId()}`,
38
38
  // 'X-Forwarded-For': '127.0.0.1',
39
39
  // 'X-Forwarded-Port': String(this.#websocketPort),
40
- // 'X-Forwarded-Proto': `http${this.#httpsProtocol ? 's' : ''}`,
40
+ // 'X-Forwarded-Proto': ${httpsProtocol ? 'https' : 'http'},
41
41
  // }
42
42
 
43
43
  const headers = parseHeaders(this.#rawHeaders)
@@ -44,13 +44,15 @@ export default class HttpServer {
44
44
  }
45
45
 
46
46
  log.notice(
47
- `Offline [http for lambda] listening on http${
48
- httpsProtocol ? 's' : ''
47
+ `Offline [http for lambda] listening on ${
48
+ httpsProtocol ? 'https' : 'http'
49
49
  }://${host}:${lambdaPort}`,
50
50
  )
51
51
 
52
52
  // Print all the invocation routes to debug
53
- const basePath = `http${httpsProtocol ? 's' : ''}://${host}:${lambdaPort}`
53
+ const basePath = `${
54
+ httpsProtocol ? 'https' : 'http'
55
+ }://${host}:${lambdaPort}`
54
56
  const funcNamePairs = this.#lambda.listFunctionNamePairs()
55
57
 
56
58
  log.notice(
@@ -41,19 +41,6 @@ export default class ChildProcessRunner {
41
41
  },
42
42
  )
43
43
 
44
- let message
45
-
46
- try {
47
- message = new Promise((res, rej) => {
48
- childProcess.on('message', (data) => {
49
- if (data.error) rej(data.error)
50
- else res(data)
51
- })
52
- })
53
- } finally {
54
- childProcess.kill()
55
- }
56
-
57
44
  childProcess.send({
58
45
  context,
59
46
  event,
@@ -63,12 +50,21 @@ export default class ChildProcessRunner {
63
50
  let result
64
51
 
65
52
  try {
66
- result = await message
53
+ result = await new Promise((res, rej) => {
54
+ childProcess.on('message', (data) => {
55
+ if (data.error) {
56
+ rej(data.error)
57
+ return
58
+ }
59
+ res(data)
60
+ })
61
+ })
67
62
  } catch (err) {
68
63
  // TODO
69
64
  log.error(err)
70
-
71
65
  throw err
66
+ } finally {
67
+ childProcess.kill()
72
68
  }
73
69
 
74
70
  return result