serverless-offline 8.8.1 → 9.0.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.
- package/README.md +3 -3
- package/package.json +33 -57
- package/src/ServerlessOffline.js +412 -0
- package/src/config/commandOptions.js +155 -0
- package/src/config/constants.js +22 -0
- package/{dist → src}/config/defaultOptions.js +8 -17
- package/src/config/index.js +4 -0
- package/src/config/supportedRuntimes.js +47 -0
- package/src/events/authCanExecuteResource.js +35 -0
- package/src/events/authFunctionNameExtractor.js +75 -0
- package/src/events/authMatchPolicyResource.js +71 -0
- package/src/events/authValidateContext.js +51 -0
- package/src/events/http/Endpoint.js +135 -0
- package/src/events/http/Http.js +50 -0
- package/src/events/http/HttpEventDefinition.js +20 -0
- package/src/events/http/HttpServer.js +1277 -0
- package/src/events/http/OfflineEndpoint.js +33 -0
- package/src/events/http/authJWTSettingsExtractor.js +70 -0
- package/src/events/http/createAuthScheme.js +176 -0
- package/src/events/http/createJWTAuthScheme.js +106 -0
- package/src/events/http/index.js +1 -0
- package/src/events/http/javaHelpers.js +102 -0
- package/src/events/http/lambda-events/LambdaIntegrationEvent.js +57 -0
- package/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js +233 -0
- package/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +190 -0
- package/src/events/http/lambda-events/VelocityContext.js +147 -0
- package/src/events/http/lambda-events/index.js +4 -0
- package/src/events/http/lambda-events/renderVelocityTemplateObject.js +93 -0
- package/{dist → src}/events/http/parseResources.js +73 -78
- package/src/events/http/payloadSchemaValidator.js +13 -0
- package/{dist → src}/events/http/templates/offline-default.req.vm +0 -0
- package/{dist → src}/events/http/templates/offline-default.res.vm +0 -0
- package/src/events/schedule/Schedule.js +131 -0
- package/src/events/schedule/ScheduleEvent.js +18 -0
- package/src/events/schedule/ScheduleEventDefinition.js +21 -0
- package/src/events/schedule/index.js +1 -0
- package/src/events/websocket/HttpServer.js +69 -0
- package/src/events/websocket/WebSocket.js +52 -0
- package/src/events/websocket/WebSocketClients.js +462 -0
- package/src/events/websocket/WebSocketEventDefinition.js +18 -0
- package/src/events/websocket/WebSocketServer.js +73 -0
- package/src/events/websocket/http-routes/_catchAll/catchAllRoute.js +16 -0
- package/src/events/websocket/http-routes/_catchAll/index.js +1 -0
- package/src/events/websocket/http-routes/connections/ConnectionsController.js +28 -0
- package/src/events/websocket/http-routes/connections/connectionsRoutes.js +70 -0
- package/src/events/websocket/http-routes/connections/index.js +1 -0
- package/src/events/websocket/http-routes/index.js +2 -0
- package/src/events/websocket/index.js +1 -0
- package/src/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +65 -0
- package/src/events/websocket/lambda-events/WebSocketConnectEvent.js +68 -0
- package/src/events/websocket/lambda-events/WebSocketDisconnectEvent.js +31 -0
- package/src/events/websocket/lambda-events/WebSocketEvent.js +29 -0
- package/src/events/websocket/lambda-events/WebSocketRequestContext.js +67 -0
- package/src/events/websocket/lambda-events/index.js +4 -0
- package/src/index.js +12 -0
- package/src/lambda/HttpServer.js +108 -0
- package/src/lambda/Lambda.js +68 -0
- package/src/lambda/LambdaContext.js +33 -0
- package/src/lambda/LambdaFunction.js +308 -0
- package/src/lambda/LambdaFunctionPool.js +109 -0
- package/src/lambda/__tests__/LambdaContext.test.js +30 -0
- package/src/lambda/__tests__/LambdaFunction.test.js +196 -0
- package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsJSONObject.fixture.js +47 -0
- package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsNativeString.fixture.js +46 -0
- package/src/lambda/__tests__/fixtures/Lambda/package.json +3 -0
- package/src/lambda/__tests__/fixtures/lambdaFunction.fixture.js +145 -0
- package/src/lambda/__tests__/fixtures/package.json +3 -0
- package/src/lambda/__tests__/routes/invocations/InvocationsController.test.js +42 -0
- package/src/lambda/handler-runner/HandlerRunner.js +136 -0
- package/src/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +72 -0
- package/src/lambda/handler-runner/child-process-runner/childProcessHelper.js +42 -0
- package/src/lambda/handler-runner/child-process-runner/index.js +1 -0
- package/src/lambda/handler-runner/docker-runner/DockerContainer.js +417 -0
- package/src/lambda/handler-runner/docker-runner/DockerImage.js +35 -0
- package/src/lambda/handler-runner/docker-runner/DockerRunner.js +63 -0
- package/src/lambda/handler-runner/docker-runner/index.js +1 -0
- package/src/lambda/handler-runner/go-runner/GoRunner.js +166 -0
- package/src/lambda/handler-runner/go-runner/index.js +1 -0
- package/src/lambda/handler-runner/in-process-runner/InProcessRunner.js +125 -0
- package/src/lambda/handler-runner/in-process-runner/index.js +1 -0
- package/src/lambda/handler-runner/index.js +1 -0
- package/src/lambda/handler-runner/java-runner/JavaRunner.js +114 -0
- package/src/lambda/handler-runner/java-runner/index.js +1 -0
- package/src/lambda/handler-runner/python-runner/PythonRunner.js +138 -0
- package/src/lambda/handler-runner/python-runner/index.js +1 -0
- package/{dist → src}/lambda/handler-runner/python-runner/invoke.py +0 -0
- package/src/lambda/handler-runner/ruby-runner/RubyRunner.js +107 -0
- package/src/lambda/handler-runner/ruby-runner/index.js +1 -0
- package/{dist → src}/lambda/handler-runner/ruby-runner/invoke.rb +0 -0
- package/src/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +70 -0
- package/src/lambda/handler-runner/worker-thread-runner/index.js +1 -0
- package/src/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +29 -0
- package/src/lambda/index.js +1 -0
- package/src/lambda/routes/index.js +2 -0
- package/src/lambda/routes/invocations/InvocationsController.js +102 -0
- package/src/lambda/routes/invocations/index.js +1 -0
- package/src/lambda/routes/invocations/invocationsRoute.js +77 -0
- package/src/lambda/routes/invoke-async/InvokeAsyncController.js +20 -0
- package/src/lambda/routes/invoke-async/index.js +1 -0
- package/src/lambda/routes/invoke-async/invokeAsyncRoute.js +33 -0
- package/src/utils/__tests__/createUniqueId.test.js +18 -0
- package/src/utils/__tests__/formatToClfTime.test.js +14 -0
- package/src/utils/__tests__/generateHapiPath.test.js +46 -0
- package/src/utils/__tests__/lowerCaseKeys.test.js +30 -0
- package/src/utils/__tests__/parseHeaders.test.js +13 -0
- package/src/utils/__tests__/parseMultiValueHeaders.test.js +24 -0
- package/src/utils/__tests__/parseMultiValueQueryStringParameters.test.js +159 -0
- package/src/utils/__tests__/parseQueryStringParameters.test.js +15 -0
- package/src/utils/__tests__/splitHandlerPathAndName.test.js +54 -0
- package/src/utils/__tests__/unflatten.test.js +32 -0
- package/src/utils/checkDockerDaemon.js +19 -0
- package/src/utils/checkGoVersion.js +16 -0
- package/src/utils/createApiKey.js +5 -0
- package/src/utils/createUniqueId.js +5 -0
- package/src/utils/detectExecutable.js +11 -0
- package/{dist → src}/utils/formatToClfTime.js +6 -14
- package/src/utils/generateHapiPath.js +26 -0
- package/src/utils/getHttpApiCorsConfig.js +28 -0
- package/src/utils/index.js +42 -0
- package/src/utils/jsonPath.js +13 -0
- package/src/utils/logRoutes.js +64 -0
- package/src/utils/lowerCaseKeys.js +6 -0
- package/src/utils/parseHeaders.js +14 -0
- package/src/utils/parseMultiValueHeaders.js +27 -0
- package/src/utils/parseMultiValueQueryStringParameters.js +31 -0
- package/src/utils/parseQueryStringParameters.js +15 -0
- package/src/utils/resolveJoins.js +29 -0
- package/src/utils/splitHandlerPathAndName.js +31 -0
- package/src/utils/unflatten.js +11 -0
- package/CHANGELOG.md +0 -78
- package/dist/ServerlessOffline.js +0 -508
- package/dist/config/commandOptions.js +0 -149
- package/dist/config/constants.js +0 -30
- package/dist/config/index.js +0 -55
- package/dist/config/supportedRuntimes.js +0 -40
- package/dist/debugLog.js +0 -12
- package/dist/events/authCanExecuteResource.js +0 -35
- package/dist/events/authFunctionNameExtractor.js +0 -87
- package/dist/events/authMatchPolicyResource.js +0 -62
- package/dist/events/authValidateContext.js +0 -53
- package/dist/events/http/Endpoint.js +0 -173
- package/dist/events/http/Http.js +0 -77
- package/dist/events/http/HttpEventDefinition.js +0 -36
- package/dist/events/http/HttpServer.js +0 -1370
- package/dist/events/http/OfflineEndpoint.js +0 -38
- package/dist/events/http/authJWTSettingsExtractor.js +0 -76
- package/dist/events/http/createAuthScheme.js +0 -184
- package/dist/events/http/createJWTAuthScheme.js +0 -159
- package/dist/events/http/index.js +0 -15
- package/dist/events/http/javaHelpers.js +0 -99
- package/dist/events/http/lambda-events/LambdaIntegrationEvent.js +0 -87
- package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +0 -246
- package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +0 -225
- package/dist/events/http/lambda-events/VelocityContext.js +0 -170
- package/dist/events/http/lambda-events/index.js +0 -39
- package/dist/events/http/lambda-events/renderVelocityTemplateObject.js +0 -111
- package/dist/events/http/payloadSchemaValidator.js +0 -13
- package/dist/events/schedule/Schedule.js +0 -183
- package/dist/events/schedule/ScheduleEvent.js +0 -27
- package/dist/events/schedule/ScheduleEventDefinition.js +0 -36
- package/dist/events/schedule/index.js +0 -15
- package/dist/events/websocket/HttpServer.js +0 -114
- package/dist/events/websocket/WebSocket.js +0 -78
- package/dist/events/websocket/WebSocketClients.js +0 -577
- package/dist/events/websocket/WebSocketEventDefinition.js +0 -32
- package/dist/events/websocket/WebSocketServer.js +0 -139
- package/dist/events/websocket/http-routes/_catchAll/catchAllRoute.js +0 -33
- package/dist/events/websocket/http-routes/_catchAll/index.js +0 -15
- package/dist/events/websocket/http-routes/connections/ConnectionsController.js +0 -45
- package/dist/events/websocket/http-routes/connections/connectionsRoutes.js +0 -95
- package/dist/events/websocket/http-routes/connections/index.js +0 -15
- package/dist/events/websocket/http-routes/index.js +0 -23
- package/dist/events/websocket/index.js +0 -15
- package/dist/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +0 -99
- package/dist/events/websocket/lambda-events/WebSocketConnectEvent.js +0 -101
- package/dist/events/websocket/lambda-events/WebSocketDisconnectEvent.js +0 -47
- package/dist/events/websocket/lambda-events/WebSocketEvent.js +0 -54
- package/dist/events/websocket/lambda-events/WebSocketRequestContext.js +0 -98
- package/dist/events/websocket/lambda-events/index.js +0 -39
- package/dist/index.js +0 -15
- package/dist/lambda/HttpServer.js +0 -124
- package/dist/lambda/Lambda.js +0 -117
- package/dist/lambda/LambdaContext.js +0 -53
- package/dist/lambda/LambdaFunction.js +0 -390
- package/dist/lambda/LambdaFunctionPool.js +0 -127
- package/dist/lambda/handler-runner/HandlerRunner.js +0 -195
- package/dist/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +0 -124
- package/dist/lambda/handler-runner/child-process-runner/childProcessHelper.js +0 -49
- package/dist/lambda/handler-runner/child-process-runner/index.js +0 -15
- package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +0 -515
- package/dist/lambda/handler-runner/docker-runner/DockerImage.js +0 -67
- package/dist/lambda/handler-runner/docker-runner/DockerRunner.js +0 -74
- package/dist/lambda/handler-runner/docker-runner/index.js +0 -15
- package/dist/lambda/handler-runner/go-runner/GoRunner.js +0 -230
- package/dist/lambda/handler-runner/go-runner/index.js +0 -15
- package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +0 -228
- package/dist/lambda/handler-runner/in-process-runner/index.js +0 -15
- package/dist/lambda/handler-runner/index.js +0 -15
- package/dist/lambda/handler-runner/java-runner/JavaRunner.js +0 -153
- package/dist/lambda/handler-runner/java-runner/index.js +0 -15
- package/dist/lambda/handler-runner/python-runner/PythonRunner.js +0 -185
- package/dist/lambda/handler-runner/python-runner/index.js +0 -15
- package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +0 -147
- package/dist/lambda/handler-runner/ruby-runner/index.js +0 -15
- package/dist/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +0 -92
- package/dist/lambda/handler-runner/worker-thread-runner/index.js +0 -15
- package/dist/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +0 -31
- package/dist/lambda/index.js +0 -15
- package/dist/lambda/routes/index.js +0 -23
- package/dist/lambda/routes/invocations/InvocationsController.js +0 -142
- package/dist/lambda/routes/invocations/index.js +0 -15
- package/dist/lambda/routes/invocations/invocationsRoute.js +0 -90
- package/dist/lambda/routes/invoke-async/InvokeAsyncController.js +0 -38
- package/dist/lambda/routes/invoke-async/index.js +0 -15
- package/dist/lambda/routes/invoke-async/invokeAsyncRoute.js +0 -43
- package/dist/main.js +0 -11
- package/dist/serverlessLog.js +0 -91
- package/dist/utils/checkDockerDaemon.js +0 -27
- package/dist/utils/checkGoVersion.js +0 -27
- package/dist/utils/createApiKey.js +0 -12
- package/dist/utils/createUniqueId.js +0 -14
- package/dist/utils/detectExecutable.js +0 -21
- package/dist/utils/generateHapiPath.js +0 -28
- package/dist/utils/getHttpApiCorsConfig.js +0 -40
- package/dist/utils/index.js +0 -165
- package/dist/utils/jsonPath.js +0 -21
- package/dist/utils/lowerCaseKeys.js +0 -14
- package/dist/utils/parseHeaders.js +0 -23
- package/dist/utils/parseMultiValueHeaders.js +0 -36
- package/dist/utils/parseMultiValueQueryStringParameters.js +0 -40
- package/dist/utils/parseQueryStringParameters.js +0 -26
- package/dist/utils/resolveJoins.js +0 -36
- package/dist/utils/satisfiesVersionRange.js +0 -20
- package/dist/utils/splitHandlerPathAndName.js +0 -37
- package/dist/utils/unflatten.js +0 -18
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises'
|
|
2
|
+
import { dirname, join, resolve } from 'node:path'
|
|
3
|
+
import { performance } from 'node:perf_hooks'
|
|
4
|
+
import { log } from '@serverless/utils/log.js'
|
|
5
|
+
import { emptyDir, ensureDir, remove } from 'fs-extra'
|
|
6
|
+
import jszip from 'jszip'
|
|
7
|
+
import HandlerRunner from './handler-runner/index.js'
|
|
8
|
+
import LambdaContext from './LambdaContext.js'
|
|
9
|
+
import resolveJoins from '../utils/resolveJoins.js'
|
|
10
|
+
import {
|
|
11
|
+
DEFAULT_LAMBDA_MEMORY_SIZE,
|
|
12
|
+
DEFAULT_LAMBDA_RUNTIME,
|
|
13
|
+
DEFAULT_LAMBDA_TIMEOUT,
|
|
14
|
+
supportedRuntimes,
|
|
15
|
+
} from '../config/index.js'
|
|
16
|
+
import { createUniqueId, splitHandlerPathAndName } from '../utils/index.js'
|
|
17
|
+
|
|
18
|
+
const { entries } = Object
|
|
19
|
+
const { ceil } = Math
|
|
20
|
+
|
|
21
|
+
export default class LambdaFunction {
|
|
22
|
+
#artifact = null
|
|
23
|
+
|
|
24
|
+
#clientContext = null
|
|
25
|
+
|
|
26
|
+
#codeDir = null
|
|
27
|
+
|
|
28
|
+
#event = null
|
|
29
|
+
|
|
30
|
+
#executionTimeEnded = null
|
|
31
|
+
|
|
32
|
+
#executionTimeStarted = null
|
|
33
|
+
|
|
34
|
+
#functionKey = null
|
|
35
|
+
|
|
36
|
+
#functionName = null
|
|
37
|
+
|
|
38
|
+
#handlerRunner = null
|
|
39
|
+
|
|
40
|
+
#idleTimeStarted = null
|
|
41
|
+
|
|
42
|
+
#initialized = false
|
|
43
|
+
|
|
44
|
+
#lambdaContext = null
|
|
45
|
+
|
|
46
|
+
#lambdaDir = null
|
|
47
|
+
|
|
48
|
+
#memorySize = null
|
|
49
|
+
|
|
50
|
+
#region = null
|
|
51
|
+
|
|
52
|
+
#runtime = null
|
|
53
|
+
|
|
54
|
+
#timeout = null
|
|
55
|
+
|
|
56
|
+
status = 'IDLE' // can be 'BUSY' or 'IDLE'
|
|
57
|
+
|
|
58
|
+
constructor(functionKey, functionDefinition, serverless, options) {
|
|
59
|
+
const {
|
|
60
|
+
service,
|
|
61
|
+
config: { serverlessPath, servicePath },
|
|
62
|
+
service: { provider, package: servicePackage = {} },
|
|
63
|
+
} = serverless
|
|
64
|
+
|
|
65
|
+
// TEMP options.location, for compatibility with serverless-webpack:
|
|
66
|
+
// https://github.com/dherault/serverless-offline/issues/787
|
|
67
|
+
// TODO FIXME look into better way to work with serverless-webpack
|
|
68
|
+
const servicepath = resolve(servicePath, options.location || '')
|
|
69
|
+
|
|
70
|
+
const { handler, name, package: functionPackage = {} } = functionDefinition
|
|
71
|
+
const [handlerPath, handlerName] = splitHandlerPathAndName(handler)
|
|
72
|
+
|
|
73
|
+
const memorySize =
|
|
74
|
+
functionDefinition.memorySize ||
|
|
75
|
+
provider.memorySize ||
|
|
76
|
+
DEFAULT_LAMBDA_MEMORY_SIZE
|
|
77
|
+
|
|
78
|
+
const runtime =
|
|
79
|
+
functionDefinition.runtime || provider.runtime || DEFAULT_LAMBDA_RUNTIME
|
|
80
|
+
|
|
81
|
+
const timeout =
|
|
82
|
+
(functionDefinition.timeout ||
|
|
83
|
+
provider.timeout ||
|
|
84
|
+
DEFAULT_LAMBDA_TIMEOUT) * 1000
|
|
85
|
+
|
|
86
|
+
// this._executionTimeout = null
|
|
87
|
+
this.#functionKey = functionKey
|
|
88
|
+
this.#functionName = name
|
|
89
|
+
this.#memorySize = memorySize
|
|
90
|
+
this.#region = provider.region
|
|
91
|
+
this.#runtime = runtime
|
|
92
|
+
this.#timeout = timeout
|
|
93
|
+
|
|
94
|
+
this.#verifySupportedRuntime()
|
|
95
|
+
|
|
96
|
+
const env = this.#getEnv(
|
|
97
|
+
resolveJoins(provider.environment),
|
|
98
|
+
functionDefinition.environment,
|
|
99
|
+
handler,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
this.#artifact = functionDefinition.package?.artifact
|
|
103
|
+
|
|
104
|
+
if (!this.#artifact) {
|
|
105
|
+
this.#artifact = service.package?.artifact
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (this.#artifact) {
|
|
109
|
+
// lambda directory contains code and layers
|
|
110
|
+
this.#lambdaDir = join(
|
|
111
|
+
servicepath,
|
|
112
|
+
'.serverless-offline',
|
|
113
|
+
'services',
|
|
114
|
+
service.service,
|
|
115
|
+
functionKey,
|
|
116
|
+
createUniqueId(),
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.#codeDir = this.#lambdaDir
|
|
121
|
+
? resolve(this.#lambdaDir, 'code')
|
|
122
|
+
: servicepath
|
|
123
|
+
|
|
124
|
+
// TEMP
|
|
125
|
+
const funOptions = {
|
|
126
|
+
codeDir: this.#codeDir,
|
|
127
|
+
functionKey,
|
|
128
|
+
functionName: name,
|
|
129
|
+
functionPackage: functionPackage.artifact
|
|
130
|
+
? resolve(servicepath, functionPackage.artifact)
|
|
131
|
+
: undefined,
|
|
132
|
+
handler,
|
|
133
|
+
handlerName,
|
|
134
|
+
handlerPath: resolve(this.#codeDir, handlerPath),
|
|
135
|
+
layers: functionDefinition.layers || [],
|
|
136
|
+
provider,
|
|
137
|
+
runtime,
|
|
138
|
+
serverlessPath,
|
|
139
|
+
servicePackage: servicePackage.artifact
|
|
140
|
+
? resolve(servicepath, servicePackage.artifact)
|
|
141
|
+
: undefined,
|
|
142
|
+
servicePath: servicepath,
|
|
143
|
+
timeout,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
this.#handlerRunner = new HandlerRunner(funOptions, options, env)
|
|
147
|
+
this.#lambdaContext = new LambdaContext(name, memorySize)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
#startExecutionTimer() {
|
|
151
|
+
this.#executionTimeStarted = performance.now()
|
|
152
|
+
// this._executionTimeout = this.#executionTimeStarted + this.#timeout * 1000
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
#stopExecutionTimer() {
|
|
156
|
+
this.#executionTimeEnded = performance.now()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
#startIdleTimer() {
|
|
160
|
+
this.#idleTimeStarted = performance.now()
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
#verifySupportedRuntime() {
|
|
164
|
+
// print message but keep working (don't error out or exit process)
|
|
165
|
+
if (!supportedRuntimes.has(this.#runtime)) {
|
|
166
|
+
log.warning()
|
|
167
|
+
log.warning(
|
|
168
|
+
`Warning: found unsupported runtime '${this.#runtime}' for function '${
|
|
169
|
+
this.#functionKey
|
|
170
|
+
}'`,
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// based on:
|
|
176
|
+
// https://github.com/serverless/serverless/blob/v1.50.0/lib/plugins/aws/invokeLocal/index.js#L108
|
|
177
|
+
#getAwsEnvVars() {
|
|
178
|
+
return {
|
|
179
|
+
AWS_DEFAULT_REGION: this.#region,
|
|
180
|
+
AWS_LAMBDA_FUNCTION_MEMORY_SIZE: this.#memorySize,
|
|
181
|
+
AWS_LAMBDA_FUNCTION_NAME: this.#functionName,
|
|
182
|
+
AWS_LAMBDA_FUNCTION_VERSION: '$LATEST',
|
|
183
|
+
// https://github.com/serverless/serverless/blob/v1.50.0/lib/plugins/aws/lib/naming.js#L123
|
|
184
|
+
AWS_LAMBDA_LOG_GROUP_NAME: `/aws/lambda/${this.#functionName}`,
|
|
185
|
+
AWS_LAMBDA_LOG_STREAM_NAME:
|
|
186
|
+
'2016/12/02/[$LATEST]f77ff5e4026c45bda9a9ebcec6bc9cad',
|
|
187
|
+
AWS_REGION: this.#region,
|
|
188
|
+
LAMBDA_RUNTIME_DIR: '/var/runtime',
|
|
189
|
+
LAMBDA_TASK_ROOT: '/var/task',
|
|
190
|
+
LANG: 'en_US.UTF-8',
|
|
191
|
+
LD_LIBRARY_PATH:
|
|
192
|
+
'/usr/local/lib64/node-v4.3.x/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib',
|
|
193
|
+
NODE_PATH: '/var/runtime:/var/task:/var/runtime/node_modules',
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
#getEnv(providerEnv, functionDefinitionEnv, handler) {
|
|
198
|
+
return {
|
|
199
|
+
...this.#getAwsEnvVars(),
|
|
200
|
+
...providerEnv,
|
|
201
|
+
...functionDefinitionEnv,
|
|
202
|
+
_HANDLER: handler, // TODO is this available in AWS?
|
|
203
|
+
IS_OFFLINE: true,
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
setClientContext(clientContext) {
|
|
208
|
+
this.#clientContext = clientContext
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
setEvent(event) {
|
|
212
|
+
this.#event = event
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// () => Promise<void>
|
|
216
|
+
async cleanup() {
|
|
217
|
+
// TODO console.log('lambda cleanup')
|
|
218
|
+
await this.#handlerRunner.cleanup()
|
|
219
|
+
if (this.#lambdaDir) {
|
|
220
|
+
await remove(this.#lambdaDir)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
#executionTimeInMillis() {
|
|
225
|
+
return this.#executionTimeEnded - this.#executionTimeStarted
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// round up to the nearest ms
|
|
229
|
+
#billedExecutionTimeInMillis() {
|
|
230
|
+
return ceil(this.#executionTimeEnded - this.#executionTimeStarted)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// extractArtifact, loosely based on:
|
|
234
|
+
// https://github.com/serverless/serverless/blob/v1.57.0/lib/plugins/aws/invokeLocal/index.js#L312
|
|
235
|
+
async #extractArtifact() {
|
|
236
|
+
if (!this.#artifact) {
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
await emptyDir(this.#codeDir)
|
|
241
|
+
|
|
242
|
+
const data = await readFile(this.#artifact)
|
|
243
|
+
const zip = await jszip.loadAsync(data)
|
|
244
|
+
|
|
245
|
+
await Promise.all(
|
|
246
|
+
entries(zip.files).map(async ([filename, jsZipObj]) => {
|
|
247
|
+
const fileData = await jsZipObj.async('nodebuffer')
|
|
248
|
+
if (filename.endsWith('/')) {
|
|
249
|
+
return Promise.resolve()
|
|
250
|
+
}
|
|
251
|
+
await ensureDir(join(this.#codeDir, dirname(filename)))
|
|
252
|
+
return writeFile(join(this.#codeDir, filename), fileData, {
|
|
253
|
+
mode: jsZipObj.unixPermissions,
|
|
254
|
+
})
|
|
255
|
+
}),
|
|
256
|
+
)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async #initialize() {
|
|
260
|
+
await this.#extractArtifact()
|
|
261
|
+
this.#initialized = true
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
get idleTimeInMinutes() {
|
|
265
|
+
return (performance.now() - this.#idleTimeStarted) / 1000 / 60
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
get functionName() {
|
|
269
|
+
return this.#functionName
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async runHandler() {
|
|
273
|
+
this.status = 'BUSY'
|
|
274
|
+
|
|
275
|
+
if (!this.#initialized) {
|
|
276
|
+
await this.#initialize()
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const requestId = createUniqueId()
|
|
280
|
+
|
|
281
|
+
this.#lambdaContext.setRequestId(requestId)
|
|
282
|
+
this.#lambdaContext.setClientContext(this.#clientContext)
|
|
283
|
+
|
|
284
|
+
const context = this.#lambdaContext.create()
|
|
285
|
+
|
|
286
|
+
this.#startExecutionTimer()
|
|
287
|
+
|
|
288
|
+
const result = await this.#handlerRunner.run(this.#event, context)
|
|
289
|
+
|
|
290
|
+
this.#stopExecutionTimer()
|
|
291
|
+
|
|
292
|
+
// TEMP TODO FIXME find better solution
|
|
293
|
+
if (!this.#handlerRunner.isDockerRunner()) {
|
|
294
|
+
log.notice(
|
|
295
|
+
`(λ: ${
|
|
296
|
+
this.#functionKey
|
|
297
|
+
}) RequestId: ${requestId} Duration: ${this.#executionTimeInMillis().toFixed(
|
|
298
|
+
2,
|
|
299
|
+
)} ms Billed Duration: ${this.#billedExecutionTimeInMillis()} ms`,
|
|
300
|
+
)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
this.status = 'IDLE'
|
|
304
|
+
this.#startIdleTimer()
|
|
305
|
+
|
|
306
|
+
return result
|
|
307
|
+
}
|
|
308
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import LambdaFunction from './LambdaFunction.js'
|
|
2
|
+
|
|
3
|
+
export default class LambdaFunctionPool {
|
|
4
|
+
#options = null
|
|
5
|
+
|
|
6
|
+
#pool = new Map()
|
|
7
|
+
|
|
8
|
+
#serverless = null
|
|
9
|
+
|
|
10
|
+
#timerRef = null
|
|
11
|
+
|
|
12
|
+
constructor(serverless, options) {
|
|
13
|
+
this.#options = options
|
|
14
|
+
this.#serverless = serverless
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
start() {
|
|
18
|
+
// start cleaner
|
|
19
|
+
this.#startCleanTimer()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#startCleanTimer() {
|
|
23
|
+
// NOTE: don't use setInterval, as it would schedule always a new run,
|
|
24
|
+
// regardless of function processing time and e.g. user action (debugging)
|
|
25
|
+
this.#timerRef = setTimeout(() => {
|
|
26
|
+
// console.log('run cleanup')
|
|
27
|
+
this.#pool.forEach((lambdaFunctions) => {
|
|
28
|
+
lambdaFunctions.forEach((lambdaFunction) => {
|
|
29
|
+
const { idleTimeInMinutes, status } = lambdaFunction
|
|
30
|
+
// console.log(idleTimeInMinutes, status)
|
|
31
|
+
|
|
32
|
+
if (
|
|
33
|
+
status === 'IDLE' &&
|
|
34
|
+
idleTimeInMinutes >=
|
|
35
|
+
this.#options.functionCleanupIdleTimeSeconds / 60
|
|
36
|
+
) {
|
|
37
|
+
// console.log(`removed Lambda Function ${lambdaFunction.functionName}`)
|
|
38
|
+
lambdaFunction.cleanup()
|
|
39
|
+
lambdaFunctions.delete(lambdaFunction)
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// schedule new timer
|
|
45
|
+
this.#startCleanTimer()
|
|
46
|
+
}, (this.#options.functionCleanupIdleTimeSeconds * 1000) / 2)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
#cleanupPool() {
|
|
50
|
+
const wait = []
|
|
51
|
+
|
|
52
|
+
this.#pool.forEach((lambdaFunctions) => {
|
|
53
|
+
lambdaFunctions.forEach((lambdaFunction) => {
|
|
54
|
+
// collect promises
|
|
55
|
+
wait.push(lambdaFunction.cleanup())
|
|
56
|
+
lambdaFunctions.delete(lambdaFunction)
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
return Promise.all(wait)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// TODO make sure to call this
|
|
64
|
+
async cleanup() {
|
|
65
|
+
clearTimeout(this.#timerRef)
|
|
66
|
+
|
|
67
|
+
return this.#cleanupPool()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get(functionKey, functionDefinition) {
|
|
71
|
+
const lambdaFunctions = this.#pool.get(functionKey)
|
|
72
|
+
let lambdaFunction
|
|
73
|
+
|
|
74
|
+
// we don't have any instances
|
|
75
|
+
if (lambdaFunctions == null) {
|
|
76
|
+
lambdaFunction = new LambdaFunction(
|
|
77
|
+
functionKey,
|
|
78
|
+
functionDefinition,
|
|
79
|
+
this.#serverless,
|
|
80
|
+
this.#options,
|
|
81
|
+
)
|
|
82
|
+
this.#pool.set(functionKey, new Set([lambdaFunction]))
|
|
83
|
+
|
|
84
|
+
return lambdaFunction
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!this.#options.reloadHandler) {
|
|
88
|
+
// find any IDLE
|
|
89
|
+
lambdaFunction = Array.from(lambdaFunctions).find(
|
|
90
|
+
({ status }) => status === 'IDLE',
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
if (lambdaFunction != null) {
|
|
94
|
+
return lambdaFunction
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// we don't have any IDLE instances
|
|
99
|
+
lambdaFunction = new LambdaFunction(
|
|
100
|
+
functionKey,
|
|
101
|
+
functionDefinition,
|
|
102
|
+
this.#serverless,
|
|
103
|
+
this.#options,
|
|
104
|
+
)
|
|
105
|
+
lambdaFunctions.add(lambdaFunction)
|
|
106
|
+
|
|
107
|
+
return lambdaFunction
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import LambdaContext from '../LambdaContext.js'
|
|
3
|
+
|
|
4
|
+
describe('LambdaContext', () => {
|
|
5
|
+
it('should create LambdaContext with correct values', () => {
|
|
6
|
+
const functionName = 'foo'
|
|
7
|
+
const memorySize = 512
|
|
8
|
+
const requestId = 'abc123'
|
|
9
|
+
|
|
10
|
+
const lambdaContext = new LambdaContext(functionName, memorySize)
|
|
11
|
+
lambdaContext.setRequestId(requestId)
|
|
12
|
+
const context = lambdaContext.create()
|
|
13
|
+
|
|
14
|
+
const expected = {
|
|
15
|
+
awsRequestId: 'abc123',
|
|
16
|
+
callbackWaitsForEmptyEventLoop: true,
|
|
17
|
+
clientContext: undefined,
|
|
18
|
+
functionName: 'foo',
|
|
19
|
+
functionVersion: '$LATEST',
|
|
20
|
+
identity: undefined,
|
|
21
|
+
invokedFunctionArn: 'offline_invokedFunctionArn_for_foo',
|
|
22
|
+
logGroupName: 'offline_logGroupName_for_foo',
|
|
23
|
+
logStreamName: 'offline_logStreamName_for_foo',
|
|
24
|
+
memoryLimitInMB: '512',
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// expect(context).toEqual(expected)
|
|
28
|
+
assert.deepEqual(context, expected)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import { dirname, resolve } from 'node:path'
|
|
3
|
+
// import { performance } from 'node:perf_hooks'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import LambdaFunction from '../LambdaFunction.js'
|
|
6
|
+
import { DEFAULT_LAMBDA_TIMEOUT } from '../../config/index.js'
|
|
7
|
+
|
|
8
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
|
|
10
|
+
describe('LambdaFunction', () => {
|
|
11
|
+
const functionName = 'foo'
|
|
12
|
+
|
|
13
|
+
const serverless = {
|
|
14
|
+
config: {
|
|
15
|
+
serverlessPath: '',
|
|
16
|
+
servicePath: resolve(__dirname),
|
|
17
|
+
},
|
|
18
|
+
service: {
|
|
19
|
+
provider: {
|
|
20
|
+
runtime: 'nodejs12.x',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
describe('Handler tests', () => {
|
|
26
|
+
;[
|
|
27
|
+
{
|
|
28
|
+
description: 'should return result when handler is context.done',
|
|
29
|
+
expected: 'foo',
|
|
30
|
+
handler: 'fixtures/lambdaFunction.fixture.contextDoneHandler',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
description:
|
|
34
|
+
'should return result when handler is context.done which is deferred',
|
|
35
|
+
expected: 'foo',
|
|
36
|
+
handler: 'fixtures/lambdaFunction.fixture.contextDoneHandlerDeferred',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
description: 'should return result when handler is context.succeed',
|
|
40
|
+
expected: 'foo',
|
|
41
|
+
handler: 'fixtures/lambdaFunction.fixture.contextSucceedHandler',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
description:
|
|
45
|
+
'should return result when handler is context.succeed which is deferred',
|
|
46
|
+
expected: 'foo',
|
|
47
|
+
handler:
|
|
48
|
+
'fixtures/lambdaFunction.fixture.contextSucceedHandlerDeferred',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
description: 'should return result when handler is a callback',
|
|
52
|
+
expected: 'foo',
|
|
53
|
+
handler: 'fixtures/lambdaFunction.fixture.callbackHandler',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
description:
|
|
57
|
+
'should return result when handler is a callback which is deferred',
|
|
58
|
+
expected: 'foo',
|
|
59
|
+
handler: 'fixtures/lambdaFunction.fixture.callbackHandlerDeferred',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
description: 'should return result when handler returns a promise',
|
|
63
|
+
expected: 'foo',
|
|
64
|
+
handler: 'fixtures/lambdaFunction.fixture.promiseHandler',
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
description:
|
|
68
|
+
'should return result when handler returns a promise which is deferred',
|
|
69
|
+
expected: 'foo',
|
|
70
|
+
handler: 'fixtures/lambdaFunction.fixture.promiseHandlerDeferred',
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
description: 'should return result when handler is an async function',
|
|
74
|
+
expected: 'foo',
|
|
75
|
+
handler: 'fixtures/lambdaFunction.fixture.asyncFunctionHandler',
|
|
76
|
+
},
|
|
77
|
+
// NOTE: mix and matching of callbacks and promises is not recommended,
|
|
78
|
+
// nonetheless, we test some of the behaviour to match AWS execution precedence
|
|
79
|
+
{
|
|
80
|
+
description:
|
|
81
|
+
'should return result when handler returns a callback but defines a callback parameter',
|
|
82
|
+
expected: 'Hello Promise!',
|
|
83
|
+
handler:
|
|
84
|
+
'fixtures/lambdaFunction.fixture.promiseWithDefinedCallbackHandler',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
description:
|
|
88
|
+
'should return result when handler calls context.succeed and context.done',
|
|
89
|
+
expected: 'Hello Context.succeed!',
|
|
90
|
+
handler:
|
|
91
|
+
'fixtures/lambdaFunction.fixture.contextSucceedWithContextDoneHandler',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
description:
|
|
95
|
+
'should return result when handler calls callback and context.done',
|
|
96
|
+
expected: 'Hello Callback!',
|
|
97
|
+
handler:
|
|
98
|
+
'fixtures/lambdaFunction.fixture.callbackWithContextDoneHandler',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
description:
|
|
102
|
+
'should return result when handler calls callback and returns Promise',
|
|
103
|
+
expected: 'Hello Callback!',
|
|
104
|
+
handler: 'fixtures/lambdaFunction.fixture.callbackWithPromiseHandler',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
description:
|
|
108
|
+
'should return result when handler calls callback inside returned Promise',
|
|
109
|
+
expected: 'Hello Callback!',
|
|
110
|
+
handler: 'fixtures/lambdaFunction.fixture.callbackInsidePromiseHandler',
|
|
111
|
+
},
|
|
112
|
+
].forEach(({ description, expected, handler }) => {
|
|
113
|
+
it(description, async () => {
|
|
114
|
+
const functionDefinition = {
|
|
115
|
+
handler,
|
|
116
|
+
}
|
|
117
|
+
const options = {}
|
|
118
|
+
const lambdaFunction = new LambdaFunction(
|
|
119
|
+
functionName,
|
|
120
|
+
functionDefinition,
|
|
121
|
+
serverless,
|
|
122
|
+
options,
|
|
123
|
+
)
|
|
124
|
+
const result = await lambdaFunction.runHandler()
|
|
125
|
+
|
|
126
|
+
await lambdaFunction.cleanup()
|
|
127
|
+
|
|
128
|
+
assert.equal(result, expected)
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('should pass remaining time to LambdaContext', async () => {
|
|
134
|
+
const functionDefinition = {
|
|
135
|
+
handler: 'fixtures/lambdaFunction.fixture.remainingExecutionTimeHandler',
|
|
136
|
+
}
|
|
137
|
+
const options = {}
|
|
138
|
+
const lambdaFunction = new LambdaFunction(
|
|
139
|
+
functionName,
|
|
140
|
+
functionDefinition,
|
|
141
|
+
serverless,
|
|
142
|
+
options,
|
|
143
|
+
)
|
|
144
|
+
const [first, second, third] = await lambdaFunction.runHandler()
|
|
145
|
+
|
|
146
|
+
await lambdaFunction.cleanup()
|
|
147
|
+
|
|
148
|
+
// handler "pauses" for 100 ms
|
|
149
|
+
assert.ok(first > second - 100)
|
|
150
|
+
assert.ok(second > third - 200)
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it.skip('should use default lambda timeout when timeout is not provided', async () => {
|
|
154
|
+
const functionDefinition = {
|
|
155
|
+
handler: 'fixtures/lambdaFunction.fixture.defaultTimeoutHandler',
|
|
156
|
+
}
|
|
157
|
+
const options = {}
|
|
158
|
+
const lambdaFunction = new LambdaFunction(
|
|
159
|
+
functionName,
|
|
160
|
+
functionDefinition,
|
|
161
|
+
serverless,
|
|
162
|
+
options,
|
|
163
|
+
)
|
|
164
|
+
const remainingTime = await lambdaFunction.runHandler()
|
|
165
|
+
|
|
166
|
+
await lambdaFunction.cleanup()
|
|
167
|
+
|
|
168
|
+
assert.ok(remainingTime < DEFAULT_LAMBDA_TIMEOUT * 1000)
|
|
169
|
+
|
|
170
|
+
// result might be flaky/unreliable:
|
|
171
|
+
// (assmuning handler runs no longer than 1 s)
|
|
172
|
+
assert.ok(remainingTime + 1000 > DEFAULT_LAMBDA_TIMEOUT * 1000)
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
// // might run flaky (unreliable)
|
|
176
|
+
// test('executionTimeInMillis should return execution time', async () => {
|
|
177
|
+
// const functionDefinition = {
|
|
178
|
+
// handler: 'fixtures/lambdaFunction.fixture.executionTimeInMillisHandler',
|
|
179
|
+
// }
|
|
180
|
+
// const options = {}
|
|
181
|
+
// const lambdaFunction = new LambdaFunction(
|
|
182
|
+
// functionName,
|
|
183
|
+
// functionDefinition,
|
|
184
|
+
// provider,
|
|
185
|
+
// config,
|
|
186
|
+
// options,
|
|
187
|
+
// )
|
|
188
|
+
// const timerStart = performance.now()
|
|
189
|
+
// await lambdaFunction.runHandler()
|
|
190
|
+
// const timerEnd = performance.now()
|
|
191
|
+
//
|
|
192
|
+
// expect(lambdaFunction.executionTimeInMillis).toBeLessThanOrEqual(
|
|
193
|
+
// timerEnd - timerStart + 10,
|
|
194
|
+
// )
|
|
195
|
+
// })
|
|
196
|
+
})
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { dirname, resolve } from 'node:path'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import LambdaFunction from '../../../LambdaFunction.js'
|
|
4
|
+
|
|
5
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
6
|
+
|
|
7
|
+
export default class LambdaFunctionThatReturnsJSONObject {
|
|
8
|
+
#lambdaFunction
|
|
9
|
+
|
|
10
|
+
options = {}
|
|
11
|
+
|
|
12
|
+
serverless = {
|
|
13
|
+
config: {
|
|
14
|
+
serverlessPath: '',
|
|
15
|
+
servicePath: resolve(__dirname),
|
|
16
|
+
},
|
|
17
|
+
service: {
|
|
18
|
+
provider: {
|
|
19
|
+
runtime: 'nodejs12.x',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
listFunctionNames() {
|
|
25
|
+
return ['foo']
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getByFunctionName(functionName) {
|
|
29
|
+
const functionDefinition = {
|
|
30
|
+
handler:
|
|
31
|
+
'../../fixtures/lambdaFunction.fixture.asyncFunctionHandlerObject',
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
this.#lambdaFunction = new LambdaFunction(
|
|
35
|
+
functionName,
|
|
36
|
+
functionDefinition,
|
|
37
|
+
this.serverless,
|
|
38
|
+
this.options,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return this.#lambdaFunction
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async cleanup() {
|
|
45
|
+
await this.#lambdaFunction.cleanup()
|
|
46
|
+
}
|
|
47
|
+
}
|