serverless-offline 8.8.0 → 9.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/README.md +12 -11
  2. package/package.json +33 -58
  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 +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 +167 -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/splitHandlerPathAndName.js +31 -0
  128. package/src/utils/unflatten.js +11 -0
  129. package/dist/ServerlessOffline.js +0 -514
  130. package/dist/config/commandOptions.js +0 -149
  131. package/dist/config/constants.js +0 -30
  132. package/dist/config/index.js +0 -55
  133. package/dist/config/supportedRuntimes.js +0 -40
  134. package/dist/debugLog.js +0 -12
  135. package/dist/events/authCanExecuteResource.js +0 -35
  136. package/dist/events/authFunctionNameExtractor.js +0 -87
  137. package/dist/events/authMatchPolicyResource.js +0 -62
  138. package/dist/events/authValidateContext.js +0 -53
  139. package/dist/events/http/Endpoint.js +0 -173
  140. package/dist/events/http/Http.js +0 -77
  141. package/dist/events/http/HttpEventDefinition.js +0 -36
  142. package/dist/events/http/HttpServer.js +0 -1370
  143. package/dist/events/http/OfflineEndpoint.js +0 -38
  144. package/dist/events/http/authJWTSettingsExtractor.js +0 -76
  145. package/dist/events/http/createAuthScheme.js +0 -184
  146. package/dist/events/http/createJWTAuthScheme.js +0 -159
  147. package/dist/events/http/index.js +0 -15
  148. package/dist/events/http/javaHelpers.js +0 -99
  149. package/dist/events/http/lambda-events/LambdaIntegrationEvent.js +0 -87
  150. package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +0 -246
  151. package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +0 -225
  152. package/dist/events/http/lambda-events/VelocityContext.js +0 -170
  153. package/dist/events/http/lambda-events/index.js +0 -39
  154. package/dist/events/http/lambda-events/renderVelocityTemplateObject.js +0 -111
  155. package/dist/events/http/payloadSchemaValidator.js +0 -13
  156. package/dist/events/schedule/Schedule.js +0 -183
  157. package/dist/events/schedule/ScheduleEvent.js +0 -27
  158. package/dist/events/schedule/ScheduleEventDefinition.js +0 -36
  159. package/dist/events/schedule/index.js +0 -15
  160. package/dist/events/websocket/HttpServer.js +0 -114
  161. package/dist/events/websocket/WebSocket.js +0 -78
  162. package/dist/events/websocket/WebSocketClients.js +0 -577
  163. package/dist/events/websocket/WebSocketEventDefinition.js +0 -32
  164. package/dist/events/websocket/WebSocketServer.js +0 -139
  165. package/dist/events/websocket/http-routes/_catchAll/catchAllRoute.js +0 -33
  166. package/dist/events/websocket/http-routes/_catchAll/index.js +0 -15
  167. package/dist/events/websocket/http-routes/connections/ConnectionsController.js +0 -45
  168. package/dist/events/websocket/http-routes/connections/connectionsRoutes.js +0 -95
  169. package/dist/events/websocket/http-routes/connections/index.js +0 -15
  170. package/dist/events/websocket/http-routes/index.js +0 -23
  171. package/dist/events/websocket/index.js +0 -15
  172. package/dist/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +0 -99
  173. package/dist/events/websocket/lambda-events/WebSocketConnectEvent.js +0 -101
  174. package/dist/events/websocket/lambda-events/WebSocketDisconnectEvent.js +0 -47
  175. package/dist/events/websocket/lambda-events/WebSocketEvent.js +0 -54
  176. package/dist/events/websocket/lambda-events/WebSocketRequestContext.js +0 -98
  177. package/dist/events/websocket/lambda-events/index.js +0 -39
  178. package/dist/index.js +0 -15
  179. package/dist/lambda/HttpServer.js +0 -124
  180. package/dist/lambda/Lambda.js +0 -117
  181. package/dist/lambda/LambdaContext.js +0 -53
  182. package/dist/lambda/LambdaFunction.js +0 -390
  183. package/dist/lambda/LambdaFunctionPool.js +0 -127
  184. package/dist/lambda/handler-runner/HandlerRunner.js +0 -195
  185. package/dist/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +0 -124
  186. package/dist/lambda/handler-runner/child-process-runner/childProcessHelper.js +0 -49
  187. package/dist/lambda/handler-runner/child-process-runner/index.js +0 -15
  188. package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +0 -515
  189. package/dist/lambda/handler-runner/docker-runner/DockerImage.js +0 -67
  190. package/dist/lambda/handler-runner/docker-runner/DockerRunner.js +0 -74
  191. package/dist/lambda/handler-runner/docker-runner/index.js +0 -15
  192. package/dist/lambda/handler-runner/go-runner/GoRunner.js +0 -230
  193. package/dist/lambda/handler-runner/go-runner/index.js +0 -15
  194. package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +0 -228
  195. package/dist/lambda/handler-runner/in-process-runner/index.js +0 -15
  196. package/dist/lambda/handler-runner/index.js +0 -15
  197. package/dist/lambda/handler-runner/java-runner/JavaRunner.js +0 -153
  198. package/dist/lambda/handler-runner/java-runner/index.js +0 -15
  199. package/dist/lambda/handler-runner/python-runner/PythonRunner.js +0 -185
  200. package/dist/lambda/handler-runner/python-runner/index.js +0 -15
  201. package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +0 -147
  202. package/dist/lambda/handler-runner/ruby-runner/index.js +0 -15
  203. package/dist/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +0 -92
  204. package/dist/lambda/handler-runner/worker-thread-runner/index.js +0 -15
  205. package/dist/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +0 -31
  206. package/dist/lambda/index.js +0 -15
  207. package/dist/lambda/routes/index.js +0 -23
  208. package/dist/lambda/routes/invocations/InvocationsController.js +0 -142
  209. package/dist/lambda/routes/invocations/index.js +0 -15
  210. package/dist/lambda/routes/invocations/invocationsRoute.js +0 -90
  211. package/dist/lambda/routes/invoke-async/InvokeAsyncController.js +0 -38
  212. package/dist/lambda/routes/invoke-async/index.js +0 -15
  213. package/dist/lambda/routes/invoke-async/invokeAsyncRoute.js +0 -43
  214. package/dist/main.js +0 -11
  215. package/dist/serverlessLog.js +0 -91
  216. package/dist/utils/checkDockerDaemon.js +0 -27
  217. package/dist/utils/checkGoVersion.js +0 -27
  218. package/dist/utils/createApiKey.js +0 -12
  219. package/dist/utils/createUniqueId.js +0 -14
  220. package/dist/utils/detectExecutable.js +0 -21
  221. package/dist/utils/generateHapiPath.js +0 -28
  222. package/dist/utils/getHttpApiCorsConfig.js +0 -40
  223. package/dist/utils/index.js +0 -165
  224. package/dist/utils/jsonPath.js +0 -21
  225. package/dist/utils/lowerCaseKeys.js +0 -14
  226. package/dist/utils/parseHeaders.js +0 -23
  227. package/dist/utils/parseMultiValueHeaders.js +0 -36
  228. package/dist/utils/parseMultiValueQueryStringParameters.js +0 -40
  229. package/dist/utils/parseQueryStringParameters.js +0 -26
  230. package/dist/utils/resolveJoins.js +0 -36
  231. package/dist/utils/satisfiesVersionRange.js +0 -20
  232. package/dist/utils/splitHandlerPathAndName.js +0 -37
  233. 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'