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.
Files changed (235) hide show
  1. package/README.md +3 -3
  2. package/package.json +33 -57
  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/CHANGELOG.md +0 -78
  131. package/dist/ServerlessOffline.js +0 -508
  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 -12
  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/authValidateContext.js +0 -53
  141. package/dist/events/http/Endpoint.js +0 -173
  142. package/dist/events/http/Http.js +0 -77
  143. package/dist/events/http/HttpEventDefinition.js +0 -36
  144. package/dist/events/http/HttpServer.js +0 -1370
  145. package/dist/events/http/OfflineEndpoint.js +0 -38
  146. package/dist/events/http/authJWTSettingsExtractor.js +0 -76
  147. package/dist/events/http/createAuthScheme.js +0 -184
  148. package/dist/events/http/createJWTAuthScheme.js +0 -159
  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 -87
  152. package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +0 -246
  153. package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +0 -225
  154. package/dist/events/http/lambda-events/VelocityContext.js +0 -170
  155. package/dist/events/http/lambda-events/index.js +0 -39
  156. package/dist/events/http/lambda-events/renderVelocityTemplateObject.js +0 -111
  157. package/dist/events/http/payloadSchemaValidator.js +0 -13
  158. package/dist/events/schedule/Schedule.js +0 -183
  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 -114
  163. package/dist/events/websocket/WebSocket.js +0 -78
  164. package/dist/events/websocket/WebSocketClients.js +0 -577
  165. package/dist/events/websocket/WebSocketEventDefinition.js +0 -32
  166. package/dist/events/websocket/WebSocketServer.js +0 -139
  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 -15
  181. package/dist/lambda/HttpServer.js +0 -124
  182. package/dist/lambda/Lambda.js +0 -117
  183. package/dist/lambda/LambdaContext.js +0 -53
  184. package/dist/lambda/LambdaFunction.js +0 -390
  185. package/dist/lambda/LambdaFunctionPool.js +0 -127
  186. package/dist/lambda/handler-runner/HandlerRunner.js +0 -195
  187. package/dist/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +0 -124
  188. package/dist/lambda/handler-runner/child-process-runner/childProcessHelper.js +0 -49
  189. package/dist/lambda/handler-runner/child-process-runner/index.js +0 -15
  190. package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +0 -515
  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 -230
  195. package/dist/lambda/handler-runner/go-runner/index.js +0 -15
  196. package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +0 -228
  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 -153
  200. package/dist/lambda/handler-runner/java-runner/index.js +0 -15
  201. package/dist/lambda/handler-runner/python-runner/PythonRunner.js +0 -185
  202. package/dist/lambda/handler-runner/python-runner/index.js +0 -15
  203. package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +0 -147
  204. package/dist/lambda/handler-runner/ruby-runner/index.js +0 -15
  205. package/dist/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +0 -92
  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 -31
  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 -40
  225. package/dist/utils/index.js +0 -165
  226. package/dist/utils/jsonPath.js +0 -21
  227. package/dist/utils/lowerCaseKeys.js +0 -14
  228. package/dist/utils/parseHeaders.js +0 -23
  229. package/dist/utils/parseMultiValueHeaders.js +0 -36
  230. package/dist/utils/parseMultiValueQueryStringParameters.js +0 -40
  231. package/dist/utils/parseQueryStringParameters.js +0 -26
  232. package/dist/utils/resolveJoins.js +0 -36
  233. package/dist/utils/satisfiesVersionRange.js +0 -20
  234. package/dist/utils/splitHandlerPathAndName.js +0 -37
  235. 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'