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,35 @@
1
+ import authMatchPolicyResource from './authMatchPolicyResource.js'
2
+
3
+ const { isArray } = Array
4
+
5
+ function checkStatementsAgainstResource(Statement, resource, effect) {
6
+ return Statement.some((statement) => {
7
+ const resourceArray = isArray(statement.Resource)
8
+ ? statement.Resource
9
+ : [statement.Resource]
10
+
11
+ return (
12
+ statement.Effect.toLowerCase() === effect.toLowerCase() &&
13
+ resourceArray.some((policyResource) =>
14
+ authMatchPolicyResource(policyResource, resource),
15
+ )
16
+ )
17
+ })
18
+ }
19
+
20
+ export default function authCanExecuteResource(policy, resource) {
21
+ const { Statement } = policy
22
+
23
+ // check for explicit deny
24
+ const denyStatementFound = checkStatementsAgainstResource(
25
+ Statement,
26
+ resource,
27
+ 'Deny',
28
+ )
29
+
30
+ if (denyStatementFound) {
31
+ return false
32
+ }
33
+
34
+ return checkStatementsAgainstResource(Statement, resource, 'Allow')
35
+ }
@@ -0,0 +1,75 @@
1
+ import { log } from '@serverless/utils/log.js'
2
+
3
+ function buildFailureResult(warningMessage) {
4
+ log.warning(warningMessage)
5
+
6
+ return {
7
+ unsupportedAuth: true,
8
+ }
9
+ }
10
+
11
+ function buildSuccessResult(authorizerName) {
12
+ return {
13
+ authorizerName,
14
+ }
15
+ }
16
+
17
+ function handleStringAuthorizer(authorizerString) {
18
+ if (authorizerString.toUpperCase() === 'AWS_IAM') {
19
+ return buildFailureResult(
20
+ 'Serverless Offline does not support the AWS_IAM authorization type',
21
+ )
22
+ }
23
+
24
+ return buildSuccessResult(authorizerString)
25
+ }
26
+
27
+ function handleObjectAuthorizer(authorizerObject) {
28
+ const { arn, authorizerId, name, type } = authorizerObject
29
+
30
+ if (type && type.toUpperCase() === 'AWS_IAM') {
31
+ return buildFailureResult(
32
+ 'Serverless Offline does not support the AWS_IAM authorization type',
33
+ )
34
+ }
35
+
36
+ if (arn) {
37
+ return buildFailureResult(
38
+ `Serverless Offline does not support non local authorizers (arn): ${arn}`,
39
+ )
40
+ }
41
+
42
+ if (authorizerId) {
43
+ return buildFailureResult(
44
+ `Serverless Offline does not support non local authorizers (authorizerId): ${authorizerId}`,
45
+ )
46
+ }
47
+
48
+ if (!name) {
49
+ return buildFailureResult(
50
+ 'Serverless Offline supports local authorizers but authorizer name is missing',
51
+ )
52
+ }
53
+
54
+ return buildSuccessResult(name)
55
+ }
56
+
57
+ export default function authFunctionNameExtractor(endpoint) {
58
+ const { authorizer } = endpoint
59
+
60
+ if (!authorizer) {
61
+ return buildSuccessResult(null)
62
+ }
63
+
64
+ if (typeof authorizer === 'string') {
65
+ return handleStringAuthorizer(authorizer)
66
+ }
67
+
68
+ if (typeof authorizer === 'object') {
69
+ return handleObjectAuthorizer(authorizer)
70
+ }
71
+
72
+ return buildFailureResult(
73
+ 'Serverless Offline supports only local authorizers defined as string or object',
74
+ )
75
+ }
@@ -0,0 +1,71 @@
1
+ function parseResource(resource) {
2
+ const [, region, accountId, restApiId, path] = resource.match(
3
+ /arn:aws:execute-api:(.*?):(.*?):(.*?)\/(.*)/,
4
+ )
5
+
6
+ return {
7
+ accountId,
8
+ path,
9
+ region,
10
+ restApiId,
11
+ }
12
+ }
13
+
14
+ export default function authMatchPolicyResource(policyResource, resource) {
15
+ // resource and policyResource are ARNs
16
+ if (policyResource === resource) {
17
+ return true
18
+ }
19
+
20
+ if (policyResource === '*') {
21
+ return true
22
+ }
23
+
24
+ if (policyResource === 'arn:aws:execute-api:**') {
25
+ // better fix for #523
26
+ return true
27
+ }
28
+
29
+ if (policyResource === 'arn:aws:execute-api:*:*:*') {
30
+ return true
31
+ }
32
+
33
+ if (policyResource.includes('*') || policyResource.includes('?')) {
34
+ // Policy contains a wildcard resource
35
+
36
+ const parsedPolicyResource = parseResource(policyResource)
37
+ const parsedResource = parseResource(resource)
38
+
39
+ if (
40
+ parsedPolicyResource.region !== '*' &&
41
+ parsedPolicyResource.region !== parsedResource.region
42
+ ) {
43
+ return false
44
+ }
45
+
46
+ if (
47
+ parsedPolicyResource.accountId !== '*' &&
48
+ parsedPolicyResource.accountId !== parsedResource.accountId
49
+ ) {
50
+ return false
51
+ }
52
+
53
+ if (
54
+ parsedPolicyResource.restApiId !== '*' &&
55
+ parsedPolicyResource.restApiId !== parsedResource.restApiId
56
+ ) {
57
+ return false
58
+ }
59
+
60
+ // The path contains stage, method and the path
61
+ // for the requested resource and the resource defined in the policy
62
+ // Need to create a regex replacing ? with one character and * with any number of characters
63
+ const regExp = new RegExp(
64
+ parsedPolicyResource.path.replace(/\*/g, '.*').replace(/\?/g, '.'),
65
+ )
66
+
67
+ return regExp.test(parsedResource.path)
68
+ }
69
+
70
+ return false
71
+ }
@@ -0,0 +1,51 @@
1
+ import Boom from '@hapi/boom'
2
+ import { log } from '@serverless/utils/log.js'
3
+
4
+ const { entries, fromEntries, values } = Object
5
+
6
+ function internalServerError(message) {
7
+ const errorType = 'AuthorizerConfigurationException'
8
+
9
+ const error = Boom.internal()
10
+
11
+ error.output.headers['x-amzn-ErrorType'] = errorType
12
+ error.output.payload.error = errorType
13
+ error.output.payload.message = message
14
+
15
+ return error
16
+ }
17
+
18
+ function isValidContext(context) {
19
+ return values(context).every(
20
+ (value) =>
21
+ typeof value === 'boolean' ||
22
+ typeof value === 'number' ||
23
+ typeof value === 'string',
24
+ )
25
+ }
26
+
27
+ function transform(context) {
28
+ return fromEntries(
29
+ entries(context).map(([key, value]) => [key, String(value)]),
30
+ )
31
+ }
32
+
33
+ export default function authValidateContext(context, authFunName) {
34
+ if (typeof context !== 'object') {
35
+ return internalServerError('Authorizer response context must be an object')
36
+ }
37
+
38
+ if (!isValidContext(context)) {
39
+ const error =
40
+ 'Authorizer response context values must be of type string, number, or boolean'
41
+
42
+ log.notice(
43
+ `Detected invalid value types returned in authorizer context: (λ: ${authFunName}). ${error}. ` +
44
+ 'More info: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html',
45
+ )
46
+
47
+ return internalServerError(error)
48
+ }
49
+
50
+ return transform(context)
51
+ }
@@ -0,0 +1,135 @@
1
+ import { existsSync, readFileSync } from 'node:fs'
2
+ import { dirname, resolve } from 'node:path'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { log } from '@serverless/utils/log.js'
5
+ import OfflineEndpoint from './OfflineEndpoint.js'
6
+
7
+ const { entries } = Object
8
+
9
+ const __dirname = dirname(fileURLToPath(import.meta.url))
10
+
11
+ // velocity template defaults
12
+ const defaultRequestTemplate = readFileSync(
13
+ resolve(__dirname, './templates/offline-default.req.vm'),
14
+ 'utf8',
15
+ )
16
+ const defaultResponseTemplate = readFileSync(
17
+ resolve(__dirname, './templates/offline-default.res.vm'),
18
+ 'utf8',
19
+ )
20
+
21
+ function getResponseContentType(fep) {
22
+ if (fep.response && fep.response.headers['Content-Type']) {
23
+ return fep.response.headers['Content-Type'].replace(/'/gm, '')
24
+ }
25
+
26
+ return 'application/json'
27
+ }
28
+
29
+ export default class Endpoint {
30
+ #handlerPath = null
31
+
32
+ #http = null
33
+
34
+ constructor(handlerPath, http) {
35
+ this.#handlerPath = handlerPath
36
+ this.#http = http
37
+ }
38
+
39
+ // determine whether we have function level overrides for velocity templates
40
+ // if not we will use defaults
41
+ #setVmTemplates(fullEndpoint) {
42
+ // determine requestTemplate
43
+ // first check if requestTemplate is set through serverless
44
+ const fep = fullEndpoint
45
+
46
+ try {
47
+ // determine request template override
48
+ const reqFilename = `${this.#handlerPath}.req.vm`
49
+
50
+ // check if serverless framework populates the object itself
51
+ if (
52
+ typeof this.#http.request === 'object' &&
53
+ typeof this.#http.request.template === 'object'
54
+ ) {
55
+ const templatesConfig = this.#http.request.template
56
+
57
+ entries(templatesConfig).forEach(([key, value]) => {
58
+ fep.requestTemplates[key] = value
59
+ })
60
+ }
61
+ // load request template if exists if not use default from serverless offline
62
+ else if (existsSync(reqFilename)) {
63
+ fep.requestTemplates['application/json'] = readFileSync(
64
+ reqFilename,
65
+ 'utf8',
66
+ )
67
+ } else {
68
+ fep.requestTemplates['application/json'] = defaultRequestTemplate
69
+ }
70
+
71
+ // determine response template
72
+ const resFilename = `${this.#handlerPath}.res.vm`
73
+
74
+ fep.responseContentType = getResponseContentType(fep)
75
+ log.debug('Response Content-Type ', fep.responseContentType)
76
+
77
+ // load response template from http response template, or load file if exists other use default
78
+ if (fep.response && fep.response.template) {
79
+ fep.responses.default.responseTemplates[fep.responseContentType] =
80
+ fep.response.template
81
+ } else if (existsSync(resFilename)) {
82
+ fep.responses.default.responseTemplates[fep.responseContentType] =
83
+ readFileSync(resFilename, 'utf8')
84
+ } else {
85
+ fep.responses.default.responseTemplates[fep.responseContentType] =
86
+ defaultResponseTemplate
87
+ }
88
+ } catch (err) {
89
+ log.debug(`Error: ${err}`)
90
+ }
91
+
92
+ return fep
93
+ }
94
+
95
+ // loosely based on:
96
+ // https://github.com/serverless/serverless/blob/v1.59.2/lib/plugins/aws/package/compile/events/apiGateway/lib/validate.js#L380
97
+ #getIntegration(http) {
98
+ const { integration, async: isAsync } = http
99
+ if (integration) {
100
+ const normalizedIntegration = integration.toUpperCase().replace('-', '_')
101
+ if (normalizedIntegration === 'LAMBDA') {
102
+ return 'AWS'
103
+ }
104
+ if (normalizedIntegration === 'LAMBDA_PROXY') {
105
+ return 'AWS_PROXY'
106
+ }
107
+ return normalizedIntegration
108
+ }
109
+
110
+ if (isAsync) {
111
+ return 'AWS'
112
+ }
113
+
114
+ return 'AWS_PROXY'
115
+ }
116
+
117
+ // return fully generated Endpoint
118
+ generate() {
119
+ const offlineEndpoint = new OfflineEndpoint()
120
+
121
+ const fullEndpoint = {
122
+ ...offlineEndpoint,
123
+ ...this.#http,
124
+ }
125
+
126
+ fullEndpoint.integration = this.#getIntegration(this.#http)
127
+
128
+ if (fullEndpoint.integration === 'AWS') {
129
+ // determine request and response templates or use defaults
130
+ return this.#setVmTemplates(fullEndpoint)
131
+ }
132
+
133
+ return fullEndpoint
134
+ }
135
+ }
@@ -0,0 +1,50 @@
1
+ import HttpEventDefinition from './HttpEventDefinition.js'
2
+ import HttpServer from './HttpServer.js'
3
+
4
+ export default class Http {
5
+ #httpServer = null
6
+
7
+ constructor(serverless, options, lambda) {
8
+ this.#httpServer = new HttpServer(serverless, options, lambda)
9
+ }
10
+
11
+ start() {
12
+ return this.#httpServer.start()
13
+ }
14
+
15
+ // stops the server
16
+ stop(timeout) {
17
+ return this.#httpServer.stop(timeout)
18
+ }
19
+
20
+ #createEvent(functionKey, rawHttpEventDefinition, handler) {
21
+ const httpEvent = new HttpEventDefinition(rawHttpEventDefinition)
22
+
23
+ this.#httpServer.createRoutes(functionKey, httpEvent, handler)
24
+ }
25
+
26
+ create(events) {
27
+ events.forEach(({ functionKey, handler, http }) => {
28
+ this.#createEvent(functionKey, http, handler)
29
+ })
30
+
31
+ this.#httpServer.writeRoutesTerminal()
32
+ }
33
+
34
+ createResourceRoutes() {
35
+ this.#httpServer.createResourceRoutes()
36
+ }
37
+
38
+ create404Route() {
39
+ this.#httpServer.create404Route()
40
+ }
41
+
42
+ registerPlugins() {
43
+ return this.#httpServer.registerPlugins()
44
+ }
45
+
46
+ // TEMP FIXME quick fix to expose gateway server for testing, look for better solution
47
+ getServer() {
48
+ return this.#httpServer.getServer()
49
+ }
50
+ }
@@ -0,0 +1,20 @@
1
+ const { assign } = Object
2
+
3
+ export default class HttpEventDefinition {
4
+ constructor(rawHttpEventDefinition) {
5
+ let method
6
+ let path
7
+ let rest
8
+
9
+ if (typeof rawHttpEventDefinition === 'string') {
10
+ ;[method, path] = rawHttpEventDefinition.split(' ')
11
+ } else {
12
+ ;({ method, path, ...rest } = rawHttpEventDefinition)
13
+ }
14
+
15
+ this.method = method
16
+ this.path = path
17
+
18
+ assign(this, rest)
19
+ }
20
+ }