serverless-offline 8.8.1 → 9.1.1

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 +112 -44
  2. package/package.json +33 -57
  3. package/src/ServerlessOffline.js +409 -0
  4. package/src/config/commandOptions.js +159 -0
  5. package/src/config/constants.js +22 -0
  6. package/{dist → src}/config/defaultOptions.js +9 -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 +1242 -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 +309 -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 +76 -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 +419 -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 +172 -0
  78. package/src/lambda/handler-runner/go-runner/index.js +1 -0
  79. package/src/lambda/handler-runner/in-process-runner/InProcessRunner.js +126 -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/splitHandlerPathAndName.js +31 -0
  128. package/src/utils/unflatten.js +11 -0
  129. package/CHANGELOG.md +0 -78
  130. package/dist/ServerlessOffline.js +0 -508
  131. package/dist/config/commandOptions.js +0 -149
  132. package/dist/config/constants.js +0 -30
  133. package/dist/config/index.js +0 -55
  134. package/dist/config/supportedRuntimes.js +0 -40
  135. package/dist/debugLog.js +0 -12
  136. package/dist/events/authCanExecuteResource.js +0 -35
  137. package/dist/events/authFunctionNameExtractor.js +0 -87
  138. package/dist/events/authMatchPolicyResource.js +0 -62
  139. package/dist/events/authValidateContext.js +0 -53
  140. package/dist/events/http/Endpoint.js +0 -173
  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 -1370
  144. package/dist/events/http/OfflineEndpoint.js +0 -38
  145. package/dist/events/http/authJWTSettingsExtractor.js +0 -76
  146. package/dist/events/http/createAuthScheme.js +0 -184
  147. package/dist/events/http/createJWTAuthScheme.js +0 -159
  148. package/dist/events/http/index.js +0 -15
  149. package/dist/events/http/javaHelpers.js +0 -99
  150. package/dist/events/http/lambda-events/LambdaIntegrationEvent.js +0 -87
  151. package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +0 -246
  152. package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +0 -225
  153. package/dist/events/http/lambda-events/VelocityContext.js +0 -170
  154. package/dist/events/http/lambda-events/index.js +0 -39
  155. package/dist/events/http/lambda-events/renderVelocityTemplateObject.js +0 -111
  156. package/dist/events/http/payloadSchemaValidator.js +0 -13
  157. package/dist/events/schedule/Schedule.js +0 -183
  158. package/dist/events/schedule/ScheduleEvent.js +0 -27
  159. package/dist/events/schedule/ScheduleEventDefinition.js +0 -36
  160. package/dist/events/schedule/index.js +0 -15
  161. package/dist/events/websocket/HttpServer.js +0 -114
  162. package/dist/events/websocket/WebSocket.js +0 -78
  163. package/dist/events/websocket/WebSocketClients.js +0 -577
  164. package/dist/events/websocket/WebSocketEventDefinition.js +0 -32
  165. package/dist/events/websocket/WebSocketServer.js +0 -139
  166. package/dist/events/websocket/http-routes/_catchAll/catchAllRoute.js +0 -33
  167. package/dist/events/websocket/http-routes/_catchAll/index.js +0 -15
  168. package/dist/events/websocket/http-routes/connections/ConnectionsController.js +0 -45
  169. package/dist/events/websocket/http-routes/connections/connectionsRoutes.js +0 -95
  170. package/dist/events/websocket/http-routes/connections/index.js +0 -15
  171. package/dist/events/websocket/http-routes/index.js +0 -23
  172. package/dist/events/websocket/index.js +0 -15
  173. package/dist/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +0 -99
  174. package/dist/events/websocket/lambda-events/WebSocketConnectEvent.js +0 -101
  175. package/dist/events/websocket/lambda-events/WebSocketDisconnectEvent.js +0 -47
  176. package/dist/events/websocket/lambda-events/WebSocketEvent.js +0 -54
  177. package/dist/events/websocket/lambda-events/WebSocketRequestContext.js +0 -98
  178. package/dist/events/websocket/lambda-events/index.js +0 -39
  179. package/dist/index.js +0 -15
  180. package/dist/lambda/HttpServer.js +0 -124
  181. package/dist/lambda/Lambda.js +0 -117
  182. package/dist/lambda/LambdaContext.js +0 -53
  183. package/dist/lambda/LambdaFunction.js +0 -390
  184. package/dist/lambda/LambdaFunctionPool.js +0 -127
  185. package/dist/lambda/handler-runner/HandlerRunner.js +0 -195
  186. package/dist/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +0 -124
  187. package/dist/lambda/handler-runner/child-process-runner/childProcessHelper.js +0 -49
  188. package/dist/lambda/handler-runner/child-process-runner/index.js +0 -15
  189. package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +0 -515
  190. package/dist/lambda/handler-runner/docker-runner/DockerImage.js +0 -67
  191. package/dist/lambda/handler-runner/docker-runner/DockerRunner.js +0 -74
  192. package/dist/lambda/handler-runner/docker-runner/index.js +0 -15
  193. package/dist/lambda/handler-runner/go-runner/GoRunner.js +0 -230
  194. package/dist/lambda/handler-runner/go-runner/index.js +0 -15
  195. package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +0 -228
  196. package/dist/lambda/handler-runner/in-process-runner/index.js +0 -15
  197. package/dist/lambda/handler-runner/index.js +0 -15
  198. package/dist/lambda/handler-runner/java-runner/JavaRunner.js +0 -153
  199. package/dist/lambda/handler-runner/java-runner/index.js +0 -15
  200. package/dist/lambda/handler-runner/python-runner/PythonRunner.js +0 -185
  201. package/dist/lambda/handler-runner/python-runner/index.js +0 -15
  202. package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +0 -147
  203. package/dist/lambda/handler-runner/ruby-runner/index.js +0 -15
  204. package/dist/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +0 -92
  205. package/dist/lambda/handler-runner/worker-thread-runner/index.js +0 -15
  206. package/dist/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +0 -31
  207. package/dist/lambda/index.js +0 -15
  208. package/dist/lambda/routes/index.js +0 -23
  209. package/dist/lambda/routes/invocations/InvocationsController.js +0 -142
  210. package/dist/lambda/routes/invocations/index.js +0 -15
  211. package/dist/lambda/routes/invocations/invocationsRoute.js +0 -90
  212. package/dist/lambda/routes/invoke-async/InvokeAsyncController.js +0 -38
  213. package/dist/lambda/routes/invoke-async/index.js +0 -15
  214. package/dist/lambda/routes/invoke-async/invokeAsyncRoute.js +0 -43
  215. package/dist/main.js +0 -11
  216. package/dist/serverlessLog.js +0 -91
  217. package/dist/utils/checkDockerDaemon.js +0 -27
  218. package/dist/utils/checkGoVersion.js +0 -27
  219. package/dist/utils/createApiKey.js +0 -12
  220. package/dist/utils/createUniqueId.js +0 -14
  221. package/dist/utils/detectExecutable.js +0 -21
  222. package/dist/utils/generateHapiPath.js +0 -28
  223. package/dist/utils/getHttpApiCorsConfig.js +0 -40
  224. package/dist/utils/index.js +0 -165
  225. package/dist/utils/jsonPath.js +0 -21
  226. package/dist/utils/lowerCaseKeys.js +0 -14
  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 -36
  232. package/dist/utils/satisfiesVersionRange.js +0 -20
  233. package/dist/utils/splitHandlerPathAndName.js +0 -37
  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,76 @@
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
+ let message
45
+
46
+ try {
47
+ message = new Promise((res, rej) => {
48
+ childProcess.on('message', (data) => {
49
+ if (data.error) rej(data.error)
50
+ else res(data)
51
+ })
52
+ })
53
+ } finally {
54
+ childProcess.kill()
55
+ }
56
+
57
+ childProcess.send({
58
+ context,
59
+ event,
60
+ timeout: this.#timeout,
61
+ })
62
+
63
+ let result
64
+
65
+ try {
66
+ result = await message
67
+ } catch (err) {
68
+ // TODO
69
+ log.error(err)
70
+
71
+ throw err
72
+ }
73
+
74
+ return result
75
+ }
76
+ }
@@ -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'