serverless-offline 8.7.0 → 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.
Files changed (234) hide show
  1. package/README.md +91 -95
  2. package/package.json +41 -69
  3. package/src/ServerlessOffline.js +412 -0
  4. package/src/config/commandOptions.js +155 -0
  5. package/src/config/constants.js +22 -0
  6. package/{dist → src}/config/defaultOptions.js +8 -17
  7. package/src/config/index.js +4 -0
  8. package/src/config/supportedRuntimes.js +47 -0
  9. package/src/events/authCanExecuteResource.js +35 -0
  10. package/src/events/authFunctionNameExtractor.js +75 -0
  11. package/src/events/authMatchPolicyResource.js +71 -0
  12. package/src/events/authValidateContext.js +51 -0
  13. package/src/events/http/Endpoint.js +135 -0
  14. package/src/events/http/Http.js +50 -0
  15. package/src/events/http/HttpEventDefinition.js +20 -0
  16. package/src/events/http/HttpServer.js +1277 -0
  17. package/src/events/http/OfflineEndpoint.js +33 -0
  18. package/src/events/http/authJWTSettingsExtractor.js +70 -0
  19. package/src/events/http/createAuthScheme.js +176 -0
  20. package/src/events/http/createJWTAuthScheme.js +106 -0
  21. package/src/events/http/index.js +1 -0
  22. package/src/events/http/javaHelpers.js +102 -0
  23. package/src/events/http/lambda-events/LambdaIntegrationEvent.js +57 -0
  24. package/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js +233 -0
  25. package/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +190 -0
  26. package/src/events/http/lambda-events/VelocityContext.js +147 -0
  27. package/src/events/http/lambda-events/index.js +4 -0
  28. package/src/events/http/lambda-events/renderVelocityTemplateObject.js +93 -0
  29. package/{dist → src}/events/http/parseResources.js +73 -78
  30. package/src/events/http/payloadSchemaValidator.js +13 -0
  31. package/{dist → src}/events/http/templates/offline-default.req.vm +0 -0
  32. package/{dist → src}/events/http/templates/offline-default.res.vm +0 -0
  33. package/src/events/schedule/Schedule.js +131 -0
  34. package/src/events/schedule/ScheduleEvent.js +18 -0
  35. package/src/events/schedule/ScheduleEventDefinition.js +21 -0
  36. package/src/events/schedule/index.js +1 -0
  37. package/src/events/websocket/HttpServer.js +69 -0
  38. package/src/events/websocket/WebSocket.js +52 -0
  39. package/src/events/websocket/WebSocketClients.js +462 -0
  40. package/src/events/websocket/WebSocketEventDefinition.js +18 -0
  41. package/src/events/websocket/WebSocketServer.js +73 -0
  42. package/src/events/websocket/http-routes/_catchAll/catchAllRoute.js +16 -0
  43. package/src/events/websocket/http-routes/_catchAll/index.js +1 -0
  44. package/src/events/websocket/http-routes/connections/ConnectionsController.js +28 -0
  45. package/src/events/websocket/http-routes/connections/connectionsRoutes.js +70 -0
  46. package/src/events/websocket/http-routes/connections/index.js +1 -0
  47. package/src/events/websocket/http-routes/index.js +2 -0
  48. package/src/events/websocket/index.js +1 -0
  49. package/src/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +65 -0
  50. package/src/events/websocket/lambda-events/WebSocketConnectEvent.js +68 -0
  51. package/src/events/websocket/lambda-events/WebSocketDisconnectEvent.js +31 -0
  52. package/src/events/websocket/lambda-events/WebSocketEvent.js +29 -0
  53. package/src/events/websocket/lambda-events/WebSocketRequestContext.js +67 -0
  54. package/src/events/websocket/lambda-events/index.js +4 -0
  55. package/src/index.js +12 -0
  56. package/src/lambda/HttpServer.js +108 -0
  57. package/src/lambda/Lambda.js +68 -0
  58. package/src/lambda/LambdaContext.js +33 -0
  59. package/src/lambda/LambdaFunction.js +308 -0
  60. package/src/lambda/LambdaFunctionPool.js +109 -0
  61. package/src/lambda/__tests__/LambdaContext.test.js +30 -0
  62. package/src/lambda/__tests__/LambdaFunction.test.js +196 -0
  63. package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsJSONObject.fixture.js +47 -0
  64. package/src/lambda/__tests__/fixtures/Lambda/LambdaFunctionThatReturnsNativeString.fixture.js +46 -0
  65. package/src/lambda/__tests__/fixtures/Lambda/package.json +3 -0
  66. package/src/lambda/__tests__/fixtures/lambdaFunction.fixture.js +145 -0
  67. package/src/lambda/__tests__/fixtures/package.json +3 -0
  68. package/src/lambda/__tests__/routes/invocations/InvocationsController.test.js +42 -0
  69. package/src/lambda/handler-runner/HandlerRunner.js +136 -0
  70. package/src/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +72 -0
  71. package/src/lambda/handler-runner/child-process-runner/childProcessHelper.js +42 -0
  72. package/src/lambda/handler-runner/child-process-runner/index.js +1 -0
  73. package/src/lambda/handler-runner/docker-runner/DockerContainer.js +417 -0
  74. package/src/lambda/handler-runner/docker-runner/DockerImage.js +35 -0
  75. package/src/lambda/handler-runner/docker-runner/DockerRunner.js +63 -0
  76. package/src/lambda/handler-runner/docker-runner/index.js +1 -0
  77. package/src/lambda/handler-runner/go-runner/GoRunner.js +166 -0
  78. package/src/lambda/handler-runner/go-runner/index.js +1 -0
  79. package/src/lambda/handler-runner/in-process-runner/InProcessRunner.js +125 -0
  80. package/src/lambda/handler-runner/in-process-runner/index.js +1 -0
  81. package/src/lambda/handler-runner/index.js +1 -0
  82. package/src/lambda/handler-runner/java-runner/JavaRunner.js +114 -0
  83. package/src/lambda/handler-runner/java-runner/index.js +1 -0
  84. package/src/lambda/handler-runner/python-runner/PythonRunner.js +138 -0
  85. package/src/lambda/handler-runner/python-runner/index.js +1 -0
  86. package/{dist → src}/lambda/handler-runner/python-runner/invoke.py +0 -0
  87. package/src/lambda/handler-runner/ruby-runner/RubyRunner.js +107 -0
  88. package/src/lambda/handler-runner/ruby-runner/index.js +1 -0
  89. package/{dist → src}/lambda/handler-runner/ruby-runner/invoke.rb +0 -0
  90. package/src/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +70 -0
  91. package/src/lambda/handler-runner/worker-thread-runner/index.js +1 -0
  92. package/src/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +29 -0
  93. package/src/lambda/index.js +1 -0
  94. package/src/lambda/routes/index.js +2 -0
  95. package/src/lambda/routes/invocations/InvocationsController.js +102 -0
  96. package/src/lambda/routes/invocations/index.js +1 -0
  97. package/src/lambda/routes/invocations/invocationsRoute.js +77 -0
  98. package/src/lambda/routes/invoke-async/InvokeAsyncController.js +20 -0
  99. package/src/lambda/routes/invoke-async/index.js +1 -0
  100. package/src/lambda/routes/invoke-async/invokeAsyncRoute.js +33 -0
  101. package/src/utils/__tests__/createUniqueId.test.js +18 -0
  102. package/src/utils/__tests__/formatToClfTime.test.js +14 -0
  103. package/src/utils/__tests__/generateHapiPath.test.js +46 -0
  104. package/src/utils/__tests__/lowerCaseKeys.test.js +30 -0
  105. package/src/utils/__tests__/parseHeaders.test.js +13 -0
  106. package/src/utils/__tests__/parseMultiValueHeaders.test.js +24 -0
  107. package/src/utils/__tests__/parseMultiValueQueryStringParameters.test.js +159 -0
  108. package/src/utils/__tests__/parseQueryStringParameters.test.js +15 -0
  109. package/src/utils/__tests__/splitHandlerPathAndName.test.js +54 -0
  110. package/src/utils/__tests__/unflatten.test.js +32 -0
  111. package/src/utils/checkDockerDaemon.js +19 -0
  112. package/src/utils/checkGoVersion.js +16 -0
  113. package/src/utils/createApiKey.js +5 -0
  114. package/src/utils/createUniqueId.js +5 -0
  115. package/src/utils/detectExecutable.js +11 -0
  116. package/{dist → src}/utils/formatToClfTime.js +6 -14
  117. package/src/utils/generateHapiPath.js +26 -0
  118. package/src/utils/getHttpApiCorsConfig.js +28 -0
  119. package/src/utils/index.js +42 -0
  120. package/src/utils/jsonPath.js +13 -0
  121. package/src/utils/logRoutes.js +64 -0
  122. package/src/utils/lowerCaseKeys.js +6 -0
  123. package/src/utils/parseHeaders.js +14 -0
  124. package/src/utils/parseMultiValueHeaders.js +27 -0
  125. package/src/utils/parseMultiValueQueryStringParameters.js +31 -0
  126. package/src/utils/parseQueryStringParameters.js +15 -0
  127. package/src/utils/resolveJoins.js +29 -0
  128. package/src/utils/splitHandlerPathAndName.js +31 -0
  129. package/src/utils/unflatten.js +11 -0
  130. package/dist/ServerlessOffline.js +0 -507
  131. package/dist/checkEngine.js +0 -21
  132. package/dist/config/commandOptions.js +0 -149
  133. package/dist/config/constants.js +0 -30
  134. package/dist/config/index.js +0 -55
  135. package/dist/config/supportedRuntimes.js +0 -40
  136. package/dist/debugLog.js +0 -10
  137. package/dist/events/authCanExecuteResource.js +0 -35
  138. package/dist/events/authFunctionNameExtractor.js +0 -87
  139. package/dist/events/authMatchPolicyResource.js +0 -62
  140. package/dist/events/http/Endpoint.js +0 -171
  141. package/dist/events/http/Http.js +0 -77
  142. package/dist/events/http/HttpEventDefinition.js +0 -36
  143. package/dist/events/http/HttpServer.js +0 -1363
  144. package/dist/events/http/OfflineEndpoint.js +0 -40
  145. package/dist/events/http/authJWTSettingsExtractor.js +0 -76
  146. package/dist/events/http/authValidateContext.js +0 -48
  147. package/dist/events/http/createAuthScheme.js +0 -184
  148. package/dist/events/http/createJWTAuthScheme.js +0 -155
  149. package/dist/events/http/index.js +0 -15
  150. package/dist/events/http/javaHelpers.js +0 -99
  151. package/dist/events/http/lambda-events/LambdaIntegrationEvent.js +0 -85
  152. package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +0 -244
  153. package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +0 -221
  154. package/dist/events/http/lambda-events/VelocityContext.js +0 -168
  155. package/dist/events/http/lambda-events/index.js +0 -39
  156. package/dist/events/http/lambda-events/renderVelocityTemplateObject.js +0 -108
  157. package/dist/events/http/payloadSchemaValidator.js +0 -13
  158. package/dist/events/schedule/Schedule.js +0 -182
  159. package/dist/events/schedule/ScheduleEvent.js +0 -27
  160. package/dist/events/schedule/ScheduleEventDefinition.js +0 -36
  161. package/dist/events/schedule/index.js +0 -15
  162. package/dist/events/websocket/HttpServer.js +0 -112
  163. package/dist/events/websocket/WebSocket.js +0 -78
  164. package/dist/events/websocket/WebSocketClients.js +0 -550
  165. package/dist/events/websocket/WebSocketEventDefinition.js +0 -32
  166. package/dist/events/websocket/WebSocketServer.js +0 -140
  167. package/dist/events/websocket/http-routes/_catchAll/catchAllRoute.js +0 -33
  168. package/dist/events/websocket/http-routes/_catchAll/index.js +0 -15
  169. package/dist/events/websocket/http-routes/connections/ConnectionsController.js +0 -45
  170. package/dist/events/websocket/http-routes/connections/connectionsRoutes.js +0 -95
  171. package/dist/events/websocket/http-routes/connections/index.js +0 -15
  172. package/dist/events/websocket/http-routes/index.js +0 -23
  173. package/dist/events/websocket/index.js +0 -15
  174. package/dist/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +0 -99
  175. package/dist/events/websocket/lambda-events/WebSocketConnectEvent.js +0 -101
  176. package/dist/events/websocket/lambda-events/WebSocketDisconnectEvent.js +0 -47
  177. package/dist/events/websocket/lambda-events/WebSocketEvent.js +0 -54
  178. package/dist/events/websocket/lambda-events/WebSocketRequestContext.js +0 -98
  179. package/dist/events/websocket/lambda-events/index.js +0 -39
  180. package/dist/index.js +0 -19
  181. package/dist/lambda/HttpServer.js +0 -122
  182. package/dist/lambda/Lambda.js +0 -113
  183. package/dist/lambda/LambdaContext.js +0 -53
  184. package/dist/lambda/LambdaFunction.js +0 -391
  185. package/dist/lambda/LambdaFunctionPool.js +0 -127
  186. package/dist/lambda/handler-runner/HandlerRunner.js +0 -223
  187. package/dist/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +0 -132
  188. package/dist/lambda/handler-runner/child-process-runner/childProcessHelper.js +0 -40
  189. package/dist/lambda/handler-runner/child-process-runner/index.js +0 -15
  190. package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +0 -517
  191. package/dist/lambda/handler-runner/docker-runner/DockerImage.js +0 -67
  192. package/dist/lambda/handler-runner/docker-runner/DockerRunner.js +0 -74
  193. package/dist/lambda/handler-runner/docker-runner/index.js +0 -15
  194. package/dist/lambda/handler-runner/go-runner/GoRunner.js +0 -211
  195. package/dist/lambda/handler-runner/go-runner/index.js +0 -15
  196. package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +0 -234
  197. package/dist/lambda/handler-runner/in-process-runner/index.js +0 -15
  198. package/dist/lambda/handler-runner/index.js +0 -15
  199. package/dist/lambda/handler-runner/java-runner/JavaRunner.js +0 -151
  200. package/dist/lambda/handler-runner/java-runner/index.js +0 -15
  201. package/dist/lambda/handler-runner/python-runner/PythonRunner.js +0 -180
  202. package/dist/lambda/handler-runner/python-runner/index.js +0 -15
  203. package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +0 -148
  204. package/dist/lambda/handler-runner/ruby-runner/index.js +0 -15
  205. package/dist/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +0 -94
  206. package/dist/lambda/handler-runner/worker-thread-runner/index.js +0 -15
  207. package/dist/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +0 -30
  208. package/dist/lambda/index.js +0 -15
  209. package/dist/lambda/routes/index.js +0 -23
  210. package/dist/lambda/routes/invocations/InvocationsController.js +0 -142
  211. package/dist/lambda/routes/invocations/index.js +0 -15
  212. package/dist/lambda/routes/invocations/invocationsRoute.js +0 -90
  213. package/dist/lambda/routes/invoke-async/InvokeAsyncController.js +0 -38
  214. package/dist/lambda/routes/invoke-async/index.js +0 -15
  215. package/dist/lambda/routes/invoke-async/invokeAsyncRoute.js +0 -43
  216. package/dist/main.js +0 -11
  217. package/dist/serverlessLog.js +0 -91
  218. package/dist/utils/checkDockerDaemon.js +0 -27
  219. package/dist/utils/checkGoVersion.js +0 -27
  220. package/dist/utils/createApiKey.js +0 -12
  221. package/dist/utils/createUniqueId.js +0 -14
  222. package/dist/utils/detectExecutable.js +0 -21
  223. package/dist/utils/generateHapiPath.js +0 -28
  224. package/dist/utils/getHttpApiCorsConfig.js +0 -44
  225. package/dist/utils/index.js +0 -158
  226. package/dist/utils/jsonPath.js +0 -21
  227. package/dist/utils/parseHeaders.js +0 -23
  228. package/dist/utils/parseMultiValueHeaders.js +0 -36
  229. package/dist/utils/parseMultiValueQueryStringParameters.js +0 -40
  230. package/dist/utils/parseQueryStringParameters.js +0 -26
  231. package/dist/utils/resolveJoins.js +0 -34
  232. package/dist/utils/satisfiesVersionRange.js +0 -20
  233. package/dist/utils/splitHandlerPathAndName.js +0 -41
  234. package/dist/utils/unflatten.js +0 -18
@@ -0,0 +1,46 @@
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 LambdaFunctionThatReturnsNativeString {
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: '../../fixtures/lambdaFunction.fixture.asyncFunctionHandler',
31
+ }
32
+
33
+ this.#lambdaFunction = new LambdaFunction(
34
+ functionName,
35
+ functionDefinition,
36
+ this.serverless,
37
+ this.options,
38
+ )
39
+
40
+ return this.#lambdaFunction
41
+ }
42
+
43
+ async cleanup() {
44
+ await this.#lambdaFunction.cleanup()
45
+ }
46
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "module"
3
+ }
@@ -0,0 +1,145 @@
1
+ 'use strict'
2
+
3
+ exports.contextDoneHandler = function contextDoneHandler(event, context) {
4
+ context.done(null, 'foo')
5
+ }
6
+
7
+ exports.contextDoneHandlerDeferred = function contextDoneHandlerDeferred(
8
+ event,
9
+ context,
10
+ ) {
11
+ setTimeout(() => context.done(null, 'foo'), 100)
12
+ }
13
+
14
+ exports.contextSucceedHandler = function contextSucceedHandler(event, context) {
15
+ context.succeed('foo')
16
+ }
17
+
18
+ exports.contextSucceedHandlerDeferred = function contextSucceedHandlerDeferred(
19
+ event,
20
+ context,
21
+ ) {
22
+ setTimeout(() => context.succeed('foo'), 100)
23
+ }
24
+
25
+ exports.callbackHandler = function callbackHandler(event, context, callback) {
26
+ callback(null, 'foo')
27
+ }
28
+
29
+ exports.callbackHandlerDeferred = function callbackHandlerDeferred(
30
+ event,
31
+ context,
32
+ callback,
33
+ ) {
34
+ setTimeout(() => callback(null, 'foo'), 100)
35
+ }
36
+
37
+ exports.promiseHandler = function promiseHandler() {
38
+ return Promise.resolve('foo')
39
+ }
40
+
41
+ exports.promiseHandlerDeferred = function promiseDeferred() {
42
+ return new Promise((resolve) => {
43
+ setTimeout(() => resolve('foo'), 100)
44
+ })
45
+ }
46
+
47
+ exports.asyncFunctionHandler = async function asyncFunctionHandler() {
48
+ return 'foo'
49
+ }
50
+
51
+ exports.asyncFunctionHandlerObject = async function asyncFunctionHandler() {
52
+ return {
53
+ foo: 'bar',
54
+ }
55
+ }
56
+
57
+ // we deliberately test the case where a 'callback' is defined
58
+ // in the handler, but a promise is being returned to protect from a
59
+ // potential naive implementation, e.g.
60
+ //
61
+ // const { promisify } = 'utils'
62
+ // const promisifiedHandler = handler.length === 3 ? promisify(handler) : handler
63
+ //
64
+ // if someone would return a promise, but also defines callback, without using it
65
+ // the handler would not be returning anything
66
+ exports.promiseWithDefinedCallbackHandler =
67
+ function promiseWithDefinedCallbackHandler(
68
+ event, // eslint-disable-line no-unused-vars
69
+ context, // eslint-disable-line no-unused-vars
70
+ callback, // eslint-disable-line no-unused-vars
71
+ ) {
72
+ return Promise.resolve('Hello Promise!')
73
+ }
74
+
75
+ exports.contextSucceedWithContextDoneHandler =
76
+ function contextSucceedWithContextDoneHandler(event, context) {
77
+ context.succeed('Hello Context.succeed!')
78
+
79
+ context.done(null, 'Hello Context.done!')
80
+ }
81
+
82
+ exports.callbackWithContextDoneHandler =
83
+ function callbackWithContextDoneHandler(event, context, callback) {
84
+ callback(null, 'Hello Callback!')
85
+
86
+ context.done(null, 'Hello Context.done!')
87
+ }
88
+
89
+ exports.callbackWithPromiseHandler = function callbackWithPromiseHandler(
90
+ event,
91
+ context,
92
+ callback,
93
+ ) {
94
+ callback(null, 'Hello Callback!')
95
+
96
+ return Promise.resolve('Hello Promise!')
97
+ }
98
+
99
+ exports.callbackInsidePromiseHandler = function callbackInsidePromiseHandler(
100
+ event,
101
+ context,
102
+ callback,
103
+ ) {
104
+ return new Promise((resolve) => {
105
+ callback(null, 'Hello Callback!')
106
+
107
+ resolve('Hello Promise!')
108
+ })
109
+ }
110
+
111
+ exports.requestIdHandler = async function requestIdHandler(event, context) {
112
+ return context.awsRequestId
113
+ }
114
+
115
+ exports.remainingExecutionTimeHandler =
116
+ async function remainingExecutionTimeHandler(event, context) {
117
+ const first = context.getRemainingTimeInMillis()
118
+
119
+ await new Promise((resolve) => {
120
+ setTimeout(resolve, 100)
121
+ })
122
+
123
+ const second = context.getRemainingTimeInMillis()
124
+
125
+ await new Promise((resolve) => {
126
+ setTimeout(resolve, 200)
127
+ })
128
+
129
+ const third = context.getRemainingTimeInMillis()
130
+
131
+ return [first, second, third]
132
+ }
133
+
134
+ exports.defaultTimeoutHandler = async function defaultTimeoutHandler(
135
+ event,
136
+ context,
137
+ ) {
138
+ return context.getRemainingTimeInMillis()
139
+ }
140
+
141
+ exports.executionTimeInMillisHandler = function executionTimeInMillisHandler() {
142
+ return new Promise((resolve) => {
143
+ setTimeout(resolve, 100)
144
+ })
145
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,42 @@
1
+ import assert from 'node:assert'
2
+ import InvocationsController from '../../../routes/invocations/InvocationsController.js'
3
+ import LambdaFunctionThatReturnsJSONObject from '../../fixtures/Lambda/LambdaFunctionThatReturnsJSONObject.fixture.js'
4
+ import LambdaFunctionThatReturnsNativeString from '../../fixtures/Lambda/LambdaFunctionThatReturnsNativeString.fixture.js'
5
+
6
+ describe('InvocationController', () => {
7
+ const functionName = 'foo'
8
+
9
+ describe('when event type is "RequestResponse"', () => {
10
+ const eventType = 'RequestResponse'
11
+
12
+ it('should return json object if lambda response is json', async () => {
13
+ const expected = {
14
+ Payload: {
15
+ foo: 'bar',
16
+ },
17
+ StatusCode: 200,
18
+ }
19
+
20
+ const lambdaFunction = new LambdaFunctionThatReturnsJSONObject()
21
+ const invocationController = new InvocationsController(lambdaFunction)
22
+ const result = await invocationController.invoke(functionName, eventType)
23
+ await lambdaFunction.cleanup()
24
+
25
+ assert.deepEqual(result, expected)
26
+ })
27
+
28
+ it('should wrap native string responses with ""', async () => {
29
+ const expected = {
30
+ Payload: '"foo"',
31
+ StatusCode: 200,
32
+ }
33
+
34
+ const lambdaFunction = new LambdaFunctionThatReturnsNativeString()
35
+ const invocationController = new InvocationsController(lambdaFunction)
36
+ const result = await invocationController.invoke(functionName, eventType)
37
+ await lambdaFunction.cleanup()
38
+
39
+ assert.deepEqual(result, expected)
40
+ })
41
+ })
42
+ })
@@ -0,0 +1,136 @@
1
+ import { log } from '@serverless/utils/log.js'
2
+ import {
3
+ supportedGo,
4
+ supportedJava,
5
+ supportedNodejs,
6
+ supportedPython,
7
+ supportedRuby,
8
+ } from '../../config/index.js'
9
+
10
+ export default class HandlerRunner {
11
+ #env = null
12
+
13
+ #funOptions = null
14
+
15
+ #options = null
16
+
17
+ #runner = null
18
+
19
+ constructor(funOptions, options, env) {
20
+ this.#env = env
21
+ this.#funOptions = funOptions
22
+ this.#options = options
23
+ }
24
+
25
+ async #loadRunner() {
26
+ const { useChildProcesses, useDocker, useInProcess } = this.#options
27
+
28
+ const { functionKey, handlerName, handlerPath, runtime, timeout } =
29
+ this.#funOptions
30
+
31
+ log.debug(`Loading handler... (${handlerPath})`)
32
+
33
+ if (useDocker) {
34
+ // https://github.com/lambci/docker-lambda/issues/329
35
+ if (runtime === 'nodejs14.x') {
36
+ log.warning(
37
+ '"nodejs14.x" runtime is not supported with docker. See https://github.com/lambci/docker-lambda/issues/329',
38
+ )
39
+ throw new Error('Unsupported runtime')
40
+ }
41
+
42
+ if (runtime === 'python3.9') {
43
+ log.warning('"python3.9" runtime is not supported with docker.')
44
+ throw new Error('Unsupported runtime')
45
+ }
46
+
47
+ const dockerOptions = {
48
+ host: this.#options.dockerHost,
49
+ hostServicePath: this.#options.dockerHostServicePath,
50
+ layersDir: this.#options.layersDir,
51
+ network: this.#options.dockerNetwork,
52
+ readOnly: this.#options.dockerReadOnly,
53
+ }
54
+
55
+ const { default: DockerRunner } = await import('./docker-runner/index.js')
56
+
57
+ return new DockerRunner(this.#funOptions, this.#env, dockerOptions)
58
+ }
59
+
60
+ if (supportedNodejs.has(runtime)) {
61
+ if (useChildProcesses) {
62
+ const { default: ChildProcessRunner } = await import(
63
+ './child-process-runner/index.js'
64
+ )
65
+
66
+ return new ChildProcessRunner(this.#funOptions, this.#env)
67
+ }
68
+
69
+ if (useInProcess) {
70
+ const { default: InProcessRunner } = await import(
71
+ './in-process-runner/index.js'
72
+ )
73
+
74
+ return new InProcessRunner(
75
+ functionKey,
76
+ handlerPath,
77
+ handlerName,
78
+ this.#env,
79
+ timeout,
80
+ )
81
+ }
82
+
83
+ const { default: WorkerThreadRunner } = await import(
84
+ './worker-thread-runner/index.js'
85
+ )
86
+
87
+ return new WorkerThreadRunner(this.#funOptions, this.#env)
88
+ }
89
+
90
+ if (supportedGo.has(runtime)) {
91
+ const { default: GoRunner } = await import('./go-runner/index.js')
92
+
93
+ return new GoRunner(this.#funOptions, this.#env)
94
+ }
95
+
96
+ if (supportedPython.has(runtime)) {
97
+ const { default: PythonRunner } = await import('./python-runner/index.js')
98
+
99
+ return new PythonRunner(this.#funOptions, this.#env)
100
+ }
101
+
102
+ if (supportedRuby.has(runtime)) {
103
+ const { default: RubyRunner } = await import('./ruby-runner/index.js')
104
+
105
+ return new RubyRunner(this.#funOptions, this.#env)
106
+ }
107
+
108
+ if (supportedJava.has(runtime)) {
109
+ const { default: JavaRunner } = await import('./java-runner/index.js')
110
+
111
+ return new JavaRunner(this.#funOptions, this.#env)
112
+ }
113
+
114
+ // TODO FIXME
115
+ throw new Error('Unsupported runtime')
116
+ }
117
+
118
+ // TEMP TODO FIXME
119
+ isDockerRunner() {
120
+ return this.#runner && this.#runner.constructor.name === 'DockerRunner'
121
+ }
122
+
123
+ // () => Promise<void>
124
+ cleanup() {
125
+ // TODO console.log('handler runner cleanup')
126
+ return this.#runner.cleanup()
127
+ }
128
+
129
+ async run(event, context) {
130
+ if (this.#runner == null) {
131
+ this.#runner = await this.#loadRunner()
132
+ }
133
+
134
+ return this.#runner.run(event, context)
135
+ }
136
+ }
@@ -0,0 +1,72 @@
1
+ import { dirname, resolve } from 'node:path'
2
+ import { fileURLToPath } from 'node:url'
3
+ import { log } from '@serverless/utils/log.js'
4
+ import { execaNode } from 'execa'
5
+
6
+ const __dirname = dirname(fileURLToPath(import.meta.url))
7
+ const childProcessHelperPath = resolve(__dirname, 'childProcessHelper.js')
8
+
9
+ export default class ChildProcessRunner {
10
+ #env = null
11
+
12
+ #functionKey = null
13
+
14
+ #handlerName = null
15
+
16
+ #handlerPath = null
17
+
18
+ #timeout = null
19
+
20
+ constructor(funOptions, env) {
21
+ const { functionKey, handlerName, handlerPath, timeout } = funOptions
22
+
23
+ this.#env = env
24
+ this.#functionKey = functionKey
25
+ this.#handlerName = handlerName
26
+ this.#handlerPath = handlerPath
27
+ this.#timeout = timeout
28
+ }
29
+
30
+ // no-op
31
+ // () => void
32
+ cleanup() {}
33
+
34
+ async run(event, context) {
35
+ const childProcess = execaNode(
36
+ childProcessHelperPath,
37
+ [this.#functionKey, this.#handlerName, this.#handlerPath],
38
+ {
39
+ env: this.#env,
40
+ stdio: 'inherit',
41
+ },
42
+ )
43
+
44
+ const message = new Promise((res, rej) => {
45
+ childProcess.on('message', (data) => {
46
+ if (data.error) rej(data.error)
47
+ else res(data)
48
+ })
49
+ }).finally(() => {
50
+ childProcess.kill()
51
+ })
52
+
53
+ childProcess.send({
54
+ context,
55
+ event,
56
+ timeout: this.#timeout,
57
+ })
58
+
59
+ let result
60
+
61
+ try {
62
+ result = await message
63
+ } catch (err) {
64
+ // TODO
65
+ log.error(err)
66
+
67
+ throw err
68
+ }
69
+
70
+ return result
71
+ }
72
+ }
@@ -0,0 +1,42 @@
1
+ import process, { argv } from 'node:process'
2
+ import InProcessRunner from '../in-process-runner/index.js'
3
+
4
+ // TODO handle this:
5
+ process.on('uncaughtException', (err) => {
6
+ const {
7
+ constructor: { name },
8
+ message,
9
+ stack,
10
+ } = err
11
+
12
+ process.send({
13
+ // process.send() can't serialize an Error object, so we help it out a bit
14
+ error: {
15
+ constructor: {
16
+ name,
17
+ },
18
+ message,
19
+ stack,
20
+ },
21
+ })
22
+ })
23
+
24
+ const [, , functionKey, handlerName, handlerPath] = argv
25
+
26
+ process.on('message', async (messageData) => {
27
+ const { context, event, timeout } = messageData
28
+
29
+ // TODO we could probably cache this in the module scope?
30
+ const inProcessRunner = new InProcessRunner(
31
+ functionKey,
32
+ handlerPath,
33
+ handlerName,
34
+ process.env,
35
+ timeout,
36
+ )
37
+
38
+ const result = await inProcessRunner.run(event, context)
39
+
40
+ // TODO check serializeability (contains function, symbol etc)
41
+ process.send(result)
42
+ })
@@ -0,0 +1 @@
1
+ export { default } from './ChildProcessRunner.js'