serverless-offline 8.3.1 → 8.6.0

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 (31) hide show
  1. package/README.md +83 -10
  2. package/dist/ServerlessOffline.js +19 -2
  3. package/dist/config/commandOptions.js +4 -0
  4. package/dist/config/defaultOptions.js +1 -0
  5. package/dist/events/{http/authCanExecuteResource.js → authCanExecuteResource.js} +0 -0
  6. package/dist/events/{http/authFunctionNameExtractor.js → authFunctionNameExtractor.js} +1 -1
  7. package/dist/events/{http/authMatchPolicyResource.js → authMatchPolicyResource.js} +0 -0
  8. package/dist/events/http/HttpServer.js +48 -10
  9. package/dist/events/http/createAuthScheme.js +3 -2
  10. package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +21 -1
  11. package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +28 -2
  12. package/dist/events/websocket/WebSocketClients.js +259 -26
  13. package/dist/events/websocket/WebSocketServer.js +50 -4
  14. package/dist/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +99 -0
  15. package/dist/events/websocket/lambda-events/index.js +8 -0
  16. package/dist/lambda/LambdaFunction.js +3 -2
  17. package/dist/lambda/handler-runner/HandlerRunner.js +9 -1
  18. package/dist/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +9 -1
  19. package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +4 -1
  20. package/dist/lambda/handler-runner/go-runner/GoRunner.js +211 -0
  21. package/dist/lambda/handler-runner/go-runner/index.js +15 -0
  22. package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +28 -7
  23. package/dist/lambda/handler-runner/java-runner/JavaRunner.js +1 -2
  24. package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +0 -2
  25. package/dist/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +2 -0
  26. package/dist/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +3 -2
  27. package/dist/lambda/routes/invocations/invocationsRoute.js +2 -1
  28. package/dist/utils/checkGoVersion.js +27 -0
  29. package/dist/utils/index.js +8 -0
  30. package/dist/utils/splitHandlerPathAndName.js +13 -9
  31. package/package.json +48 -19
@@ -244,7 +244,10 @@ class DockerContainer {
244
244
  // Add `host.docker.internal` DNS name to access host from inside the container
245
245
  // https://github.com/docker/for-linux/issues/264
246
246
  const gatewayIp = await this._getBridgeGatewayIp();
247
- dockerArgs.push('--add-host', `host.docker.internal:${gatewayIp}`);
247
+
248
+ if (gatewayIp) {
249
+ dockerArgs.push('--add-host', `host.docker.internal:${gatewayIp}`);
250
+ }
248
251
  }
249
252
 
250
253
  if (_classPrivateFieldLooseBase(this, _dockerOptions)[_dockerOptions].network) {
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _os = require("os");
9
+
10
+ var _fs = require("fs");
11
+
12
+ var _path = require("path");
13
+
14
+ var _execa = _interopRequireWildcard(require("execa"));
15
+
16
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
+
18
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
19
+
20
+ function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }
21
+
22
+ var id = 0;
23
+
24
+ function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
25
+
26
+ const {
27
+ writeFile,
28
+ readFile,
29
+ mkdir,
30
+ rmdir
31
+ } = _fs.promises;
32
+ const {
33
+ parse,
34
+ stringify
35
+ } = JSON;
36
+ const {
37
+ cwd
38
+ } = process;
39
+ const PAYLOAD_IDENTIFIER = 'offline_payload';
40
+
41
+ var _env = /*#__PURE__*/_classPrivateFieldLooseKey("env");
42
+
43
+ var _handlerPath = /*#__PURE__*/_classPrivateFieldLooseKey("handlerPath");
44
+
45
+ var _tmpPath = /*#__PURE__*/_classPrivateFieldLooseKey("tmpPath");
46
+
47
+ var _tmpFile = /*#__PURE__*/_classPrivateFieldLooseKey("tmpFile");
48
+
49
+ var _goEnv = /*#__PURE__*/_classPrivateFieldLooseKey("goEnv");
50
+
51
+ class GoRunner {
52
+ constructor(funOptions, env, v3Utils) {
53
+ Object.defineProperty(this, _env, {
54
+ writable: true,
55
+ value: null
56
+ });
57
+ Object.defineProperty(this, _handlerPath, {
58
+ writable: true,
59
+ value: null
60
+ });
61
+ Object.defineProperty(this, _tmpPath, {
62
+ writable: true,
63
+ value: null
64
+ });
65
+ Object.defineProperty(this, _tmpFile, {
66
+ writable: true,
67
+ value: null
68
+ });
69
+ Object.defineProperty(this, _goEnv, {
70
+ writable: true,
71
+ value: null
72
+ });
73
+ const {
74
+ handlerPath
75
+ } = funOptions;
76
+ _classPrivateFieldLooseBase(this, _env)[_env] = env;
77
+ _classPrivateFieldLooseBase(this, _handlerPath)[_handlerPath] = handlerPath;
78
+
79
+ if (v3Utils) {
80
+ this.log = v3Utils.log;
81
+ this.progress = v3Utils.progress;
82
+ this.writeText = v3Utils.writeText;
83
+ this.v3Utils = v3Utils;
84
+ } // Make sure we have the mock-lambda runner
85
+
86
+
87
+ (0, _execa.sync)('go', ['get', 'github.com/icarus-sullivan/mock-lambda@e065469']);
88
+ }
89
+
90
+ async cleanup() {
91
+ try {
92
+ await rmdir(_classPrivateFieldLooseBase(this, _tmpPath)[_tmpPath], {
93
+ recursive: true
94
+ });
95
+ } catch (e) {// @ignore
96
+ }
97
+
98
+ _classPrivateFieldLooseBase(this, _tmpFile)[_tmpFile] = null;
99
+ _classPrivateFieldLooseBase(this, _tmpPath)[_tmpPath] = null;
100
+ }
101
+
102
+ _parsePayload(value) {
103
+ const log = [];
104
+ let payload;
105
+
106
+ for (const item of value.split(_os.EOL)) {
107
+ if (item.indexOf(PAYLOAD_IDENTIFIER) === -1) {
108
+ log.push(item);
109
+ } else if (item.indexOf(PAYLOAD_IDENTIFIER) !== -1) {
110
+ try {
111
+ const {
112
+ offline_payload: {
113
+ success,
114
+ error
115
+ }
116
+ } = parse(item);
117
+
118
+ if (success) {
119
+ payload = success;
120
+ } else if (error) {
121
+ payload = error;
122
+ }
123
+ } catch (err) {// @ignore
124
+ }
125
+ }
126
+ } // Log to console in case engineers want to see the rest of the info
127
+
128
+
129
+ if (this.log) {
130
+ this.log(log.join(_os.EOL));
131
+ } else {
132
+ console.log(log.join(_os.EOL));
133
+ }
134
+
135
+ return payload;
136
+ }
137
+
138
+ async run(event, context) {
139
+ const {
140
+ dir
141
+ } = (0, _path.parse)(_classPrivateFieldLooseBase(this, _handlerPath)[_handlerPath]);
142
+ const handlerCodeRoot = dir.split(_path.sep).slice(0, -1).join(_path.sep);
143
+ const handlerCode = await readFile(`${_classPrivateFieldLooseBase(this, _handlerPath)[_handlerPath]}.go`, 'utf8');
144
+ _classPrivateFieldLooseBase(this, _tmpPath)[_tmpPath] = (0, _path.resolve)(handlerCodeRoot, 'tmp');
145
+ _classPrivateFieldLooseBase(this, _tmpFile)[_tmpFile] = (0, _path.resolve)(_classPrivateFieldLooseBase(this, _tmpPath)[_tmpPath], 'main.go');
146
+ const out = handlerCode.replace('"github.com/aws/aws-lambda-go/lambda"', 'lambda "github.com/icarus-sullivan/mock-lambda"');
147
+
148
+ try {
149
+ await mkdir(_classPrivateFieldLooseBase(this, _tmpPath)[_tmpPath], {
150
+ recursive: true
151
+ });
152
+ } catch (e) {// @ignore
153
+ }
154
+
155
+ try {
156
+ await writeFile(_classPrivateFieldLooseBase(this, _tmpFile)[_tmpFile], out, 'utf8');
157
+ } catch (e) {// @ignore
158
+ } // Get go env to run this locally
159
+
160
+
161
+ if (!_classPrivateFieldLooseBase(this, _goEnv)[_goEnv]) {
162
+ const goEnvResponse = await (0, _execa.default)('go', ['env'], {
163
+ stdio: 'pipe',
164
+ encoding: 'utf-8'
165
+ });
166
+ const goEnvString = goEnvResponse.stdout || goEnvResponse.stderr;
167
+ _classPrivateFieldLooseBase(this, _goEnv)[_goEnv] = goEnvString.split(_os.EOL).reduce((a, b) => {
168
+ const [k, v] = b.split('="'); // eslint-disable-next-line no-param-reassign
169
+
170
+ a[k] = v ? v.slice(0, -1) : '';
171
+ return a;
172
+ }, {});
173
+ } // Remove our root, since we want to invoke go relatively
174
+
175
+
176
+ const cwdPath = `${_classPrivateFieldLooseBase(this, _tmpFile)[_tmpFile]}`.replace(`${cwd()}${_path.sep}`, '');
177
+ const {
178
+ stdout,
179
+ stderr
180
+ } = await (0, _execa.default)(`go`, ['run', cwdPath], {
181
+ stdio: 'pipe',
182
+ env: { ..._classPrivateFieldLooseBase(this, _env)[_env],
183
+ ..._classPrivateFieldLooseBase(this, _goEnv)[_goEnv],
184
+ AWS_LAMBDA_LOG_GROUP_NAME: context.logGroupName,
185
+ AWS_LAMBDA_LOG_STREAM_NAME: context.logStreamName,
186
+ AWS_LAMBDA_FUNCTION_NAME: context.functionName,
187
+ AWS_LAMBDA_FUNCTION_MEMORY_SIZE: context.memoryLimitInMB,
188
+ AWS_LAMBDA_FUNCTION_VERSION: context.functionVersion,
189
+ LAMBDA_EVENT: stringify(event),
190
+ LAMBDA_TEST_EVENT: `${event}`,
191
+ LAMBDA_CONTEXT: stringify(context),
192
+ IS_LAMBDA_AUTHORIZER: event.type === 'REQUEST' || event.type === 'TOKEN',
193
+ IS_LAMBDA_REQUEST_AUTHORIZER: event.type === 'REQUEST',
194
+ IS_LAMBDA_TOKEN_AUTHORIZER: event.type === 'TOKEN',
195
+ PATH: process.env.PATH
196
+ },
197
+ encoding: 'utf-8'
198
+ }); // Clean up after we created the temporary file
199
+
200
+ await this.cleanup();
201
+
202
+ if (stderr) {
203
+ return stderr;
204
+ }
205
+
206
+ return this._parsePayload(stdout);
207
+ }
208
+
209
+ }
210
+
211
+ exports.default = GoRunner;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "default", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _GoRunner.default;
10
+ }
11
+ });
12
+
13
+ var _GoRunner = _interopRequireDefault(require("./GoRunner.js"));
14
+
15
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -58,8 +58,8 @@ const clearModule = (fP, opts) => {
58
58
  delete require.cache[filePath];
59
59
 
60
60
  for (const c of cld) {
61
- // Unload any non node_modules children
62
- if (!c.filename.match(/node_modules/)) {
61
+ // Unload any non node_modules and non-binary children
62
+ if (!c.filename.match(/\/node_modules\//i) && !c.filename.match(/\.node$/i)) {
63
63
  clearModule(c.id, { ...options,
64
64
  cleanup: false
65
65
  });
@@ -74,7 +74,7 @@ const clearModule = (fP, opts) => {
74
74
  cleanup = false;
75
75
 
76
76
  for (const fn of Object.keys(require.cache)) {
77
- if (require.cache[fn].id !== '.' && require.cache[fn].parent && require.cache[fn].parent.id !== '.' && !require.cache[require.cache[fn].parent.id]) {
77
+ if (require.cache[fn] && require.cache[fn].id !== '.' && require.cache[fn].parent && require.cache[fn].parent.id !== '.' && !require.cache[require.cache[fn].parent.id] && !fn.match(/\/node_modules\//i) && !fn.match(/\.node$/i)) {
78
78
  delete require.cache[fn];
79
79
  cleanup = true;
80
80
  }
@@ -92,12 +92,14 @@ var _handlerName = /*#__PURE__*/_classPrivateFieldLooseKey("handlerName");
92
92
 
93
93
  var _handlerPath = /*#__PURE__*/_classPrivateFieldLooseKey("handlerPath");
94
94
 
95
+ var _handlerModuleNesting = /*#__PURE__*/_classPrivateFieldLooseKey("handlerModuleNesting");
96
+
95
97
  var _timeout = /*#__PURE__*/_classPrivateFieldLooseKey("timeout");
96
98
 
97
99
  var _allowCache = /*#__PURE__*/_classPrivateFieldLooseKey("allowCache");
98
100
 
99
101
  class InProcessRunner {
100
- constructor(functionKey, handlerPath, handlerName, env, timeout, allowCache) {
102
+ constructor(functionKey, handlerPath, handlerName, handlerModuleNesting, env, timeout, allowCache) {
101
103
  Object.defineProperty(this, _env, {
102
104
  writable: true,
103
105
  value: null
@@ -114,6 +116,10 @@ class InProcessRunner {
114
116
  writable: true,
115
117
  value: null
116
118
  });
119
+ Object.defineProperty(this, _handlerModuleNesting, {
120
+ writable: true,
121
+ value: null
122
+ });
117
123
  Object.defineProperty(this, _timeout, {
118
124
  writable: true,
119
125
  value: null
@@ -126,6 +132,7 @@ class InProcessRunner {
126
132
  _classPrivateFieldLooseBase(this, _functionKey)[_functionKey] = functionKey;
127
133
  _classPrivateFieldLooseBase(this, _handlerName)[_handlerName] = handlerName;
128
134
  _classPrivateFieldLooseBase(this, _handlerPath)[_handlerPath] = handlerPath;
135
+ _classPrivateFieldLooseBase(this, _handlerModuleNesting)[_handlerModuleNesting] = handlerModuleNesting;
129
136
  _classPrivateFieldLooseBase(this, _timeout)[_timeout] = timeout;
130
137
  _classPrivateFieldLooseBase(this, _allowCache)[_allowCache] = allowCache;
131
138
  } // no-op
@@ -152,9 +159,17 @@ class InProcessRunner {
152
159
  });
153
160
  }
154
161
 
155
- const {
156
- [_classPrivateFieldLooseBase(this, _handlerName)[_handlerName]]: handler
157
- } = await Promise.resolve(`${_classPrivateFieldLooseBase(this, _handlerPath)[_handlerPath]}`).then(s => _interopRequireWildcard(require(s)));
162
+ let handler;
163
+
164
+ try {
165
+ const handlerPathExport = await Promise.resolve(`${_classPrivateFieldLooseBase(this, _handlerPath)[_handlerPath]}`).then(s => _interopRequireWildcard(require(s))); // this supports handling of nested handler paths like <pathToFile>/<fileName>.object1.object2.object3.handler
166
+ // a use case for this, is when the handler is further down the export tree or in nested objects
167
+ // NOTE: this feature is supported in AWS Lambda
168
+
169
+ handler = _classPrivateFieldLooseBase(this, _handlerModuleNesting)[_handlerModuleNesting].reduce((obj, key) => obj[key], handlerPathExport);
170
+ } catch (error) {
171
+ throw new Error(`offline: one of the module nesting ${_classPrivateFieldLooseBase(this, _handlerModuleNesting)[_handlerModuleNesting]} for handler ${_classPrivateFieldLooseBase(this, _handlerName)[_handlerName]} is undefined or not exported`);
172
+ }
158
173
 
159
174
  if (typeof handler !== 'function') {
160
175
  throw new Error(`offline: handler '${_classPrivateFieldLooseBase(this, _handlerName)[_handlerName]}' in ${_classPrivateFieldLooseBase(this, _handlerPath)[_handlerPath]} is not a function`);
@@ -163,8 +178,14 @@ class InProcessRunner {
163
178
  let callback;
164
179
  const callbackCalled = new Promise((resolve, reject) => {
165
180
  callback = (err, data) => {
181
+ if (err === 'Unauthorized') {
182
+ resolve('Unauthorized');
183
+ return;
184
+ }
185
+
166
186
  if (err) {
167
187
  reject(err);
188
+ return;
168
189
  }
169
190
 
170
191
  resolve(data);
@@ -116,8 +116,7 @@ class JavaRunner {
116
116
  data: input,
117
117
  function: _classPrivateFieldLooseBase(this, _functionName)[_functionName],
118
118
  jsonOutput: true,
119
- serverlessOffline: true,
120
- allowCache: _classPrivateFieldLooseBase(this, _allowCache)[_allowCache]
119
+ serverlessOffline: true
121
120
  });
122
121
  const httpOptions = {
123
122
  method: 'POST',
@@ -138,8 +138,6 @@ class RubyRunner {
138
138
  } else {
139
139
  console.log(stderr);
140
140
  }
141
-
142
- return stderr;
143
141
  }
144
142
 
145
143
  return this._parsePayload(stdout);
@@ -39,6 +39,7 @@ class WorkerThreadRunner {
39
39
  functionKey,
40
40
  handlerName,
41
41
  handlerPath,
42
+ handlerModuleNesting,
42
43
  timeout
43
44
  } = funOptions;
44
45
  _classPrivateFieldLooseBase(this, _allowCache)[_allowCache] = allowCache;
@@ -49,6 +50,7 @@ class WorkerThreadRunner {
49
50
  functionKey,
50
51
  handlerName,
51
52
  handlerPath,
53
+ handlerModuleNesting,
52
54
  timeout
53
55
  }
54
56
  });
@@ -10,7 +10,8 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
10
10
  const {
11
11
  functionKey,
12
12
  handlerName,
13
- handlerPath
13
+ handlerPath,
14
+ handlerModuleNesting
14
15
  } = _worker_threads.workerData;
15
16
 
16
17
  _worker_threads.parentPort.on('message', async messageData => {
@@ -22,7 +23,7 @@ _worker_threads.parentPort.on('message', async messageData => {
22
23
  allowCache
23
24
  } = messageData; // TODO we could probably cache this in the module scope?
24
25
 
25
- const inProcessRunner = new _index.default(functionKey, handlerPath, handlerName, process.env, timeout, allowCache);
26
+ const inProcessRunner = new _index.default(functionKey, handlerPath, handlerName, handlerModuleNesting, process.env, timeout, allowCache);
26
27
  const result = await inProcessRunner.run(event, context); // TODO check serializeability (contains function, symbol etc)
27
28
 
28
29
  port.postMessage(result);
@@ -53,7 +53,8 @@ function invocationsRoute(lambda, options, v3Utils) {
53
53
  let functionError = null;
54
54
 
55
55
  if (invokeResults) {
56
- resultPayload = invokeResults.Payload || '';
56
+ const isPayloadDefined = typeof invokeResults.Payload !== 'undefined';
57
+ resultPayload = isPayloadDefined ? invokeResults.Payload : '';
57
58
  statusCode = invokeResults.StatusCode || 200;
58
59
  functionError = invokeResults.FunctionError || null;
59
60
  }
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = checkGoVersion;
7
+
8
+ var _execa = _interopRequireDefault(require("execa"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ async function checkGoVersion() {
13
+ let goVersion;
14
+
15
+ try {
16
+ const {
17
+ stdout
18
+ } = await (0, _execa.default)('go', ['version']);
19
+
20
+ if (stdout.match(/go1.\d+/g)) {
21
+ goVersion = '1.x';
22
+ }
23
+ } catch (err) {// @ignore
24
+ }
25
+
26
+ return goVersion;
27
+ }
@@ -9,6 +9,12 @@ Object.defineProperty(exports, "checkDockerDaemon", {
9
9
  return _checkDockerDaemon.default;
10
10
  }
11
11
  });
12
+ Object.defineProperty(exports, "checkGoVersion", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _checkGoVersion.default;
16
+ }
17
+ });
12
18
  Object.defineProperty(exports, "createApiKey", {
13
19
  enumerable: true,
14
20
  get: function () {
@@ -118,6 +124,8 @@ var _splitHandlerPathAndName = _interopRequireDefault(require("./splitHandlerPat
118
124
 
119
125
  var _checkDockerDaemon = _interopRequireDefault(require("./checkDockerDaemon.js"));
120
126
 
127
+ var _checkGoVersion = _interopRequireDefault(require("./checkGoVersion.js"));
128
+
121
129
  var _generateHapiPath = _interopRequireDefault(require("./generateHapiPath.js"));
122
130
 
123
131
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
@@ -8,18 +8,18 @@ exports.default = splitHandlerPathAndName;
8
8
  // some-folder/src.index => some-folder/src
9
9
  function splitHandlerPathAndName(handler) {
10
10
  // Split handler into method name and path i.e. handler.run
11
- // Support Ruby paths with namespace resolution operators e.g.
11
+ const prepathDelimiter = handler.lastIndexOf('/');
12
+ const prepath = handler.substr(0, prepathDelimiter + 1); // include '/' for path
13
+
14
+ const postpath = handler.substr(prepathDelimiter + 1); // Support Ruby paths with namespace resolution operators e.g.
12
15
  // ./src/somefolder/source.LambdaFunctions::Handler.process
13
16
  // prepath: ./src/somefolder/
14
17
  // postpath: source.LambdaFunctions::Handler.process
15
18
  // filename: source
16
19
  // path: ./src/somefolder/source
17
20
  // name: LambdaFunctions::Handler.process
18
- if (handler.match(/::/)) {
19
- const prepathDelimiter = handler.lastIndexOf('/');
20
- const prepath = handler.substr(0, prepathDelimiter + 1); // include '/' for path
21
21
 
22
- const postpath = handler.substr(prepathDelimiter + 1);
22
+ if (handler.match(/::/)) {
23
23
  const nameDelimiter = postpath.indexOf('.');
24
24
  const filename = postpath.substr(0, nameDelimiter);
25
25
  const path = prepath + filename;
@@ -30,8 +30,12 @@ function splitHandlerPathAndName(handler) {
30
30
  // name: run
31
31
 
32
32
 
33
- const delimiter = handler.lastIndexOf('.');
34
- const path = handler.substr(0, delimiter);
35
- const name = handler.substr(delimiter + 1);
36
- return [path, name];
33
+ const [filename, ...moduleNesting] = postpath.split('.');
34
+ const [name] = moduleNesting.slice(-1);
35
+ const path = prepath + filename; // module nesting has been added to support when the
36
+ // handler function is buried deep inside of a module
37
+ // e.g /src/somefoler/handlers/index.layer1.layer2.handler
38
+ // AWS supports this feature
39
+
40
+ return [path, name, moduleNesting];
37
41
  }
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": "8.3.1",
4
+ "version": "8.6.0",
5
5
  "description": "Emulate AWS λ and API Gateway locally when developing your Serverless project",
6
6
  "license": "MIT",
7
7
  "main": "dist/main.js",
@@ -13,6 +13,7 @@
13
13
  "lint:updated": "pipe-git-updated --ext=js -- eslint",
14
14
  "list-contributors": "echo 'clone https://github.com/mgechev/github-contributors-list.git first, then run npm install' && cd ../github-contributors-list && node bin/githubcontrib --owner dherault --repo serverless-offline --sortBy contributions --showlogin true --sortOrder desc > contributors.md",
15
15
  "prepare": "npm run build",
16
+ "prepare-release": "standard-version && prettier --write CHANGELOG.md",
16
17
  "prepublishOnly": "npm run lint && npm run build",
17
18
  "prettier-check": "prettier -c --ignore-path .gitignore \"**/*.{css,html,js,json,md,yaml,yml}\"",
18
19
  "prettier-check:updated": "pipe-git-updated --ext=css --ext=html --ext=js --ext=json --ext=md --ext=yaml --ext=yml -- prettier -c",
@@ -101,6 +102,7 @@
101
102
  "Gert Jansen van Rensburg (https://github.com/gertjvr)",
102
103
  "Guillaume Carbonneau (https://github.com/guillaume)",
103
104
  "György Balássy (https://github.com/balassy)",
105
+ "James Relyea (https://github.com/james-relyea)",
104
106
  "Jarda Snajdr (https://github.com/jsnajdr)",
105
107
  "Jaryd Carolin (https://github.com/horyd)",
106
108
  "Jeff Hall (https://github.com/electrikdevelopment)",
@@ -115,6 +117,7 @@
115
117
  "Kiryl Yermakou (https://github.com/rma4ok)",
116
118
  "kobanyan (https://github.com/kobanyan)",
117
119
  "Leonardo Alifraco (https://github.com/lalifraco-devspark)",
120
+ "Leonardo Medici (https://github.com/doclm)",
118
121
  "Luke Chavers (https://github.com/vmadman)",
119
122
  "Manuel Böhm (https://github.com/boehmers)",
120
123
  "Marc Campbell (https://github.com/marccampbell)",
@@ -147,6 +150,7 @@
147
150
  "Stewart Gleadow (https://github.com/sgleadow)",
148
151
  "Thales Minussi (https://github.com/tminussi)",
149
152
  "Thang Minh Vu (https://github.com/ittus)",
153
+ "Tom St. Clair (https://github.com/tom-stclair)",
150
154
  "Trevor Leach (https://github.com/trevor-leach)",
151
155
  "Tuan Minh Huynh (https://github.com/tuanmh)",
152
156
  "Utku Turunc (https://github.com/utkuturunc)",
@@ -154,7 +158,8 @@
154
158
  "Dima Krutolianov (https://github.com/dimadk24)",
155
159
  "Bryan Vaz (https://github.com/bryanvaz)",
156
160
  "Justin Ng (https://github.com/njyjn)",
157
- "Fernando Alvarez (https://github.com/jefer590)"
161
+ "Fernando Alvarez (https://github.com/jefer590)",
162
+ "Eric Carter (https://github.com/ericctsf)"
158
163
  ],
159
164
  "husky": {
160
165
  "hooks": {
@@ -172,11 +177,35 @@
172
177
  "engines": {
173
178
  "node": ">=12.0.0"
174
179
  },
180
+ "standard-version": {
181
+ "skip": {
182
+ "commit": true,
183
+ "tag": true
184
+ },
185
+ "types": [
186
+ {
187
+ "type": "feat",
188
+ "section": "Features"
189
+ },
190
+ {
191
+ "type": "fix",
192
+ "section": "Bug Fixes"
193
+ },
194
+ {
195
+ "type": "perf",
196
+ "section": "Performance Improvements"
197
+ },
198
+ {
199
+ "type": "refactor",
200
+ "section": "Maintenance Improvements"
201
+ }
202
+ ]
203
+ },
175
204
  "dependencies": {
176
205
  "@hapi/boom": "^9.1.4",
177
206
  "@hapi/h2o2": "^9.1.0",
178
207
  "@hapi/hapi": "^20.2.1",
179
- "aws-sdk": "^2.1036.0",
208
+ "aws-sdk": "^2.1097.0",
180
209
  "boxen": "^5.1.2",
181
210
  "chalk": "^4.1.2",
182
211
  "cuid": "^2.1.8",
@@ -190,44 +219,44 @@
190
219
  "jsonwebtoken": "^8.5.1",
191
220
  "jszip": "^3.7.1",
192
221
  "luxon": "^1.28.0",
193
- "node-fetch": "^2.6.6",
222
+ "node-fetch": "^2.6.7",
194
223
  "node-schedule": "^1.3.3",
195
224
  "object.fromentries": "^2.0.5",
196
- "p-memoize": "^4.0.3",
225
+ "p-memoize": "^4.0.4",
197
226
  "p-queue": "^6.6.2",
198
227
  "p-retry": "^4.6.1",
199
228
  "please-upgrade-node": "^3.2.0",
200
- "portfinder": "^1.0.28",
201
229
  "semver": "^7.3.5",
202
230
  "update-notifier": "^5.1.0",
203
- "velocityjs": "^2.0.5",
204
- "ws": "^7.5.6"
231
+ "velocityjs": "^2.0.6",
232
+ "ws": "^7.5.7"
205
233
  },
206
234
  "devDependencies": {
207
- "@babel/cli": "^7.16.0",
208
- "@babel/core": "^7.16.0",
209
- "@babel/plugin-proposal-class-properties": "^7.16.0",
210
- "@babel/plugin-proposal-dynamic-import": "^7.16.0",
211
- "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0",
212
- "@babel/plugin-proposal-optional-chaining": "^7.16.0",
213
- "@babel/plugin-transform-modules-commonjs": "^7.16.0",
214
- "@babel/register": "^7.16.0",
235
+ "@babel/cli": "^7.17.6",
236
+ "@babel/core": "^7.17.8",
237
+ "@babel/plugin-proposal-class-properties": "^7.16.7",
238
+ "@babel/plugin-proposal-dynamic-import": "^7.16.7",
239
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7",
240
+ "@babel/plugin-proposal-optional-chaining": "^7.16.7",
241
+ "@babel/plugin-transform-modules-commonjs": "^7.17.7",
242
+ "@babel/register": "^7.17.7",
215
243
  "archiver": "^5.3.0",
216
244
  "babel-eslint": "^10.1.0",
217
245
  "copyfiles": "^2.4.1",
218
246
  "eslint": "^7.32.0",
219
247
  "eslint-config-airbnb-base": "^14.2.1",
220
248
  "eslint-config-prettier": "^7.2.0",
221
- "eslint-plugin-import": "^2.25.3",
249
+ "eslint-plugin-import": "^2.25.4",
222
250
  "eslint-plugin-prettier": "^3.4.1",
223
251
  "git-list-updated": "^1.2.1",
224
252
  "husky": "^4.3.8",
225
253
  "jest": "^26.6.3",
226
254
  "lint-staged": "^11.2.6",
227
255
  "p-map": "^4.0.0",
228
- "prettier": "^2.4.1",
256
+ "prettier": "^2.6.0",
229
257
  "rimraf": "^3.0.2",
230
- "serverless": "^2.66.2"
258
+ "serverless": "^2.72.3",
259
+ "standard-version": "^9.3.2"
231
260
  },
232
261
  "peerDependencies": {
233
262
  "serverless": "^1.60.0 || 2 || 3"