serverless-offline 13.6.0 → 14.1.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.
@@ -1,359 +1,338 @@
1
+ /* eslint-disable import/no-dynamic-require */
2
+ /* eslint-disable global-require */
3
+ /* eslint-disable no-underscore-dangle */
4
+ /* eslint-disable func-names */
5
+ /**
6
+ * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
7
+ *
8
+ * This code was copied from:
9
+ * https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/blob/main/src/UserFunction.js
10
+ *
11
+ * This module defines the functions for loading the user's code as specified
12
+ * in a handler string.
13
+ */
14
+
1
15
  "use strict"
2
16
 
17
+ const path = require("node:path")
3
18
  const { pathToFileURL } = require("node:url")
19
+ const fs = require("node:fs")
20
+ const process = require("node:process")
4
21
 
5
- // node_modules/lambda-runtime/dist/node16/UserFunction.js
6
- ;(function () {
7
- const __getOwnPropNames = Object.getOwnPropertyNames
8
- const __commonJS = (cb, mod) =>
9
- function __require() {
10
- return (
11
- mod ||
12
- (0, cb[__getOwnPropNames(cb)[0]])(
13
- (mod = { exports: {} }).exports,
14
- mod,
15
- ),
16
- mod.exports
17
- )
18
- }
19
- const require_Errors = __commonJS({
20
- "Errors.js": function (exports2, module2) {
21
- "use strict"
22
-
23
- const util = require("util")
24
- function _isError(obj) {
25
- return (
26
- obj &&
27
- obj.name &&
28
- obj.message &&
29
- obj.stack &&
30
- typeof obj.name === "string" &&
31
- typeof obj.message === "string" &&
32
- typeof obj.stack === "string"
33
- )
34
- }
35
- function intoError(err) {
36
- if (err instanceof Error) {
37
- return err
38
- }
39
- return new Error(err)
40
- }
41
- module2.exports.intoError = intoError
42
- function toRapidResponse(error) {
43
- try {
44
- if (util.types.isNativeError(error) || _isError(error)) {
45
- return {
46
- errorType: error.name,
47
- errorMessage: error.message,
48
- trace: error.stack.split("\n"),
49
- }
50
- }
51
- return {
52
- errorType: typeof error,
53
- errorMessage: error.toString(),
54
- trace: [],
55
- }
56
- } catch (_err) {
57
- return {
58
- errorType: "handled",
59
- errorMessage:
60
- "callback called with Error argument, but there was a problem while retrieving one or more of its message, name, and stack",
61
- }
62
- }
63
- }
64
- module2.exports.toRapidResponse = toRapidResponse
65
- module2.exports.toFormatted = (error) => {
66
- try {
67
- return ` ${JSON.stringify(error, (_k, v) =>
68
- _withEnumerableProperties(v),
69
- )}`
70
- } catch (err) {
71
- return ` ${JSON.stringify(toRapidResponse(error))}`
72
- }
73
- }
74
- function _withEnumerableProperties(error) {
75
- if (error instanceof Error) {
76
- const ret = {
77
- errorType: error.name,
78
- errorMessage: error.message,
79
- code: error.code,
80
- ...error,
81
- }
82
- if (typeof error.stack === "string") {
83
- ret.stack = error.stack.split("\n")
84
- }
85
- return ret
86
- }
87
- return error
88
- }
89
- const errorClasses = [
90
- class ImportModuleError extends Error {},
91
- class HandlerNotFound extends Error {},
92
- class MalformedHandlerName extends Error {},
93
- class UserCodeSyntaxError extends Error {},
94
- class MalformedStreamingHandler extends Error {},
95
- class InvalidStreamingOperation extends Error {},
96
- class UnhandledPromiseRejection extends Error {
97
- constructor(reason, promise) {
98
- super(reason)
99
- this.reason = reason
100
- this.promise = promise
101
- }
102
- },
103
- ]
104
- errorClasses.forEach((e) => {
105
- module2.exports[e.name] = e
106
- e.prototype.name = `Runtime.${e.name}`
107
- })
108
- },
109
- })
110
- const require_VerboseLog = __commonJS({
111
- "VerboseLog.js": function (exports2) {
112
- "use strict"
113
-
114
- const EnvVarName = "AWS_LAMBDA_RUNTIME_VERBOSE"
115
- const Tag = "RUNTIME"
116
- const Verbosity = (() => {
117
- if (!process.env[EnvVarName]) {
118
- return 0
119
- }
120
- try {
121
- const verbosity = parseInt(process.env[EnvVarName])
122
- return verbosity < 0 ? 0 : verbosity > 3 ? 3 : verbosity
123
- } catch (_) {
124
- return 0
125
- }
126
- })()
127
- exports2.logger = function (category) {
128
- return {
129
- verbose() {
130
- if (Verbosity >= 1) {
131
- console.log.apply(null, [Tag, category, ...arguments])
132
- }
133
- },
134
- vverbose() {
135
- if (Verbosity >= 2) {
136
- console.log.apply(null, [Tag, category, ...arguments])
137
- }
138
- },
139
- vvverbose() {
140
- if (Verbosity >= 3) {
141
- console.log.apply(null, [Tag, category, ...arguments])
142
- }
143
- },
144
- }
145
- }
146
- },
147
- })
148
- const require_HttpResponseStream = __commonJS({
149
- "HttpResponseStream.js": function (exports2, module2) {
150
- "use strict"
151
-
152
- const METADATA_PRELUDE_CONTENT_TYPE =
153
- "application/vnd.awslambda.http-integration-response"
154
- const DELIMITER_LEN = 8
155
- const HttpResponseStream2 = class {
156
- static from(underlyingStream, prelude) {
157
- underlyingStream.setContentType(METADATA_PRELUDE_CONTENT_TYPE)
158
- const metadataPrelude = JSON.stringify(prelude)
159
- underlyingStream._onBeforeFirstWrite = (write) => {
160
- write(metadataPrelude)
161
- write(new Uint8Array(DELIMITER_LEN))
162
- }
163
- return underlyingStream
164
- }
165
- }
166
- module2.exports.HttpResponseStream = HttpResponseStream2
167
- },
168
- })
169
- const path = require("path")
170
- const fs = require("fs")
171
- const {
172
- HandlerNotFound,
173
- MalformedHandlerName,
174
- ImportModuleError,
175
- UserCodeSyntaxError,
176
- } = require_Errors()
177
- const { verbose } = require_VerboseLog().logger("LOADER")
178
- const { HttpResponseStream } = require_HttpResponseStream()
179
- const FUNCTION_EXPR = /^([^.]*)\.(.*)$/
180
- const RELATIVE_PATH_SUBSTRING = ".."
181
- const HANDLER_STREAMING = Symbol.for("aws.lambda.runtime.handler.streaming")
182
- const STREAM_RESPONSE = "response"
183
- const NoGlobalAwsLambda =
184
- process.env.AWS_LAMBDA_NODEJS_NO_GLOBAL_AWSLAMBDA === "1" ||
185
- process.env.AWS_LAMBDA_NODEJS_NO_GLOBAL_AWSLAMBDA === "true"
186
- function _moduleRootAndHandler(fullHandlerString) {
187
- const handlerString = path.basename(fullHandlerString)
188
- const moduleRoot = fullHandlerString.substring(
189
- 0,
190
- fullHandlerString.indexOf(handlerString),
191
- )
192
- return [moduleRoot, handlerString]
193
- }
194
- function _splitHandlerString(handler) {
195
- const match = handler.match(FUNCTION_EXPR)
196
- if (!match || match.length != 3) {
197
- throw new MalformedHandlerName("Bad handler")
198
- }
199
- return [match[1], match[2]]
200
- }
201
- function _resolveHandler(object, nestedProperty) {
202
- return nestedProperty.split(".").reduce((nested, key) => {
203
- return nested && nested[key]
204
- }, object)
22
+ const { require: tsxRequire } = require(`tsx/cjs/api`)
23
+ const {
24
+ HandlerNotFound,
25
+ MalformedHandlerName,
26
+ ImportModuleError,
27
+ UserCodeSyntaxError,
28
+ MalformedStreamingHandler,
29
+ } = require("./Errors.js")
30
+ const { verbose } = require("./VerboseLog.js").logger("LOADER")
31
+ const { HttpResponseStream } = require("./HttpResponseStream.js")
32
+
33
+ const FUNCTION_EXPR = /^([^.]*)\.(.*)$/
34
+ const RELATIVE_PATH_SUBSTRING = ".."
35
+ const HANDLER_STREAMING = Symbol.for("aws.lambda.runtime.handler.streaming")
36
+ const HANDLER_HIGHWATERMARK = Symbol.for(
37
+ "aws.lambda.runtime.handler.streaming.highWaterMark",
38
+ )
39
+ const STREAM_RESPONSE = "response"
40
+
41
+ // `awslambda.streamifyResponse` function is provided by default.
42
+ const NoGlobalAwsLambda =
43
+ process.env.AWS_LAMBDA_NODEJS_NO_GLOBAL_AWSLAMBDA === "1" ||
44
+ process.env.AWS_LAMBDA_NODEJS_NO_GLOBAL_AWSLAMBDA === "true"
45
+
46
+ /**
47
+ * Break the full handler string into two pieces, the module root and the actual
48
+ * handler string.
49
+ * Given './somepath/something/module.nestedobj.handler' this returns
50
+ * ['./somepath/something', 'module.nestedobj.handler']
51
+ */
52
+ function _moduleRootAndHandler(fullHandlerString) {
53
+ const handlerString = path.basename(fullHandlerString)
54
+ const moduleRoot = fullHandlerString.substring(
55
+ 0,
56
+ fullHandlerString.indexOf(handlerString),
57
+ )
58
+ return [moduleRoot, handlerString]
59
+ }
60
+
61
+ /**
62
+ * Split the handler string into two pieces: the module name and the path to
63
+ * the handler function.
64
+ */
65
+ function _splitHandlerString(handler) {
66
+ const match = handler.match(FUNCTION_EXPR)
67
+ if (!match || match.length !== 3) {
68
+ throw new MalformedHandlerName("Bad handler")
205
69
  }
206
- function _tryRequireFile(file, extension) {
207
- const path2 = file + (extension || "")
208
- verbose("Try loading as commonjs:", path2)
209
- return fs.existsSync(path2) ? require(path2) : void 0
70
+ return [match[1], match[2]] // [module, function-path]
71
+ }
72
+
73
+ /**
74
+ * Resolve the user's handler function from the module.
75
+ */
76
+ function _resolveHandler(object, nestedProperty) {
77
+ return nestedProperty.split(".").reduce((nested, key) => {
78
+ return nested && nested[key]
79
+ }, object)
80
+ }
81
+
82
+ function _tryRequireFile(file, extension) {
83
+ const pathRequireFile = file + (extension || "")
84
+ verbose("Try loading as commonjs:", pathRequireFile)
85
+ return fs.existsSync(pathRequireFile) ? require(pathRequireFile) : undefined
86
+ }
87
+
88
+ async function _tryAwaitImport(file, extension) {
89
+ const pathAwaitImport = file + (extension || "")
90
+ verbose("Try loading as esmodule:", pathAwaitImport)
91
+
92
+ if (fs.existsSync(pathAwaitImport)) {
93
+ // eslint-disable-next-line no-return-await
94
+ return await import(pathToFileURL(pathAwaitImport).href)
210
95
  }
211
- async function _tryAwaitImport(file, extension) {
212
- const path2 = file + (extension || "")
213
- verbose("Try loading as esmodule:", path2)
214
- if (fs.existsSync(path2)) {
215
- return await import(pathToFileURL(path2).href)
216
- }
217
- return void 0
96
+
97
+ return undefined
98
+ }
99
+
100
+ function _hasFolderPackageJsonTypeModule(folder) {
101
+ // Check if package.json exists, return true if type === "module" in package json.
102
+ // If there is no package.json, and there is a node_modules, return false.
103
+ // Check parent folder otherwise, if there is one.
104
+ if (folder.endsWith("/node_modules")) {
105
+ return false
218
106
  }
219
- function _hasFolderPackageJsonTypeModule(folder) {
220
- if (folder.endsWith("/node_modules")) {
221
- return false
222
- }
223
- const pj = path.join(folder, "/package.json")
224
- if (fs.existsSync(pj)) {
225
- try {
226
- const pkg = JSON.parse(fs.readFileSync(pj))
227
- if (pkg) {
228
- if (pkg.type === "module") {
229
- verbose(`'type: module' detected in ${pj}`)
230
- return true
231
- }
232
- verbose(`'type: module' not detected in ${pj}`)
233
- return false
107
+
108
+ const pj = path.join(folder, "/package.json")
109
+ if (fs.existsSync(pj)) {
110
+ try {
111
+ const pkg = JSON.parse(fs.readFileSync(pj))
112
+ if (pkg) {
113
+ if (pkg.type === "module") {
114
+ verbose("type: module detected in", pj)
115
+ return true
234
116
  }
235
- } catch (e) {
236
- console.warn(
237
- `${pj} cannot be read, it will be ignored for ES module detection purposes.`,
238
- e,
239
- )
117
+ verbose("type: module not detected in", pj)
240
118
  return false
241
119
  }
242
- }
243
- if (folder === "/") {
120
+ } catch (e) {
121
+ // eslint-disable-next-line no-console
122
+ console.warn(
123
+ `${pj} cannot be read, it will be ignored for ES module detection purposes.`,
124
+ e,
125
+ )
244
126
  return false
245
127
  }
246
- return _hasFolderPackageJsonTypeModule(path.resolve(folder, ".."))
247
128
  }
248
- function _hasPackageJsonTypeModule(file) {
249
- const jsPath = `${file}.js`
250
- return fs.existsSync(jsPath)
251
- ? _hasFolderPackageJsonTypeModule(path.resolve(path.dirname(jsPath)))
252
- : false
129
+
130
+ if (folder === "/") {
131
+ // We have reached root without finding either a package.json or a node_modules.
132
+ return false
253
133
  }
254
- async function _tryRequire(appRoot, moduleRoot, module2) {
255
- verbose(
256
- "Try loading as commonjs: ",
257
- module2,
258
- " with paths: ,",
259
- appRoot,
260
- moduleRoot,
261
- )
262
- const lambdaStylePath = path.resolve(appRoot, moduleRoot, module2)
263
- const extensionless = _tryRequireFile(lambdaStylePath)
264
- if (extensionless) {
265
- return extensionless
266
- }
267
- const pjHasModule = _hasPackageJsonTypeModule(lambdaStylePath)
268
- if (!pjHasModule) {
269
- const loaded2 = _tryRequireFile(lambdaStylePath, ".js")
270
- if (loaded2) {
271
- return loaded2
272
- }
273
- }
274
- const loaded =
275
- (pjHasModule && (await _tryAwaitImport(lambdaStylePath, ".js"))) ||
276
- (await _tryAwaitImport(lambdaStylePath, ".mjs")) ||
277
- _tryRequireFile(lambdaStylePath, ".cjs")
134
+
135
+ return _hasFolderPackageJsonTypeModule(path.resolve(folder, ".."))
136
+ }
137
+
138
+ function _hasPackageJsonTypeModule(file) {
139
+ // File must have a .js extension
140
+ const jsPath = `${file}.js`
141
+ return fs.existsSync(jsPath)
142
+ ? _hasFolderPackageJsonTypeModule(path.resolve(path.dirname(jsPath)))
143
+ : false
144
+ }
145
+
146
+ /**
147
+ * Attempt to load the user's module.
148
+ * Attempts to directly resolve the module relative to the application root,
149
+ * then falls back to the more general require().
150
+ */
151
+ async function _tryRequire(appRoot, moduleRoot, module) {
152
+ verbose(
153
+ "Try loading as commonjs: ",
154
+ module,
155
+ " with paths: ,",
156
+ appRoot,
157
+ moduleRoot,
158
+ )
159
+
160
+ const lambdaStylePath = path.resolve(appRoot, moduleRoot, module)
161
+
162
+ // Extensionless files are loaded via require.
163
+ const extensionless = _tryRequireFile(lambdaStylePath)
164
+ if (extensionless) {
165
+ return extensionless
166
+ }
167
+
168
+ // If package.json type != module, .js files are loaded via require.
169
+ const pjHasModule = _hasPackageJsonTypeModule(lambdaStylePath)
170
+ if (!pjHasModule) {
171
+ const loaded = _tryRequireFile(lambdaStylePath, ".js")
278
172
  if (loaded) {
279
173
  return loaded
280
174
  }
281
- verbose(
282
- "Try loading as commonjs: ",
283
- module2,
284
- " with path(s): ",
285
- appRoot,
286
- moduleRoot,
287
- )
288
- const nodeStylePath = require.resolve(module2, {
289
- paths: [appRoot, moduleRoot],
290
- })
291
- return require(nodeStylePath)
292
175
  }
293
- async function _loadUserApp(appRoot, moduleRoot, module2) {
294
- if (!NoGlobalAwsLambda) {
295
- globalThis.awslambda = {
296
- streamifyResponse: (handler) => {
297
- handler[HANDLER_STREAMING] = STREAM_RESPONSE
298
- return handler
299
- },
300
- HttpResponseStream,
301
- }
302
- }
303
- try {
304
- return await _tryRequire(appRoot, moduleRoot, module2)
305
- } catch (e) {
306
- if (e instanceof SyntaxError) {
307
- throw new UserCodeSyntaxError(e)
308
- } else if (e.code !== void 0 && e.code === "MODULE_NOT_FOUND") {
309
- verbose("globalPaths", JSON.stringify(require("module").globalPaths))
310
- throw new ImportModuleError(e)
311
- } else {
312
- throw e
313
- }
314
- }
176
+
177
+ // If still not loaded, try .js, .mjs, .cjs and .ts in that order.
178
+ // Files ending with .js are loaded as ES modules when the nearest parent package.json
179
+ // file contains a top-level field "type" with a value of "module".
180
+ // https://nodejs.org/api/packages.html#packages_type
181
+ const loaded =
182
+ (pjHasModule && (await _tryAwaitImport(lambdaStylePath, ".js"))) ||
183
+ (await _tryAwaitImport(lambdaStylePath, ".mjs")) ||
184
+ _tryRequireFile(lambdaStylePath, ".cjs") ||
185
+ tsxRequire(`${lambdaStylePath}.ts`, `${lambdaStylePath}.ts`)
186
+ if (loaded) {
187
+ return loaded
315
188
  }
316
- function _throwIfInvalidHandler(fullHandlerString) {
317
- if (fullHandlerString.includes(RELATIVE_PATH_SUBSTRING)) {
318
- throw new MalformedHandlerName(
319
- `'${fullHandlerString}' is not a valid handler name. Use absolute paths when specifying root directories in handler names.`,
320
- )
189
+
190
+ verbose(
191
+ "Try loading as commonjs: ",
192
+ module,
193
+ " with path(s): ",
194
+ appRoot,
195
+ moduleRoot,
196
+ )
197
+
198
+ // Why not just require(module)?
199
+ // Because require() is relative to __dirname, not process.cwd(). And the
200
+ // runtime implementation is not located in /var/task
201
+ // This won't work (yet) for esModules as import.meta.resolve is still experimental
202
+ // See: https://nodejs.org/api/esm.html#esm_import_meta_resolve_specifier_parent
203
+ const nodeStylePath = require.resolve(module, {
204
+ paths: [appRoot, moduleRoot],
205
+ })
206
+
207
+ return require(nodeStylePath)
208
+ }
209
+
210
+ /**
211
+ * Load the user's application or throw a descriptive error.
212
+ * @throws Runtime errors in two cases
213
+ * 1 - UserCodeSyntaxError if there's a syntax error while loading the module
214
+ * 2 - ImportModuleError if the module cannot be found
215
+ */
216
+ async function _loadUserApp(appRoot, moduleRoot, module) {
217
+ if (!NoGlobalAwsLambda) {
218
+ globalThis.awslambda = {
219
+ HttpResponseStream,
220
+ streamifyResponse: (handler, options) => {
221
+ // eslint-disable-next-line no-param-reassign
222
+ handler[HANDLER_STREAMING] = STREAM_RESPONSE
223
+ if (typeof options?.highWaterMark === "number") {
224
+ // eslint-disable-next-line no-param-reassign
225
+ handler[HANDLER_HIGHWATERMARK] = Number.parseInt(
226
+ options.highWaterMark,
227
+ 10,
228
+ )
229
+ }
230
+ return handler
231
+ },
321
232
  }
322
233
  }
323
- function _isHandlerStreaming(handler) {
324
- if (
325
- typeof handler[HANDLER_STREAMING] === "undefined" ||
326
- handler[HANDLER_STREAMING] === null ||
327
- handler[HANDLER_STREAMING] === false
328
- ) {
329
- return false
330
- }
331
- if (handler[HANDLER_STREAMING] === STREAM_RESPONSE) {
332
- return STREAM_RESPONSE
234
+
235
+ try {
236
+ return await _tryRequire(appRoot, moduleRoot, module)
237
+ } catch (e) {
238
+ if (e instanceof SyntaxError) {
239
+ throw new UserCodeSyntaxError(e)
240
+ } else if (e.code !== undefined && e.code === "MODULE_NOT_FOUND") {
241
+ verbose("globalPaths", JSON.stringify(require("node:module").globalPaths))
242
+ throw new ImportModuleError(e)
243
+ } else {
244
+ throw e
333
245
  }
334
- throw new MalformedStreamingHandler("Only response streaming is supported.")
335
246
  }
336
- module.exports.load = async function (appRoot, fullHandlerString) {
337
- _throwIfInvalidHandler(fullHandlerString)
338
- const [moduleRoot, moduleAndHandler] =
339
- _moduleRootAndHandler(fullHandlerString)
340
- const [module2, handlerPath] = _splitHandlerString(moduleAndHandler)
341
- const userApp = await _loadUserApp(appRoot, moduleRoot, module2)
342
- const handlerFunc = _resolveHandler(userApp, handlerPath)
343
- if (!handlerFunc) {
344
- throw new HandlerNotFound(
345
- `${fullHandlerString} is undefined or not exported`,
346
- )
347
- }
348
- if (typeof handlerFunc !== "function") {
349
- throw new HandlerNotFound(`${fullHandlerString} is not a function`)
350
- }
351
- return handlerFunc
247
+ }
248
+
249
+ function _throwIfInvalidHandler(fullHandlerString) {
250
+ if (fullHandlerString.includes(RELATIVE_PATH_SUBSTRING)) {
251
+ throw new MalformedHandlerName(
252
+ `'${fullHandlerString}' is not a valid handler name. Use absolute paths when specifying root directories in handler names.`,
253
+ )
352
254
  }
353
- module.exports.getHandlerMetadata = function (handlerFunc) {
354
- return {
355
- streaming: _isHandlerStreaming(handlerFunc),
356
- }
255
+ }
256
+
257
+ function _isHandlerStreaming(handler) {
258
+ if (
259
+ handler[HANDLER_STREAMING] === undefined ||
260
+ handler[HANDLER_STREAMING] === null ||
261
+ handler[HANDLER_STREAMING] === false
262
+ ) {
263
+ return false
264
+ }
265
+
266
+ if (handler[HANDLER_STREAMING] === STREAM_RESPONSE) {
267
+ return STREAM_RESPONSE
268
+ }
269
+ throw new MalformedStreamingHandler("Only response streaming is supported.")
270
+ }
271
+
272
+ function _highWaterMark(handler) {
273
+ if (
274
+ handler[HANDLER_HIGHWATERMARK] === undefined ||
275
+ handler[HANDLER_HIGHWATERMARK] === null ||
276
+ handler[HANDLER_HIGHWATERMARK] === false
277
+ ) {
278
+ return undefined
279
+ }
280
+
281
+ const hwm = Number.parseInt(handler[HANDLER_HIGHWATERMARK], 10)
282
+ return Number.isNaN(hwm) ? undefined : hwm
283
+ }
284
+
285
+ /**
286
+ * Load the user's function with the approot and the handler string.
287
+ * @param appRoot {string}
288
+ * The path to the application root.
289
+ * @param handlerString {string}
290
+ * The user-provided handler function in the form 'module.function'.
291
+ * @return userFuction {function}
292
+ * The user's handler function. This function will be passed the event body,
293
+ * the context object, and the callback function.
294
+ * @throws In five cases:-
295
+ * 1 - if the handler string is incorrectly formatted an error is thrown
296
+ * 2 - if the module referenced by the handler cannot be loaded
297
+ * 3 - if the function in the handler does not exist in the module
298
+ * 4 - if a property with the same name, but isn't a function, exists on the
299
+ * module
300
+ * 5 - the handler includes illegal character sequences (like relative paths
301
+ * for traversing up the filesystem '..')
302
+ * Errors for scenarios known by the runtime, will be wrapped by Runtime.* errors.
303
+ */
304
+ module.exports.load = async function (appRoot, fullHandlerString) {
305
+ _throwIfInvalidHandler(fullHandlerString)
306
+
307
+ const [moduleRoot, moduleAndHandler] =
308
+ _moduleRootAndHandler(fullHandlerString)
309
+ const [module, handlerPath] = _splitHandlerString(moduleAndHandler)
310
+
311
+ const userApp = await _loadUserApp(appRoot, moduleRoot, module)
312
+ const handlerFunc = _resolveHandler(userApp, handlerPath)
313
+
314
+ if (!handlerFunc) {
315
+ throw new HandlerNotFound(
316
+ `${fullHandlerString} is undefined or not exported`,
317
+ )
318
+ }
319
+
320
+ if (typeof handlerFunc !== "function") {
321
+ throw new HandlerNotFound(`${fullHandlerString} is not a function`)
322
+ }
323
+
324
+ return handlerFunc
325
+ }
326
+
327
+ module.exports.isHandlerFunction = function (value) {
328
+ return typeof value === "function"
329
+ }
330
+
331
+ module.exports.getHandlerMetadata = function (handlerFunc) {
332
+ return {
333
+ highWaterMark: _highWaterMark(handlerFunc),
334
+ streaming: _isHandlerStreaming(handlerFunc),
357
335
  }
358
- module.exports.STREAM_RESPONSE = STREAM_RESPONSE
359
- })()
336
+ }
337
+
338
+ module.exports.STREAM_RESPONSE = STREAM_RESPONSE