serverless-offline 13.4.0 → 13.5.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 (33) hide show
  1. package/README.md +176 -96
  2. package/package.json +2 -2
  3. package/src/ServerlessOffline.js +3 -2
  4. package/src/events/alb/HttpServer.js +1 -1
  5. package/src/events/authFunctionNameExtractor.js +1 -1
  6. package/src/events/authValidateContext.js +1 -1
  7. package/src/events/http/Endpoint.js +1 -1
  8. package/src/events/http/HttpServer.js +11 -1
  9. package/src/events/http/authJWTSettingsExtractor.js +1 -1
  10. package/src/events/http/createAuthScheme.js +1 -1
  11. package/src/events/http/createJWTAuthScheme.js +1 -1
  12. package/src/events/http/lambda-events/LambdaIntegrationEvent.js +1 -1
  13. package/src/events/http/lambda-events/LambdaProxyIntegrationEvent.js +13 -2
  14. package/src/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +13 -2
  15. package/src/events/http/lambda-events/renderVelocityTemplateObject.js +1 -1
  16. package/src/events/schedule/Schedule.js +1 -1
  17. package/src/events/websocket/HttpServer.js +1 -1
  18. package/src/events/websocket/WebSocketClients.js +1 -1
  19. package/src/events/websocket/WebSocketServer.js +1 -1
  20. package/src/events/websocket/http-routes/_catchAll/catchAllRoute.js +1 -1
  21. package/src/events/websocket/http-routes/connections/connectionsRoutes.js +1 -1
  22. package/src/lambda/HttpServer.js +1 -1
  23. package/src/lambda/LambdaFunction.js +1 -1
  24. package/src/lambda/handler-runner/HandlerRunner.js +1 -1
  25. package/src/lambda/handler-runner/docker-runner/DockerContainer.js +1 -1
  26. package/src/lambda/handler-runner/docker-runner/DockerImage.js +1 -1
  27. package/src/lambda/handler-runner/go-runner/GoRunner.js +2 -2
  28. package/src/lambda/handler-runner/java-runner/JavaRunner.js +1 -1
  29. package/src/lambda/handler-runner/python-runner/PythonRunner.js +1 -1
  30. package/src/lambda/handler-runner/ruby-runner/RubyRunner.js +1 -1
  31. package/src/lambda/routes/invocations/InvocationsController.js +1 -1
  32. package/src/utils/getHttpApiCorsConfig.js +1 -1
  33. package/src/utils/log.js +20 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "dedicatedTo": "Blue, a great migrating bird.",
3
3
  "name": "serverless-offline",
4
- "version": "13.4.0",
4
+ "version": "13.5.1",
5
5
  "description": "Emulate AWS λ and API Gateway locally when developing your Serverless project",
6
6
  "license": "MIT",
7
7
  "exports": {
@@ -9,6 +9,7 @@
9
9
  "./lambda": "./src/lambda/index.js"
10
10
  },
11
11
  "type": "module",
12
+ "main": "src/index.js",
12
13
  "scripts": {
13
14
  "code-quality": "npm run prettier && npm run lint",
14
15
  "lint": "eslint .",
@@ -80,7 +81,6 @@
80
81
  "@hapi/boom": "^10.0.1",
81
82
  "@hapi/h2o2": "^10.0.4",
82
83
  "@hapi/hapi": "^21.3.3",
83
- "@serverless/utils": "^6.15.0",
84
84
  "array-unflat-js": "^0.1.3",
85
85
  "boxen": "^7.1.1",
86
86
  "chalk": "^5.3.0",
@@ -1,5 +1,5 @@
1
1
  import process, { exit } from "node:process"
2
- import { log } from "@serverless/utils/log.js"
2
+ import { log, setLogUtils } from "./utils/log.js"
3
3
  import {
4
4
  commandOptions,
5
5
  CUSTOM_OPTION,
@@ -54,9 +54,10 @@ export default class ServerlessOffline {
54
54
  "offline:start:ready": this.#ready.bind(this),
55
55
  }
56
56
 
57
- constructor(serverless, cliOptions) {
57
+ constructor(serverless, cliOptions, utils) {
58
58
  this.#cliOptions = cliOptions
59
59
  this.#serverless = serverless
60
+ setLogUtils(utils)
60
61
  }
61
62
 
62
63
  // Entry point for the plugin (sls offline) when running 'sls offline start'
@@ -1,7 +1,7 @@
1
1
  import { Buffer } from "node:buffer"
2
2
  import { exit } from "node:process"
3
3
  import { Server } from "@hapi/hapi"
4
- import { log } from "@serverless/utils/log.js"
4
+ import { log } from "../../utils/log.js"
5
5
  import {
6
6
  detectEncoding,
7
7
  generateAlbHapiPath,
@@ -1,4 +1,4 @@
1
- import { log } from "@serverless/utils/log.js"
1
+ import { log } from "../utils/log.js"
2
2
 
3
3
  function buildFailureResult(warningMessage) {
4
4
  log.warning(warningMessage)
@@ -1,5 +1,5 @@
1
1
  import Boom from "@hapi/boom"
2
- import { log } from "@serverless/utils/log.js"
2
+ import { log } from "../utils/log.js"
3
3
 
4
4
  const { entries, fromEntries, values } = Object
5
5
 
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync } from "node:fs"
2
- import { log } from "@serverless/utils/log.js"
3
2
  import { join } from "desm"
3
+ import { log } from "../../utils/log.js"
4
4
  import OfflineEndpoint from "./OfflineEndpoint.js"
5
5
 
6
6
  const { entries } = Object
@@ -5,7 +5,7 @@ import { join, resolve } from "node:path"
5
5
  import { exit } from "node:process"
6
6
  import h2o2 from "@hapi/h2o2"
7
7
  import { Server } from "@hapi/hapi"
8
- import { log } from "@serverless/utils/log.js"
8
+ import { log } from "../../utils/log.js"
9
9
  import authFunctionNameExtractor from "../authFunctionNameExtractor.js"
10
10
  import authJWTSettingsExtractor from "./authJWTSettingsExtractor.js"
11
11
  import createAuthScheme from "./createAuthScheme.js"
@@ -439,6 +439,7 @@ export default class HttpServer {
439
439
  // payload processing
440
440
  const encoding = detectEncoding(request)
441
441
 
442
+ request.raw.req.payload = request.payload
442
443
  request.payload = request.payload && request.payload.toString(encoding)
443
444
  request.rawPayload = request.payload
444
445
 
@@ -591,6 +592,15 @@ export default class HttpServer {
591
592
  )
592
593
 
593
594
  event = lambdaProxyIntegrationEvent.create()
595
+
596
+ const customizations = this.#serverless.service.custom
597
+ const hasCustomAuthProvider =
598
+ customizations?.offline?.customAuthenticationProvider
599
+
600
+ if (!endpoint.authorizer && !hasCustomAuthProvider) {
601
+ log.debug("no authorizer configured, deleting authorizer payload")
602
+ delete event.requestContext.authorizer
603
+ }
594
604
  }
595
605
 
596
606
  log.debug("event:", event)
@@ -1,4 +1,4 @@
1
- import { log } from "@serverless/utils/log.js"
1
+ import { log } from "../../utils/log.js"
2
2
 
3
3
  function buildFailureResult(warningMessage) {
4
4
  log.warning(warningMessage)
@@ -1,5 +1,5 @@
1
1
  import Boom from "@hapi/boom"
2
- import { log } from "@serverless/utils/log.js"
2
+ import { log } from "../../utils/log.js"
3
3
  import authCanExecuteResource from "../authCanExecuteResource.js"
4
4
  import authValidateContext from "../authValidateContext.js"
5
5
  import {
@@ -1,6 +1,6 @@
1
1
  import Boom from "@hapi/boom"
2
- import { log } from "@serverless/utils/log.js"
3
2
  import { decodeJwt } from "jose"
3
+ import { log } from "../../utils/log.js"
4
4
 
5
5
  const { isArray } = Array
6
6
  const { now } = Date
@@ -1,5 +1,5 @@
1
1
  import { env } from "node:process"
2
- import { log } from "@serverless/utils/log.js"
2
+ import { log } from "../../../utils/log.js"
3
3
  import renderVelocityTemplateObject from "./renderVelocityTemplateObject.js"
4
4
  import VelocityContext from "./VelocityContext.js"
5
5
 
@@ -1,9 +1,10 @@
1
1
  import { Buffer } from "node:buffer"
2
2
  import crypto from "node:crypto"
3
3
  import { env } from "node:process"
4
- import { log } from "@serverless/utils/log.js"
5
4
  import { decodeJwt } from "jose"
5
+ import { log } from "../../../utils/log.js"
6
6
  import {
7
+ detectEncoding,
7
8
  formatToClfTime,
8
9
  nullIfEmpty,
9
10
  parseHeaders,
@@ -63,6 +64,7 @@ export default class LambdaProxyIntegrationEvent {
63
64
  }
64
65
 
65
66
  let body = this.#request.payload
67
+ let isBase64Encoded = false
66
68
 
67
69
  const { rawHeaders, url } = this.#request.raw.req
68
70
 
@@ -80,6 +82,15 @@ export default class LambdaProxyIntegrationEvent {
80
82
  }
81
83
 
82
84
  if (body) {
85
+ if (
86
+ this.#request.raw.req.payload &&
87
+ detectEncoding(this.#request) === "binary"
88
+ ) {
89
+ body = Buffer.from(this.#request.raw.req.payload).toString("base64")
90
+ headers["Content-Length"] = String(Buffer.byteLength(body, "base64"))
91
+ isBase64Encoded = true
92
+ }
93
+
83
94
  if (typeof body !== "string") {
84
95
  // this.#request.payload is NOT the same as the rawPayload
85
96
  body = this.#request.rawPayload
@@ -155,7 +166,7 @@ export default class LambdaProxyIntegrationEvent {
155
166
  body,
156
167
  headers,
157
168
  httpMethod,
158
- isBase64Encoded: false, // TODO hook up
169
+ isBase64Encoded,
159
170
  multiValueHeaders: parseMultiValueHeaders(
160
171
  // NOTE FIXME request.raw.req.rawHeaders can only be null for testing (hapi shot inject())
161
172
  rawHeaders || [],
@@ -1,8 +1,9 @@
1
1
  import { Buffer } from "node:buffer"
2
2
  import { env } from "node:process"
3
- import { log } from "@serverless/utils/log.js"
4
3
  import { decodeJwt } from "jose"
4
+ import { log } from "../../../utils/log.js"
5
5
  import {
6
+ detectEncoding,
6
7
  formatToClfTime,
7
8
  lowerCaseKeys,
8
9
  nullIfEmpty,
@@ -55,6 +56,7 @@ export default class LambdaProxyIntegrationEventV2 {
55
56
  }
56
57
 
57
58
  let body = this.#request.payload
59
+ let isBase64Encoded = false
58
60
 
59
61
  const { rawHeaders } = this.#request.raw.req
60
62
 
@@ -72,6 +74,15 @@ export default class LambdaProxyIntegrationEventV2 {
72
74
  }
73
75
 
74
76
  if (body) {
77
+ if (
78
+ this.#request.raw.req.payload &&
79
+ detectEncoding(this.#request) === "binary"
80
+ ) {
81
+ body = Buffer.from(this.#request.raw.req.payload).toString("base64")
82
+ headers["content-length"] = String(Buffer.byteLength(body, "base64"))
83
+ isBase64Encoded = true
84
+ }
85
+
75
86
  if (typeof body !== "string") {
76
87
  // this.#request.payload is NOT the same as the rawPayload
77
88
  body = this.#request.rawPayload
@@ -145,7 +156,7 @@ export default class LambdaProxyIntegrationEventV2 {
145
156
  body,
146
157
  cookies,
147
158
  headers,
148
- isBase64Encoded: false,
159
+ isBase64Encoded,
149
160
  pathParameters: nullIfEmpty(pathParams),
150
161
  queryStringParameters: this.#request.url.search
151
162
  ? parseQueryStringParametersForPayloadV2(this.#request.url.searchParams)
@@ -1,5 +1,5 @@
1
- import { log } from "@serverless/utils/log.js"
2
1
  import velocityjs from "velocityjs"
2
+ import { log } from "../../../utils/log.js"
3
3
  import runInPollutedScope from "../javaHelpers.js"
4
4
  import { isPlainObject } from "../../../utils/index.js"
5
5
 
@@ -1,8 +1,8 @@
1
1
  // based on:
2
2
  // https://github.com/ajmath/serverless-offline-scheduler
3
3
 
4
- import { log } from "@serverless/utils/log.js"
5
4
  import nodeSchedule from "node-schedule"
5
+ import { log } from "../../utils/log.js"
6
6
  import ScheduleEvent from "./ScheduleEvent.js"
7
7
  import ScheduleEventDefinition from "./ScheduleEventDefinition.js"
8
8
 
@@ -2,7 +2,7 @@ import { readFile } from "node:fs/promises"
2
2
  import { resolve } from "node:path"
3
3
  import { exit } from "node:process"
4
4
  import { Server } from "@hapi/hapi"
5
- import { log } from "@serverless/utils/log.js"
5
+ import { log } from "../../utils/log.js"
6
6
  import { catchAllRoute, connectionsRoutes } from "./http-routes/index.js"
7
7
 
8
8
  export default class HttpServer {
@@ -1,6 +1,6 @@
1
1
  import { WebSocket } from "ws"
2
2
  import { isBoom } from "@hapi/boom"
3
- import { log } from "@serverless/utils/log.js"
3
+ import { log } from "../../utils/log.js"
4
4
  import {
5
5
  WebSocketAuthorizerEvent,
6
6
  WebSocketConnectEvent,
@@ -1,6 +1,6 @@
1
1
  import crypto from "node:crypto"
2
- import { log } from "@serverless/utils/log.js"
3
2
  import { WebSocketServer as WsWebSocketServer } from "ws"
3
+ import { log } from "../../utils/log.js"
4
4
 
5
5
  export default class WebSocketServer {
6
6
  #connectionIds = new Map()
@@ -1,4 +1,4 @@
1
- import { log } from "@serverless/utils/log.js"
1
+ import { log } from "../../../../utils/log.js"
2
2
 
3
3
  export default function catchAllRoute() {
4
4
  return {
@@ -1,5 +1,5 @@
1
- import { log } from "@serverless/utils/log.js"
2
1
  import ConnectionsController from "./ConnectionsController.js"
2
+ import { log } from "../../../../utils/log.js"
3
3
 
4
4
  export default function connectionsRoutes(webSocketClients) {
5
5
  const connectionsController = new ConnectionsController(webSocketClients)
@@ -1,6 +1,6 @@
1
1
  import { exit } from "node:process"
2
2
  import { Server } from "@hapi/hapi"
3
- import { log } from "@serverless/utils/log.js"
3
+ import { log } from "../utils/log.js"
4
4
  import { invocationsRoute, invokeAsyncRoute } from "./routes/index.js"
5
5
 
6
6
  export default class HttpServer {
@@ -4,9 +4,9 @@ import { dirname, join, resolve } from "node:path"
4
4
  import process from "node:process"
5
5
  import { performance } from "node:perf_hooks"
6
6
  import { setTimeout } from "node:timers/promises"
7
- import { log } from "@serverless/utils/log.js"
8
7
  import { emptyDir, ensureDir, remove } from "fs-extra"
9
8
  import jszip from "jszip"
9
+ import { log } from "../utils/log.js"
10
10
  import HandlerRunner from "./handler-runner/index.js"
11
11
  import LambdaContext from "./LambdaContext.js"
12
12
  import {
@@ -1,4 +1,4 @@
1
- import { log } from "@serverless/utils/log.js"
1
+ import { log } from "../../utils/log.js"
2
2
  import {
3
3
  supportedGo,
4
4
  supportedJava,
@@ -4,11 +4,11 @@ import { readFile, unlink, writeFile } from "node:fs/promises"
4
4
  import { platform } from "node:os"
5
5
  import { dirname, join, sep } from "node:path"
6
6
  import { LambdaClient, GetLayerVersionCommand } from "@aws-sdk/client-lambda"
7
- import { log, progress } from "@serverless/utils/log.js"
8
7
  import { execa } from "execa"
9
8
  import { ensureDir, pathExists } from "fs-extra"
10
9
  import isWsl from "is-wsl"
11
10
  import jszip from "jszip"
11
+ import { log, progress } from "../../../utils/log.js"
12
12
  import DockerImage from "./DockerImage.js"
13
13
  import Runtime from "./DockerRuntime.js"
14
14
 
@@ -1,8 +1,8 @@
1
- import { log } from "@serverless/utils/log.js"
2
1
  import { execa } from "execa"
3
2
  // TODO FIXME eslint plugin import bug, or not supporting package.json "expprts" field?
4
3
  // eslint-disable-next-line import/no-unresolved
5
4
  import promiseMemoize from "p-memoize"
5
+ import { log } from "../../../utils/log.js"
6
6
 
7
7
  export default class DockerImage {
8
8
  #imageNameTag = null
@@ -2,8 +2,8 @@ import { mkdir, readFile, rm, rmdir, writeFile } from "node:fs/promises"
2
2
  import { EOL } from "node:os"
3
3
  import process, { chdir, cwd } from "node:process"
4
4
  import { parse as pathParse, resolve, sep } from "node:path"
5
- import { log } from "@serverless/utils/log.js"
6
5
  import { execa } from "execa"
6
+ import { log } from "../../../utils/log.js"
7
7
  import { splitHandlerPathAndName } from "../../../utils/index.js"
8
8
 
9
9
  const { parse, stringify } = JSON
@@ -89,7 +89,7 @@ export default class GoRunner {
89
89
  }
90
90
 
91
91
  // Log to console in case engineers want to see the rest of the info
92
- log(logs.join(EOL))
92
+ log.debug(logs.join(EOL))
93
93
 
94
94
  return payload
95
95
  }
@@ -1,7 +1,7 @@
1
1
  import { EOL } from "node:os"
2
2
  import process from "node:process"
3
- import { log } from "@serverless/utils/log.js"
4
3
  import { invokeJavaLocal } from "java-invoke-local"
4
+ import { log } from "../../../utils/log.js"
5
5
 
6
6
  const { parse, stringify } = JSON
7
7
  const { hasOwn } = Object
@@ -3,8 +3,8 @@ import { EOL, platform } from "node:os"
3
3
  import { delimiter, join as pathJoin, relative } from "node:path"
4
4
  import process, { cwd, nextTick } from "node:process"
5
5
  import { createInterface } from "node:readline"
6
- import { log } from "@serverless/utils/log.js"
7
6
  import { join } from "desm"
7
+ import { log } from "../../../utils/log.js"
8
8
  import { splitHandlerPathAndName } from "../../../utils/index.js"
9
9
 
10
10
  const { parse, stringify } = JSON
@@ -1,9 +1,9 @@
1
1
  import { EOL, platform } from "node:os"
2
2
  import { relative } from "node:path"
3
3
  import { cwd } from "node:process"
4
- import { log } from "@serverless/utils/log.js"
5
4
  import { join } from "desm"
6
5
  import { execa } from "execa"
6
+ import { log } from "../../../utils/log.js"
7
7
  import { splitHandlerPathAndName } from "../../../utils/index.js"
8
8
 
9
9
  const { parse, stringify } = JSON
@@ -1,4 +1,4 @@
1
- import { log } from "@serverless/utils/log.js"
1
+ import { log } from "../../../utils/log.js"
2
2
 
3
3
  export default class InvocationsController {
4
4
  #lambda = null
@@ -1,4 +1,4 @@
1
- import { log } from "@serverless/utils/log.js"
1
+ import { log } from "./log.js"
2
2
 
3
3
  export default function getHttpApiCorsConfig(httpApiCors) {
4
4
  if (httpApiCors === true) {
@@ -0,0 +1,20 @@
1
+ let utils
2
+
3
+ export function setLogUtils({ log, progress }) {
4
+ utils = { log, progress }
5
+ }
6
+
7
+ export const log = {
8
+ debug: (...args) => utils?.log?.debug(...args),
9
+ error: (...args) => utils?.log?.error(...args),
10
+ info: (...args) => utils?.log?.info(...args),
11
+ notice: (...args) => utils?.log?.notice(...args),
12
+ verbose: (...args) => utils?.log?.verbose(...args),
13
+ warning: (...args) => utils?.log?.warning(...args),
14
+ }
15
+
16
+ export const progress = {
17
+ get: (namespace) => utils?.progress?.get(namespace),
18
+ notice: (message) => utils?.progress?.notice(message),
19
+ remove: () => utils?.progress?.remove(),
20
+ }