serverless-offline 14.4.0 → 14.5.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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2016-2024 David Hérault
3
+ Copyright (c) 2016-2025 David Hérault
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,22 +1,32 @@
1
1
  # Serverless Offline
2
2
 
3
3
  <div align="center">
4
- <p>
5
- <sup>
6
- <a href="https://github.com/sponsors/dherault">Serverless-offline is supported by the community.</a>
7
- </sup>
8
- </p>
4
+ We are looking for maintainers!
5
+ <br />
6
+ Please contact <a href="https://github.com/dherault">dherault</a> if you feel you are a good match.
7
+ </div>
8
+ <br />
9
+ <div align="center">
10
+ <sup>
11
+ Serverless-offline is supported by the community.
12
+ </sup>
13
+ <br />
9
14
  <sup>
10
15
  Special thanks to:
11
16
  </sup>
12
- <a href="https://airfriend.app?ref=so">
17
+ <br />
18
+ <a href="https://symmetrics.app?ref=so">
13
19
  <div>
14
- <img src="https://airfriend.app/images/logotype.png" height="64" alt="Airfriend">
20
+ <img src="https://symmetrics.app/images/logo/logotype.png" height="64" alt="Symmetrics">
15
21
  </div>
16
22
  <b>
17
- An AI friend on WhatsApp.
23
+ Become a data-driven product builder
18
24
  </b>
25
+ <div>
26
+ Metrics, community and resources for lead developers and engineering managers.
27
+ </div>
19
28
  </a>
29
+ <br />
20
30
  <a href="https://arccode.dev?ref=so">
21
31
  <div>
22
32
  <img src="https://arccode.dev/images/logotype.png" height="64" alt="Arccode">
@@ -31,9 +41,6 @@
31
41
  </div>
32
42
  &nbsp;
33
43
  <p>
34
- <a href="https://www.serverless.com">
35
- <img src="http://public.serverless.com/badges/v3.svg">
36
- </a>
37
44
  <a href="https://www.npmjs.com/package/serverless-offline">
38
45
  <img src="https://img.shields.io/npm/v/serverless-offline.svg?style=flat-square">
39
46
  </a>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "serverless-offline",
3
- "version": "14.4.0",
3
+ "version": "14.5.0",
4
4
  "description": "Emulate AWS λ and API Gateway locally when developing your Serverless project",
5
5
  "license": "MIT",
6
6
  "exports": {
@@ -49,7 +49,7 @@
49
49
  ],
50
50
  "author": "David Hérault <dherault@gmail.com> (https://github.com/dherault)",
51
51
  "engines": {
52
- "node": ">=18.12.0"
52
+ "node": ">=20.0.0"
53
53
  },
54
54
  "commit-and-tag-version": {
55
55
  "skip": {
@@ -4,7 +4,7 @@ export const BASE_URL_PLACEHOLDER = "http://example"
4
4
 
5
5
  export const CUSTOM_OPTION = "serverless-offline"
6
6
 
7
- export const DEFAULT_LAMBDA_RUNTIME = "nodejs14.x"
7
+ export const DEFAULT_LAMBDA_RUNTIME = "nodejs20.x"
8
8
 
9
9
  export const DEFAULT_LAMBDA_ARCHITECTURE = "arm64"
10
10
 
@@ -11,19 +11,19 @@ const X86_64 = "x86_64"
11
11
  const ARM64 = "arm64"
12
12
 
13
13
  export const supportedRuntimesArchitecture = {
14
- "nodejs14.x": [ARM64, X86_64],
15
- "nodejs16.x": [ARM64, X86_64],
16
- "nodejs18.x": [ARM64, X86_64],
17
14
  "nodejs20.x": [ARM64, X86_64],
18
15
  "nodejs22.x": [ARM64, X86_64],
16
+ "nodejs24.x": [ARM64, X86_64],
19
17
  "python3.7": [X86_64],
20
18
  "python3.8": [ARM64, X86_64],
21
19
  "python3.9": [ARM64, X86_64],
22
20
  "python3.10": [ARM64, X86_64],
23
21
  "python3.11": [ARM64, X86_64],
24
22
  "python3.12": [ARM64, X86_64],
23
+ "python3.13": [ARM64, X86_64],
25
24
  "ruby2.7": [ARM64, X86_64],
26
25
  "ruby3.2": [ARM64, X86_64],
26
+ "ruby3.3": [ARM64, X86_64],
27
27
  java8: [X86_64],
28
28
  "java8.al2": [ARM64, X86_64],
29
29
  java11: [ARM64, X86_64],
@@ -44,11 +44,9 @@ export const supportedJava = new Set(["java8", "java8.al2", "java11", "java17"])
44
44
 
45
45
  // NODE.JS
46
46
  export const supportedNodejs = new Set([
47
- "nodejs14.x",
48
- "nodejs16.x",
49
- "nodejs18.x",
50
47
  "nodejs20.x",
51
48
  "nodejs22.x",
49
+ "nodejs24.x",
52
50
  ])
53
51
 
54
52
  // PROVIDED
@@ -66,10 +64,11 @@ export const supportedPython = new Set([
66
64
  "python3.10",
67
65
  "python3.11",
68
66
  "python3.12",
67
+ "python3.13",
69
68
  ])
70
69
 
71
70
  // RUBY
72
- export const supportedRuby = new Set(["ruby2.7", "ruby3.2"])
71
+ export const supportedRuby = new Set(["ruby2.7", "ruby3.2", "ruby3.3"])
73
72
 
74
73
  export const supportedRuntimes = new Set([
75
74
  // ...supportedDotnetcore,
@@ -7,6 +7,7 @@ import { setTimeout } from "node:timers/promises"
7
7
  import { emptyDir, ensureDir, remove } from "fs-extra"
8
8
  import jszip from "jszip"
9
9
  import { log } from "../utils/log.js"
10
+ import renderIntrinsicFunction from "../utils/renderIntrinsicFunction.js"
10
11
  import HandlerRunner from "./handler-runner/index.js"
11
12
  import LambdaContext from "./LambdaContext.js"
12
13
  import {
@@ -114,8 +115,8 @@ export default class LambdaFunction {
114
115
  entries(process.env).filter(([key]) => key.startsWith("AWS_")),
115
116
  )),
116
117
  ...this.#getAwsEnvVars(),
117
- ...provider.environment,
118
- ...functionDefinition.environment,
118
+ ...renderIntrinsicFunction(provider.environment),
119
+ ...renderIntrinsicFunction(functionDefinition.environment),
119
120
  IS_OFFLINE: "true",
120
121
  }
121
122
 
@@ -20,6 +20,7 @@ const fs = require("node:fs")
20
20
  const process = require("node:process")
21
21
 
22
22
  const { require: tsxRequire } = require(`tsx/cjs/api`)
23
+ const { tsImport } = require(`tsx/esm/api`)
23
24
  const {
24
25
  HandlerNotFound,
25
26
  MalformedHandlerName,
@@ -136,10 +137,9 @@ function _hasFolderPackageJsonTypeModule(folder) {
136
137
  }
137
138
 
138
139
  function _hasPackageJsonTypeModule(file) {
139
- // File must have a .js extension
140
- const jsPath = `${file}.js`
141
- return fs.existsSync(jsPath)
142
- ? _hasFolderPackageJsonTypeModule(path.resolve(path.dirname(jsPath)))
140
+ const dir = path.dirname(file)
141
+ return fs.existsSync(dir)
142
+ ? _hasFolderPackageJsonTypeModule(path.resolve(dir))
143
143
  : false
144
144
  }
145
145
 
@@ -175,13 +175,15 @@ async function _tryRequire(appRoot, moduleRoot, module) {
175
175
  }
176
176
 
177
177
  // If still not loaded, try .js, .mjs, .cjs and .ts in that order.
178
- // Files ending with .js are loaded as ES modules when the nearest parent package.json
178
+ // Files ending with .js and .ts are loaded as ES modules when the nearest parent package.json
179
179
  // file contains a top-level field "type" with a value of "module".
180
180
  // https://nodejs.org/api/packages.html#packages_type
181
181
  const loaded =
182
182
  (pjHasModule && (await _tryAwaitImport(lambdaStylePath, ".js"))) ||
183
183
  (await _tryAwaitImport(lambdaStylePath, ".mjs")) ||
184
184
  _tryRequireFile(lambdaStylePath, ".cjs") ||
185
+ (pjHasModule &&
186
+ (await tsImport(`${lambdaStylePath}.ts`, `${lambdaStylePath}.ts`))) ||
185
187
  tsxRequire(`${lambdaStylePath}.ts`, `${lambdaStylePath}.ts`)
186
188
  if (loaded) {
187
189
  return loaded
@@ -0,0 +1,34 @@
1
+ export default function renderIntrinsicFunction(input) {
2
+ if (input === null || input === undefined) {
3
+ return input
4
+ }
5
+
6
+ if (typeof input === "string") {
7
+ return input
8
+ }
9
+
10
+ if (Array.isArray(input)) {
11
+ return input.map(renderIntrinsicFunction)
12
+ }
13
+
14
+ if (typeof input === "object") {
15
+ const result = {}
16
+ for (const [key, value] of Object.entries(input)) {
17
+ if (key === "Fn::Join" || key === "!Join") {
18
+ const [delimiter, list] = value
19
+ return list.map(renderIntrinsicFunction).join(delimiter)
20
+ }
21
+ if (key === "Fn::Sub" || key === "!Sub") {
22
+ const [template, variables] = value
23
+ result[key] = template.replaceAll(/\${(.*?)}/g, (match, variable) => {
24
+ return variable in variables ? variables[variable] : match
25
+ })
26
+ return result[key]
27
+ }
28
+ result[key] = renderIntrinsicFunction(value)
29
+ }
30
+ return result
31
+ }
32
+
33
+ return input
34
+ }