@skuba-lib/api 2.2.0-add-cdk-NodejsFunction-20260613135656 → 2.2.0-hoist-changesets-20260614023310

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/lib/cdk/index.cjs CHANGED
@@ -1,6 +1,13 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- //#region src/cdk/normaliseTemplate/index.ts
2
+ //#region src/cdk/index.ts
3
+ var cdk_exports = /* @__PURE__ */ require("../chunk-DakpK96I.cjs").__exportAll({ normaliseTemplate: () => normaliseTemplate });
3
4
  const normaliseTemplateJsonString = (json) => json.replace(/"S3Key":"([0-9a-f]+)\.zip"/g, (_, hash) => `"S3Key":"${"x".repeat(hash.length)}.zip"`).replace(/workerCurrentVersion([0-9a-zA-Z]+)"/g, (_, hash) => `workerCurrentVersion${"x".repeat(hash.length)}"`).replaceAll(/"Value":"\d+\.\d+\.\d+-([^"]+)"/g, (_, hash) => `"Value": "x.x.x-${"x".repeat(hash.length)}"`).replaceAll(/"Value":"v\d+\.\d+\.\d+"/g, (_) => "\"Value\": \"vx.x.x\"").replace(/"DD_TAGS":"git.commit.sha:([0-9a-f]+),git.repository_url:([^\"]+)",/g, "").replaceAll(/(layer:Datadog-[^-]+-.+?:)\d+/g, (_, layer) => `${layer}x`);
4
5
  const normaliseTemplate = (template) => JSON.parse(normaliseTemplateJsonString(JSON.stringify(template)));
5
6
  //#endregion
7
+ Object.defineProperty(exports, "cdk_exports", {
8
+ enumerable: true,
9
+ get: function() {
10
+ return cdk_exports;
11
+ }
12
+ });
6
13
  exports.normaliseTemplate = normaliseTemplate;
@@ -1,4 +1,6 @@
1
- //#region src/cdk/normaliseTemplate/index.d.ts
1
+ declare namespace index_d_exports {
2
+ export { normaliseTemplate };
3
+ }
2
4
  declare const normaliseTemplate: (template: object) => unknown;
3
5
  //#endregion
4
- export { normaliseTemplate };
6
+ export { normaliseTemplate, index_d_exports as t };
@@ -1,4 +1,6 @@
1
- //#region src/cdk/normaliseTemplate/index.d.ts
1
+ declare namespace index_d_exports {
2
+ export { normaliseTemplate };
3
+ }
2
4
  declare const normaliseTemplate: (template: object) => unknown;
3
5
  //#endregion
4
- export { normaliseTemplate };
6
+ export { normaliseTemplate, index_d_exports as t };
package/lib/cdk/index.mjs CHANGED
@@ -1,5 +1,7 @@
1
- //#region src/cdk/normaliseTemplate/index.ts
1
+ import { t as __exportAll } from "../chunk-D7D4PA-g.mjs";
2
+ //#region src/cdk/index.ts
3
+ var cdk_exports = /* @__PURE__ */ __exportAll({ normaliseTemplate: () => normaliseTemplate });
2
4
  const normaliseTemplateJsonString = (json) => json.replace(/"S3Key":"([0-9a-f]+)\.zip"/g, (_, hash) => `"S3Key":"${"x".repeat(hash.length)}.zip"`).replace(/workerCurrentVersion([0-9a-zA-Z]+)"/g, (_, hash) => `workerCurrentVersion${"x".repeat(hash.length)}"`).replaceAll(/"Value":"\d+\.\d+\.\d+-([^"]+)"/g, (_, hash) => `"Value": "x.x.x-${"x".repeat(hash.length)}"`).replaceAll(/"Value":"v\d+\.\d+\.\d+"/g, (_) => "\"Value\": \"vx.x.x\"").replace(/"DD_TAGS":"git.commit.sha:([0-9a-f]+),git.repository_url:([^\"]+)",/g, "").replaceAll(/(layer:Datadog-[^-]+-.+?:)\d+/g, (_, layer) => `${layer}x`);
3
5
  const normaliseTemplate = (template) => JSON.parse(normaliseTemplateJsonString(JSON.stringify(template)));
4
6
  //#endregion
5
- export { normaliseTemplate };
7
+ export { normaliseTemplate, cdk_exports as t };
package/lib/index.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_buildkite = require("./buildkite-Dyd__LF3.cjs");
3
+ const require_cdk_index = require("./cdk/index.cjs");
3
4
  const require_git = require("./git-CEnn1Qrs.cjs");
4
5
  const require_github = require("./github-CzH1PaKH.cjs");
5
6
  const require_net = require("./net-BGgnkCnN.cjs");
@@ -9,6 +10,12 @@ Object.defineProperty(exports, "Buildkite", {
9
10
  return require_buildkite.buildkite_exports;
10
11
  }
11
12
  });
13
+ Object.defineProperty(exports, "Cdk", {
14
+ enumerable: true,
15
+ get: function() {
16
+ return require_cdk_index.cdk_exports;
17
+ }
18
+ });
12
19
  Object.defineProperty(exports, "Git", {
13
20
  enumerable: true,
14
21
  get: function() {
package/lib/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { t as index_d_exports } from "./index-CNxgBJm_.cjs";
2
- import { t as index_d_exports$1 } from "./index-C9WMO_Y9.cjs";
3
- import { t as index_d_exports$2 } from "./index-D4JUiy2k.cjs";
4
- import { t as index_d_exports$3 } from "./index-Kyp8ZCwF.cjs";
5
- export { index_d_exports as Buildkite, index_d_exports$1 as Git, index_d_exports$2 as GitHub, index_d_exports$3 as Net };
2
+ import { t as index_d_exports$1 } from "./cdk/index.cjs";
3
+ import { t as index_d_exports$2 } from "./index-C9WMO_Y9.cjs";
4
+ import { t as index_d_exports$3 } from "./index-D4JUiy2k.cjs";
5
+ import { t as index_d_exports$4 } from "./index-Kyp8ZCwF.cjs";
6
+ export { index_d_exports as Buildkite, index_d_exports$1 as Cdk, index_d_exports$2 as Git, index_d_exports$3 as GitHub, index_d_exports$4 as Net };
package/lib/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { t as index_d_exports } from "./index-CNxgBJm_.mjs";
2
- import { t as index_d_exports$1 } from "./index-C9WMO_Y9.mjs";
3
- import { t as index_d_exports$2 } from "./index-DbjgHTTm.mjs";
4
- import { t as index_d_exports$3 } from "./index-Kyp8ZCwF.mjs";
5
- export { index_d_exports as Buildkite, index_d_exports$1 as Git, index_d_exports$2 as GitHub, index_d_exports$3 as Net };
2
+ import { t as index_d_exports$1 } from "./cdk/index.mjs";
3
+ import { t as index_d_exports$2 } from "./index-C9WMO_Y9.mjs";
4
+ import { t as index_d_exports$3 } from "./index-DbjgHTTm.mjs";
5
+ import { t as index_d_exports$4 } from "./index-Kyp8ZCwF.mjs";
6
+ export { index_d_exports as Buildkite, index_d_exports$1 as Cdk, index_d_exports$2 as Git, index_d_exports$3 as GitHub, index_d_exports$4 as Net };
package/lib/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { t as buildkite_exports } from "./buildkite-CJ4a_6Cv.mjs";
2
+ import { t as cdk_exports } from "./cdk/index.mjs";
2
3
  import { t as git_exports } from "./git-BSWQdkgU.mjs";
3
4
  import { t as github_exports } from "./github-IYwiDs5D.mjs";
4
5
  import { t as net_exports } from "./net-ZfhL_QSV.mjs";
5
- export { buildkite_exports as Buildkite, git_exports as Git, github_exports as GitHub, net_exports as Net };
6
+ export { buildkite_exports as Buildkite, cdk_exports as Cdk, git_exports as Git, github_exports as GitHub, net_exports as Net };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skuba-lib/api",
3
- "version": "2.2.0-add-cdk-NodejsFunction-20260613135656",
3
+ "version": "2.2.0-hoist-changesets-20260614023310",
4
4
  "description": "Node.js development API for skuba",
5
5
  "homepage": "https://github.com/seek-oss/skuba#readme",
6
6
  "bugs": {
@@ -26,10 +26,6 @@
26
26
  "import": "./lib/cdk/index.mjs",
27
27
  "require": "./lib/cdk/index.cjs"
28
28
  },
29
- "./cdk/nodejsFunction": {
30
- "import": "./lib/cdk/nodejsFunction/index.mjs",
31
- "require": "./lib/cdk/nodejsFunction/index.cjs"
32
- },
33
29
  "./git": {
34
30
  "import": "./lib/git/index.mjs",
35
31
  "require": "./lib/git/index.cjs"
@@ -66,30 +62,8 @@
66
62
  "isomorphic-git": "^1.37.6",
67
63
  "npm-run-path": "^6.0.0",
68
64
  "npm-which": "^3.0.1",
69
- "yaml": "^2.9.0",
70
65
  "zod": "^4.3.5"
71
66
  },
72
- "devDependencies": {
73
- "aws-cdk-lib": "^2.253.0",
74
- "constructs": "^10.0.17",
75
- "rolldown": "~1.0.0"
76
- },
77
- "peerDependencies": {
78
- "aws-cdk-lib": ">=2.130.0",
79
- "constructs": "^10.0.0",
80
- "rolldown": ">=1.0.0"
81
- },
82
- "peerDependenciesMeta": {
83
- "aws-cdk-lib": {
84
- "optional": true
85
- },
86
- "constructs": {
87
- "optional": true
88
- },
89
- "rolldown": {
90
- "optional": true
91
- }
92
- },
93
67
  "engines": {
94
68
  "node": ">=22.14.0"
95
69
  },
@@ -1,6 +0,0 @@
1
- {
2
- "type": "module",
3
- "main": "../../lib/cdk/nodejsFunction/index.cjs",
4
- "module": "../../lib/cdk/nodejsFunction/index.mjs",
5
- "types": "../../lib/cdk/nodejsFunction/index.d.cts"
6
- }
@@ -1,49 +0,0 @@
1
- import { writeFileSync } from "node:fs";
2
- import { join } from "node:path";
3
- import { pathToFileURL } from "node:url";
4
- import { rolldown } from "rolldown";
5
- //#region src/cdk/nodejsFunction/util.ts
6
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7
- const BUNDLE_META_FILENAME = ".lambda-bundle-meta";
8
- const ESM_FORMATS = new Set([
9
- "es",
10
- "esm",
11
- "module"
12
- ]);
13
- const isEsmFormat = (format) => ESM_FORMATS.has(format ?? "");
14
- //#endregion
15
- //#region src/cdk/nodejsFunction/bridges/rolldown.mts
16
- const [configPath, entry, outputDir] = process.argv.slice(2, 5);
17
- if (!configPath || !entry || !outputDir) throw new Error("Expected arguments: <configPath> <entry> <outputDir>");
18
- const asRecord = (value) => isRecord(value) ? value : void 0;
19
- const asString = (value) => typeof value === "string" ? value : void 0;
20
- const userConfig = asRecord(asRecord(await import(pathToFileURL(configPath).href))?.default);
21
- if (!userConfig) throw new Error(`Config file must export a default config object: ${configPath}`);
22
- const rawOutput = userConfig.output;
23
- if (Array.isArray(rawOutput) && rawOutput.length !== 1) throw new Error("`output` must be a single output object: NodejsFunction emits a single index.js/index.mjs handler.");
24
- const baseRaw = asRecord(Array.isArray(rawOutput) ? rawOutput[0] : rawOutput) ?? {};
25
- if (baseRaw.preserveModules) throw new Error("`output.preserveModules` is not supported: NodejsFunction emits a single index.js/index.mjs handler.");
26
- if (baseRaw.entryFileNames !== void 0) throw new Error("`output.entryFileNames` is not supported: NodejsFunction names the handler index.js/index.mjs itself.");
27
- if (userConfig.input !== void 0) throw new Error("`input` is not supported: NodejsFunction sets the bundle entry itself.");
28
- const format = asString(baseRaw.format) ?? "es";
29
- const { file: _file, ...baseRest } = baseRaw;
30
- const { output: _output, ...userConfigRest } = userConfig;
31
- const inputOptions = {
32
- ...userConfigRest,
33
- input: entry
34
- };
35
- const outputOptions = {
36
- ...baseRest,
37
- format,
38
- dir: outputDir,
39
- entryFileNames: isEsmFormat(format) ? "index.mjs" : "index.js"
40
- };
41
- const bundle = await rolldown(inputOptions);
42
- try {
43
- await bundle.write(outputOptions);
44
- } finally {
45
- await bundle.close();
46
- }
47
- writeFileSync(join(outputDir, BUNDLE_META_FILENAME), JSON.stringify({ format }));
48
- //#endregion
49
- export {};
@@ -1,371 +0,0 @@
1
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_chunk = require("../../chunk-DakpK96I.cjs");
3
- let node_fs = require("node:fs");
4
- node_fs = require_chunk.__toESM(node_fs, 1);
5
- let node_path = require("node:path");
6
- node_path = require_chunk.__toESM(node_path, 1);
7
- let aws_cdk_lib_aws_lambda = require("aws-cdk-lib/aws-lambda");
8
- aws_cdk_lib_aws_lambda = require_chunk.__toESM(aws_cdk_lib_aws_lambda, 1);
9
- let node_child_process = require("node:child_process");
10
- let aws_cdk_lib = require("aws-cdk-lib");
11
- aws_cdk_lib = require_chunk.__toESM(aws_cdk_lib, 1);
12
- let node_url = require("node:url");
13
- let yaml = require("yaml");
14
- let node_module = require("node:module");
15
- //#region src/cdk/nodejsFunction/errors.ts
16
- var ValidationError = class extends Error {
17
- constructor(message) {
18
- super(message);
19
- this.name = "ValidationError";
20
- }
21
- };
22
- //#endregion
23
- //#region src/cdk/nodejsFunction/bridge-path.ts
24
- const findPackageRoot = (moduleUrl) => {
25
- let dir = node_path.dirname((0, node_url.fileURLToPath)(moduleUrl));
26
- for (;;) {
27
- if (node_fs.existsSync(node_path.join(dir, "package.json"))) return dir;
28
- const parent = node_path.dirname(dir);
29
- if (parent === dir) throw new ValidationError("Unable to locate the package root to resolve the bundler bridge script.");
30
- dir = parent;
31
- }
32
- };
33
- const BRIDGE_OUTPUT_SEGMENTS = [
34
- "lib",
35
- "cdk",
36
- "bridges",
37
- "rolldown.mjs"
38
- ];
39
- let bridgePath;
40
- const resolveRolldownBridge = () => bridgePath ??= node_path.join(findPackageRoot(require("url").pathToFileURL(__filename).href), ...BRIDGE_OUTPUT_SEGMENTS);
41
- //#endregion
42
- //#region src/cdk/nodejsFunction/util.ts
43
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
44
- const BUNDLE_META_FILENAME = ".lambda-bundle-meta";
45
- const ESM_FORMATS = new Set([
46
- "es",
47
- "esm",
48
- "module"
49
- ]);
50
- const isEsmFormat = (format) => ESM_FORMATS.has(format ?? "");
51
- const parseJsonFile = (filePath) => {
52
- try {
53
- return JSON.parse(node_fs.readFileSync(filePath, "utf-8"));
54
- } catch (err) {
55
- throw new ValidationError(`Failed to parse ${filePath} as JSON: ${err.message}`);
56
- }
57
- };
58
- const findUp = (name, directory = process.cwd()) => {
59
- const absoluteDirectory = node_path.resolve(directory);
60
- const file = node_path.join(absoluteDirectory, name);
61
- if (node_fs.existsSync(file)) return file;
62
- const { root } = node_path.parse(absoluteDirectory);
63
- if (absoluteDirectory === root) return;
64
- return findUp(name, node_path.dirname(absoluteDirectory));
65
- };
66
- const extractDependencies = (pkgPath, modules) => {
67
- const result = {};
68
- const base = (0, node_url.pathToFileURL)(pkgPath);
69
- for (const mod of modules) {
70
- let modPkgPath;
71
- try {
72
- modPkgPath = (0, node_module.findPackageJSON)(mod, base);
73
- } catch {
74
- modPkgPath = void 0;
75
- }
76
- const parsed = modPkgPath ? parseJsonFile(modPkgPath) : void 0;
77
- const version = isRecord(parsed) && typeof parsed.version === "string" ? parsed.version.trim() : void 0;
78
- if (!version) throw new ValidationError(`Cannot extract version for module '${mod}'. Check that it's referenced in your package.json or installed.`);
79
- result[mod] = version;
80
- }
81
- return result;
82
- };
83
- //#endregion
84
- //#region src/cdk/nodejsFunction/package-manager.ts
85
- const PNPM_LOCK = "pnpm-lock.yaml";
86
- const PNPM_WORKSPACE_FILES = [
87
- "pnpm-workspace.yaml",
88
- ".npmrc",
89
- ".pnpmfile.cjs",
90
- ".pnpmfile.mjs"
91
- ];
92
- const PNPM_INSTALL_COMMAND = [
93
- "pnpm",
94
- "install",
95
- "--config.node-linker=hoisted",
96
- "--config.package-import-method=clone-or-copy",
97
- "--no-frozen-lockfile"
98
- ];
99
- const isInside = (parent, child) => {
100
- const rel = node_path.relative(node_path.resolve(parent), node_path.resolve(child));
101
- return rel === "" || !rel.startsWith("..") && !node_path.isAbsolute(rel);
102
- };
103
- const assertPnpm = (name, source, pkgPath) => {
104
- if (name !== "pnpm") throw new ValidationError(`Unsupported package manager '${name}' declared in ${source} of ${pkgPath}. NodejsFunction only supports pnpm.`);
105
- };
106
- const readPackageManagerMeta = (projectRoot) => {
107
- const pkgPath = node_path.join(projectRoot, "package.json");
108
- const nearestPackageJson = node_fs.existsSync(pkgPath) ? pkgPath : void 0;
109
- if (!nearestPackageJson) return {
110
- nearestPackageJson,
111
- packageManagerField: void 0
112
- };
113
- const parsed = parseJsonFile(pkgPath);
114
- if (!isRecord(parsed)) return {
115
- nearestPackageJson,
116
- packageManagerField: void 0
117
- };
118
- if (isRecord(parsed.devEngines)) {
119
- const devEnginesPm = parsed.devEngines.packageManager;
120
- if (isRecord(devEnginesPm) && typeof devEnginesPm.name === "string") assertPnpm(devEnginesPm.name, "the `devEngines.packageManager` field", pkgPath);
121
- }
122
- if (typeof parsed.packageManager === "string") {
123
- const m = /^([^@\s]+)@/.exec(parsed.packageManager);
124
- if (m) {
125
- assertPnpm(m[1], "the `packageManager` field", pkgPath);
126
- return {
127
- nearestPackageJson,
128
- packageManagerField: parsed.packageManager
129
- };
130
- }
131
- }
132
- return {
133
- nearestPackageJson,
134
- packageManagerField: void 0
135
- };
136
- };
137
- const injectIgnoreScripts = (outputDir) => {
138
- const target = node_path.join(outputDir, ".npmrc");
139
- const existing = node_fs.existsSync(target) ? node_fs.readFileSync(target, "utf8") : "";
140
- if (/^ignore-scripts\s*=/m.test(existing)) return;
141
- const sep = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
142
- node_fs.writeFileSync(target, `${existing}${sep}ignore-scripts=true\n`);
143
- };
144
- const copyPatchFile = (relativePath, projectRoot, outputDir, copiedFiles) => {
145
- const src = node_path.join(projectRoot, relativePath);
146
- const dest = node_path.join(outputDir, relativePath);
147
- if (!isInside(projectRoot, src) || !isInside(outputDir, dest)) throw new ValidationError(`Refusing to copy pnpm patch '${relativePath}': it resolves outside the project root or output directory.`);
148
- if (!node_fs.existsSync(src)) return;
149
- const realSrc = node_fs.realpathSync(src);
150
- if (!isInside(node_fs.realpathSync(projectRoot), realSrc)) throw new ValidationError(`Refusing to copy pnpm patch '${relativePath}': it resolves (via symlink) outside the project root.`);
151
- node_fs.mkdirSync(node_path.dirname(dest), { recursive: true });
152
- node_fs.copyFileSync(realSrc, dest);
153
- copiedFiles.push(dest);
154
- };
155
- const filterPnpmWorkspaceYaml = (content, nodeModules, projectRoot, outputDir) => {
156
- let doc;
157
- try {
158
- doc = (0, yaml.parse)(content);
159
- } catch (err) {
160
- throw new ValidationError(`Failed to parse pnpm-workspace.yaml: ${err.message}`);
161
- }
162
- if (!isRecord(doc) || !("patchedDependencies" in doc)) return {
163
- content,
164
- copiedFiles: []
165
- };
166
- const patched = doc.patchedDependencies;
167
- const copiedFiles = [];
168
- if (isRecord(patched)) for (const [key, value] of Object.entries(patched)) {
169
- const pkgName = key.replace(/(?<=.)@[^@]+$/, "");
170
- if (!nodeModules.includes(pkgName)) delete patched[key];
171
- else if (typeof value === "string" && value) copyPatchFile(value, projectRoot, outputDir, copiedFiles);
172
- }
173
- if (!isRecord(patched) || Object.keys(patched).length === 0) delete doc.patchedDependencies;
174
- return {
175
- content: (0, yaml.stringify)(doc),
176
- copiedFiles
177
- };
178
- };
179
- const copyWorkspaceFiles = (projectRoot, outputDir, nodeModules = [], ignoreScripts = false) => {
180
- const stagedFiles = [];
181
- for (const file of PNPM_WORKSPACE_FILES) {
182
- const src = node_path.join(projectRoot, file);
183
- if (!node_fs.existsSync(src)) continue;
184
- const dest = node_path.join(outputDir, file);
185
- if (file === "pnpm-workspace.yaml") {
186
- const filtered = filterPnpmWorkspaceYaml(node_fs.readFileSync(src, "utf8"), nodeModules, projectRoot, outputDir);
187
- node_fs.writeFileSync(dest, filtered.content);
188
- stagedFiles.push(...filtered.copiedFiles);
189
- } else node_fs.copyFileSync(src, dest);
190
- }
191
- if (ignoreScripts) injectIgnoreScripts(outputDir);
192
- return stagedFiles;
193
- };
194
- //#endregion
195
- //#region src/cdk/nodejsFunction/bundling.ts
196
- const SPAWN_MAX_BUFFER = 256 * 1024 * 1024;
197
- const describeExit = (result) => result.signal != null ? `killed by signal ${result.signal}` : `exited with status ${result.status}`;
198
- const stderrTail = (stderr) => {
199
- if (!stderr) return "";
200
- const text = typeof stderr === "string" ? stderr : stderr.toString("utf-8");
201
- if (!text) return "";
202
- const tail = text.trimEnd().split("\n").slice(-20).join("\n");
203
- return tail ? `\n\n${tail}` : "";
204
- };
205
- const checkSpawnResult = (result, prefix) => {
206
- if (result.error) {
207
- if (result.error.code === "ETIMEDOUT") throw new ValidationError(`${prefix} timed out.${stderrTail(result.stderr)}`);
208
- throw result.error;
209
- }
210
- if (result.status !== 0) throw new ValidationError(`${prefix} ${describeExit(result)}.${stderrTail(result.stderr)}`);
211
- if (result.stderr) process.stderr.write(result.stderr);
212
- };
213
- const writeOutputPackageJson = (outputDir, fields) => {
214
- const pkg = {};
215
- if (fields.dependencies) pkg.dependencies = fields.dependencies;
216
- if (fields.isEsm) pkg.type = "module";
217
- if (fields.packageManager) pkg.packageManager = fields.packageManager;
218
- if (Object.keys(pkg).length === 0) return;
219
- node_fs.writeFileSync(node_path.join(outputDir, "package.json"), JSON.stringify(pkg, null, 2));
220
- };
221
- const removeEmptyParentDirs = (startDir, outputDir) => {
222
- let dir = startDir;
223
- while (dir.startsWith(outputDir + node_path.sep)) {
224
- try {
225
- node_fs.rmdirSync(dir);
226
- } catch {
227
- return;
228
- }
229
- dir = node_path.dirname(dir);
230
- }
231
- };
232
- var Bundling = class Bundling {
233
- props;
234
- static bundle(props) {
235
- return aws_cdk_lib_aws_lambda.Code.fromAsset(props.projectRoot, {
236
- assetHash: props.assetHash,
237
- assetHashType: props.assetHash ? aws_cdk_lib.AssetHashType.CUSTOM : aws_cdk_lib.AssetHashType.OUTPUT,
238
- bundling: new Bundling(props)
239
- });
240
- }
241
- image;
242
- local;
243
- constructor(props) {
244
- this.props = props;
245
- this.image = aws_cdk_lib.DockerImage.fromRegistry("dummy");
246
- this.local = this.buildLocalBundling();
247
- }
248
- buildLocalBundling() {
249
- return { tryBundle: (outputDir) => {
250
- this.runHooks(this.props.commandHooks?.beforeBundling(this.props.projectRoot, outputDir) ?? [], this.props.projectRoot);
251
- this.runBundler(outputDir);
252
- const isEsm = this.readBundleMeta(outputDir);
253
- const { nodeModules } = this.props;
254
- if (nodeModules?.length) this.installNodeModules(outputDir, isEsm, nodeModules);
255
- else writeOutputPackageJson(outputDir, { isEsm });
256
- this.runHooks(this.props.commandHooks?.afterBundling(this.props.projectRoot, outputDir) ?? [], this.props.projectRoot);
257
- return true;
258
- } };
259
- }
260
- runHooks(commands, cwd) {
261
- for (const cmd of commands) this.spawn(cmd, [], cwd, `Command hook '${cmd}'`, { shell: true });
262
- }
263
- runBundler(outputDir) {
264
- this.spawn("node", [
265
- resolveRolldownBridge(),
266
- this.props.bundlerConfig,
267
- this.props.entry,
268
- outputDir
269
- ], this.props.projectRoot, "Bundler 'rolldown'");
270
- }
271
- readBundleMeta(outputDir) {
272
- const metaPath = node_path.join(outputDir, BUNDLE_META_FILENAME);
273
- if (!node_fs.existsSync(metaPath)) return false;
274
- try {
275
- const parsed = parseJsonFile(metaPath);
276
- return isEsmFormat(isRecord(parsed) && typeof parsed.format === "string" ? parsed.format : void 0);
277
- } finally {
278
- node_fs.unlinkSync(metaPath);
279
- }
280
- }
281
- installNodeModules(outputDir, isEsm, nodeModules) {
282
- const { nearestPackageJson, packageManagerField } = readPackageManagerMeta(this.props.projectRoot);
283
- if (!nearestPackageJson) throw new ValidationError("Cannot find a package.json. Using nodeModules requires a package.json.");
284
- this.runHooks(this.props.commandHooks?.beforeInstall(this.props.projectRoot, outputDir) ?? [], this.props.projectRoot);
285
- writeOutputPackageJson(outputDir, {
286
- dependencies: extractDependencies(nearestPackageJson, nodeModules),
287
- isEsm,
288
- packageManager: packageManagerField
289
- });
290
- let stagedFiles = [];
291
- try {
292
- stagedFiles = copyWorkspaceFiles(this.props.projectRoot, outputDir, nodeModules, this.props.ignoreScripts);
293
- if (node_fs.existsSync(this.props.depsLockFilePath)) node_fs.copyFileSync(this.props.depsLockFilePath, node_path.join(outputDir, PNPM_LOCK));
294
- const [installBin, ...installArgs] = PNPM_INSTALL_COMMAND;
295
- this.spawn(installBin, installArgs, outputDir, "Package manager 'pnpm' install");
296
- } finally {
297
- node_fs.rmSync(node_path.join(outputDir, PNPM_LOCK), { force: true });
298
- for (const file of PNPM_WORKSPACE_FILES) node_fs.rmSync(node_path.join(outputDir, file), { force: true });
299
- for (const file of stagedFiles) {
300
- node_fs.rmSync(file, { force: true });
301
- removeEmptyParentDirs(node_path.dirname(file), outputDir);
302
- }
303
- }
304
- }
305
- spawn(bin, args, cwd, prefix, opts) {
306
- checkSpawnResult((0, node_child_process.spawnSync)(bin, args, {
307
- env: process.env,
308
- stdio: [
309
- "ignore",
310
- "inherit",
311
- "pipe"
312
- ],
313
- cwd,
314
- timeout: this.props.timeout,
315
- encoding: "utf-8",
316
- maxBuffer: SPAWN_MAX_BUFFER,
317
- shell: opts?.shell
318
- }), prefix);
319
- }
320
- };
321
- //#endregion
322
- //#region src/cdk/nodejsFunction/function.ts
323
- var NodejsFunction = class extends aws_cdk_lib_aws_lambda.Function {
324
- constructor(scope, id, props) {
325
- if (props.runtime && props.runtime.family !== aws_cdk_lib_aws_lambda.RuntimeFamily.NODEJS) throw new ValidationError("Only NODEJS runtimes are supported.");
326
- const runtime = props.runtime ?? aws_cdk_lib_aws_lambda.Runtime.NODEJS_LATEST;
327
- const entry = validateEntry(props.entry);
328
- const depsLockFilePath = findLockFile(props.depsLockFilePath);
329
- const projectRoot = node_path.resolve(props.projectRoot ?? node_path.dirname(depsLockFilePath));
330
- const bundlerConfig = findBundlerConfig(props.bundling.bundlerConfig, projectRoot);
331
- const handlerFn = resolveHandlerFn(props.handler);
332
- const { entry: _entry, bundling, depsLockFilePath: _depsLockFilePath, projectRoot: _projectRoot, handler: _handler, runtime: _runtime, ...functionOptions } = props;
333
- super(scope, id, {
334
- ...functionOptions,
335
- runtime,
336
- code: Bundling.bundle({
337
- ...bundling,
338
- bundlerConfig,
339
- entry,
340
- runtime,
341
- depsLockFilePath,
342
- projectRoot
343
- }),
344
- handler: `index.${handlerFn}`
345
- });
346
- }
347
- };
348
- const resolveHandlerFn = (handler) => {
349
- const handlerName = (handler ?? "handler").trim();
350
- const handlerFn = handlerName.slice(handlerName.lastIndexOf(".") + 1);
351
- if (!/^[A-Za-z_$][\w$]*$/.test(handlerFn)) throw new ValidationError(`Invalid handler '${handler}'. Expected an exported function name, optionally prefixed with a file part (e.g. 'handler' or 'index.handler').`);
352
- return handlerFn;
353
- };
354
- const validateEntry = (entry) => {
355
- const base = node_path.basename(entry);
356
- if (/\.d\.(c|m)?ts$/i.test(base) || !/\.(js|ts|mjs|mts|cts|cjs)$/i.test(base)) throw new ValidationError("Only JavaScript or TypeScript entry files are supported.");
357
- return node_path.resolve(entry);
358
- };
359
- const findBundlerConfig = (bundlerConfig, projectRoot) => node_path.isAbsolute(bundlerConfig) ? bundlerConfig : node_path.resolve(projectRoot, bundlerConfig);
360
- const findLockFile = (depsLockFilePath) => {
361
- if (depsLockFilePath) {
362
- const resolved = node_path.resolve(depsLockFilePath);
363
- if (!node_fs.existsSync(resolved)) throw new ValidationError(`Cannot find a pnpm-lock.yaml file at '${depsLockFilePath}'.`);
364
- return resolved;
365
- }
366
- const lockFile = findUp(PNPM_LOCK);
367
- if (!lockFile) throw new ValidationError("Cannot find a pnpm-lock.yaml file. Please specify it with `depsLockFilePath`.");
368
- return lockFile;
369
- };
370
- //#endregion
371
- exports.NodejsFunction = NodejsFunction;
@@ -1,32 +0,0 @@
1
- import * as lambda from "aws-cdk-lib/aws-lambda";
2
- import { Construct } from "constructs";
3
-
4
- //#region src/cdk/nodejsFunction/types.d.ts
5
- interface ICommandHooks {
6
- beforeBundling(inputDir: string, outputDir: string): string[];
7
- afterBundling(inputDir: string, outputDir: string): string[];
8
- beforeInstall(inputDir: string, outputDir: string): string[];
9
- }
10
- interface BundlingOptions {
11
- bundlerConfig: string;
12
- nodeModules?: string[];
13
- commandHooks?: ICommandHooks;
14
- assetHash?: string;
15
- timeout?: number;
16
- ignoreScripts?: boolean;
17
- }
18
- //#endregion
19
- //#region src/cdk/nodejsFunction/function.d.ts
20
- interface NodejsFunctionProps extends lambda.FunctionOptions {
21
- readonly entry: string;
22
- readonly handler?: string;
23
- readonly runtime?: lambda.Runtime;
24
- readonly depsLockFilePath?: string;
25
- readonly projectRoot?: string;
26
- readonly bundling: BundlingOptions;
27
- }
28
- declare class NodejsFunction extends lambda.Function {
29
- constructor(scope: Construct, id: string, props: NodejsFunctionProps);
30
- }
31
- //#endregion
32
- export { type BundlingOptions, type ICommandHooks, NodejsFunction, type NodejsFunctionProps };
@@ -1,32 +0,0 @@
1
- import * as lambda from "aws-cdk-lib/aws-lambda";
2
- import { Construct } from "constructs";
3
-
4
- //#region src/cdk/nodejsFunction/types.d.ts
5
- interface ICommandHooks {
6
- beforeBundling(inputDir: string, outputDir: string): string[];
7
- afterBundling(inputDir: string, outputDir: string): string[];
8
- beforeInstall(inputDir: string, outputDir: string): string[];
9
- }
10
- interface BundlingOptions {
11
- bundlerConfig: string;
12
- nodeModules?: string[];
13
- commandHooks?: ICommandHooks;
14
- assetHash?: string;
15
- timeout?: number;
16
- ignoreScripts?: boolean;
17
- }
18
- //#endregion
19
- //#region src/cdk/nodejsFunction/function.d.ts
20
- interface NodejsFunctionProps extends lambda.FunctionOptions {
21
- readonly entry: string;
22
- readonly handler?: string;
23
- readonly runtime?: lambda.Runtime;
24
- readonly depsLockFilePath?: string;
25
- readonly projectRoot?: string;
26
- readonly bundling: BundlingOptions;
27
- }
28
- declare class NodejsFunction extends lambda.Function {
29
- constructor(scope: Construct, id: string, props: NodejsFunctionProps);
30
- }
31
- //#endregion
32
- export { type BundlingOptions, type ICommandHooks, NodejsFunction, type NodejsFunctionProps };
@@ -1,365 +0,0 @@
1
- import { findPackageJSON } from "node:module";
2
- import * as fs from "node:fs";
3
- import * as path from "node:path";
4
- import * as lambda from "aws-cdk-lib/aws-lambda";
5
- import { spawnSync } from "node:child_process";
6
- import * as cdk from "aws-cdk-lib";
7
- import { fileURLToPath, pathToFileURL } from "node:url";
8
- import { parse, stringify } from "yaml";
9
- //#region src/cdk/nodejsFunction/errors.ts
10
- var ValidationError = class extends Error {
11
- constructor(message) {
12
- super(message);
13
- this.name = "ValidationError";
14
- }
15
- };
16
- //#endregion
17
- //#region src/cdk/nodejsFunction/bridge-path.ts
18
- const findPackageRoot = (moduleUrl) => {
19
- let dir = path.dirname(fileURLToPath(moduleUrl));
20
- for (;;) {
21
- if (fs.existsSync(path.join(dir, "package.json"))) return dir;
22
- const parent = path.dirname(dir);
23
- if (parent === dir) throw new ValidationError("Unable to locate the package root to resolve the bundler bridge script.");
24
- dir = parent;
25
- }
26
- };
27
- const BRIDGE_OUTPUT_SEGMENTS = [
28
- "lib",
29
- "cdk",
30
- "bridges",
31
- "rolldown.mjs"
32
- ];
33
- let bridgePath;
34
- const resolveRolldownBridge = () => bridgePath ??= path.join(findPackageRoot(import.meta.url), ...BRIDGE_OUTPUT_SEGMENTS);
35
- //#endregion
36
- //#region src/cdk/nodejsFunction/util.ts
37
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
38
- const BUNDLE_META_FILENAME = ".lambda-bundle-meta";
39
- const ESM_FORMATS = new Set([
40
- "es",
41
- "esm",
42
- "module"
43
- ]);
44
- const isEsmFormat = (format) => ESM_FORMATS.has(format ?? "");
45
- const parseJsonFile = (filePath) => {
46
- try {
47
- return JSON.parse(fs.readFileSync(filePath, "utf-8"));
48
- } catch (err) {
49
- throw new ValidationError(`Failed to parse ${filePath} as JSON: ${err.message}`);
50
- }
51
- };
52
- const findUp = (name, directory = process.cwd()) => {
53
- const absoluteDirectory = path.resolve(directory);
54
- const file = path.join(absoluteDirectory, name);
55
- if (fs.existsSync(file)) return file;
56
- const { root } = path.parse(absoluteDirectory);
57
- if (absoluteDirectory === root) return;
58
- return findUp(name, path.dirname(absoluteDirectory));
59
- };
60
- const extractDependencies = (pkgPath, modules) => {
61
- const result = {};
62
- const base = pathToFileURL(pkgPath);
63
- for (const mod of modules) {
64
- let modPkgPath;
65
- try {
66
- modPkgPath = findPackageJSON(mod, base);
67
- } catch {
68
- modPkgPath = void 0;
69
- }
70
- const parsed = modPkgPath ? parseJsonFile(modPkgPath) : void 0;
71
- const version = isRecord(parsed) && typeof parsed.version === "string" ? parsed.version.trim() : void 0;
72
- if (!version) throw new ValidationError(`Cannot extract version for module '${mod}'. Check that it's referenced in your package.json or installed.`);
73
- result[mod] = version;
74
- }
75
- return result;
76
- };
77
- //#endregion
78
- //#region src/cdk/nodejsFunction/package-manager.ts
79
- const PNPM_LOCK = "pnpm-lock.yaml";
80
- const PNPM_WORKSPACE_FILES = [
81
- "pnpm-workspace.yaml",
82
- ".npmrc",
83
- ".pnpmfile.cjs",
84
- ".pnpmfile.mjs"
85
- ];
86
- const PNPM_INSTALL_COMMAND = [
87
- "pnpm",
88
- "install",
89
- "--config.node-linker=hoisted",
90
- "--config.package-import-method=clone-or-copy",
91
- "--no-frozen-lockfile"
92
- ];
93
- const isInside = (parent, child) => {
94
- const rel = path.relative(path.resolve(parent), path.resolve(child));
95
- return rel === "" || !rel.startsWith("..") && !path.isAbsolute(rel);
96
- };
97
- const assertPnpm = (name, source, pkgPath) => {
98
- if (name !== "pnpm") throw new ValidationError(`Unsupported package manager '${name}' declared in ${source} of ${pkgPath}. NodejsFunction only supports pnpm.`);
99
- };
100
- const readPackageManagerMeta = (projectRoot) => {
101
- const pkgPath = path.join(projectRoot, "package.json");
102
- const nearestPackageJson = fs.existsSync(pkgPath) ? pkgPath : void 0;
103
- if (!nearestPackageJson) return {
104
- nearestPackageJson,
105
- packageManagerField: void 0
106
- };
107
- const parsed = parseJsonFile(pkgPath);
108
- if (!isRecord(parsed)) return {
109
- nearestPackageJson,
110
- packageManagerField: void 0
111
- };
112
- if (isRecord(parsed.devEngines)) {
113
- const devEnginesPm = parsed.devEngines.packageManager;
114
- if (isRecord(devEnginesPm) && typeof devEnginesPm.name === "string") assertPnpm(devEnginesPm.name, "the `devEngines.packageManager` field", pkgPath);
115
- }
116
- if (typeof parsed.packageManager === "string") {
117
- const m = /^([^@\s]+)@/.exec(parsed.packageManager);
118
- if (m) {
119
- assertPnpm(m[1], "the `packageManager` field", pkgPath);
120
- return {
121
- nearestPackageJson,
122
- packageManagerField: parsed.packageManager
123
- };
124
- }
125
- }
126
- return {
127
- nearestPackageJson,
128
- packageManagerField: void 0
129
- };
130
- };
131
- const injectIgnoreScripts = (outputDir) => {
132
- const target = path.join(outputDir, ".npmrc");
133
- const existing = fs.existsSync(target) ? fs.readFileSync(target, "utf8") : "";
134
- if (/^ignore-scripts\s*=/m.test(existing)) return;
135
- const sep = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
136
- fs.writeFileSync(target, `${existing}${sep}ignore-scripts=true\n`);
137
- };
138
- const copyPatchFile = (relativePath, projectRoot, outputDir, copiedFiles) => {
139
- const src = path.join(projectRoot, relativePath);
140
- const dest = path.join(outputDir, relativePath);
141
- if (!isInside(projectRoot, src) || !isInside(outputDir, dest)) throw new ValidationError(`Refusing to copy pnpm patch '${relativePath}': it resolves outside the project root or output directory.`);
142
- if (!fs.existsSync(src)) return;
143
- const realSrc = fs.realpathSync(src);
144
- if (!isInside(fs.realpathSync(projectRoot), realSrc)) throw new ValidationError(`Refusing to copy pnpm patch '${relativePath}': it resolves (via symlink) outside the project root.`);
145
- fs.mkdirSync(path.dirname(dest), { recursive: true });
146
- fs.copyFileSync(realSrc, dest);
147
- copiedFiles.push(dest);
148
- };
149
- const filterPnpmWorkspaceYaml = (content, nodeModules, projectRoot, outputDir) => {
150
- let doc;
151
- try {
152
- doc = parse(content);
153
- } catch (err) {
154
- throw new ValidationError(`Failed to parse pnpm-workspace.yaml: ${err.message}`);
155
- }
156
- if (!isRecord(doc) || !("patchedDependencies" in doc)) return {
157
- content,
158
- copiedFiles: []
159
- };
160
- const patched = doc.patchedDependencies;
161
- const copiedFiles = [];
162
- if (isRecord(patched)) for (const [key, value] of Object.entries(patched)) {
163
- const pkgName = key.replace(/(?<=.)@[^@]+$/, "");
164
- if (!nodeModules.includes(pkgName)) delete patched[key];
165
- else if (typeof value === "string" && value) copyPatchFile(value, projectRoot, outputDir, copiedFiles);
166
- }
167
- if (!isRecord(patched) || Object.keys(patched).length === 0) delete doc.patchedDependencies;
168
- return {
169
- content: stringify(doc),
170
- copiedFiles
171
- };
172
- };
173
- const copyWorkspaceFiles = (projectRoot, outputDir, nodeModules = [], ignoreScripts = false) => {
174
- const stagedFiles = [];
175
- for (const file of PNPM_WORKSPACE_FILES) {
176
- const src = path.join(projectRoot, file);
177
- if (!fs.existsSync(src)) continue;
178
- const dest = path.join(outputDir, file);
179
- if (file === "pnpm-workspace.yaml") {
180
- const filtered = filterPnpmWorkspaceYaml(fs.readFileSync(src, "utf8"), nodeModules, projectRoot, outputDir);
181
- fs.writeFileSync(dest, filtered.content);
182
- stagedFiles.push(...filtered.copiedFiles);
183
- } else fs.copyFileSync(src, dest);
184
- }
185
- if (ignoreScripts) injectIgnoreScripts(outputDir);
186
- return stagedFiles;
187
- };
188
- //#endregion
189
- //#region src/cdk/nodejsFunction/bundling.ts
190
- const SPAWN_MAX_BUFFER = 256 * 1024 * 1024;
191
- const describeExit = (result) => result.signal != null ? `killed by signal ${result.signal}` : `exited with status ${result.status}`;
192
- const stderrTail = (stderr) => {
193
- if (!stderr) return "";
194
- const text = typeof stderr === "string" ? stderr : stderr.toString("utf-8");
195
- if (!text) return "";
196
- const tail = text.trimEnd().split("\n").slice(-20).join("\n");
197
- return tail ? `\n\n${tail}` : "";
198
- };
199
- const checkSpawnResult = (result, prefix) => {
200
- if (result.error) {
201
- if (result.error.code === "ETIMEDOUT") throw new ValidationError(`${prefix} timed out.${stderrTail(result.stderr)}`);
202
- throw result.error;
203
- }
204
- if (result.status !== 0) throw new ValidationError(`${prefix} ${describeExit(result)}.${stderrTail(result.stderr)}`);
205
- if (result.stderr) process.stderr.write(result.stderr);
206
- };
207
- const writeOutputPackageJson = (outputDir, fields) => {
208
- const pkg = {};
209
- if (fields.dependencies) pkg.dependencies = fields.dependencies;
210
- if (fields.isEsm) pkg.type = "module";
211
- if (fields.packageManager) pkg.packageManager = fields.packageManager;
212
- if (Object.keys(pkg).length === 0) return;
213
- fs.writeFileSync(path.join(outputDir, "package.json"), JSON.stringify(pkg, null, 2));
214
- };
215
- const removeEmptyParentDirs = (startDir, outputDir) => {
216
- let dir = startDir;
217
- while (dir.startsWith(outputDir + path.sep)) {
218
- try {
219
- fs.rmdirSync(dir);
220
- } catch {
221
- return;
222
- }
223
- dir = path.dirname(dir);
224
- }
225
- };
226
- var Bundling = class Bundling {
227
- props;
228
- static bundle(props) {
229
- return lambda.Code.fromAsset(props.projectRoot, {
230
- assetHash: props.assetHash,
231
- assetHashType: props.assetHash ? cdk.AssetHashType.CUSTOM : cdk.AssetHashType.OUTPUT,
232
- bundling: new Bundling(props)
233
- });
234
- }
235
- image;
236
- local;
237
- constructor(props) {
238
- this.props = props;
239
- this.image = cdk.DockerImage.fromRegistry("dummy");
240
- this.local = this.buildLocalBundling();
241
- }
242
- buildLocalBundling() {
243
- return { tryBundle: (outputDir) => {
244
- this.runHooks(this.props.commandHooks?.beforeBundling(this.props.projectRoot, outputDir) ?? [], this.props.projectRoot);
245
- this.runBundler(outputDir);
246
- const isEsm = this.readBundleMeta(outputDir);
247
- const { nodeModules } = this.props;
248
- if (nodeModules?.length) this.installNodeModules(outputDir, isEsm, nodeModules);
249
- else writeOutputPackageJson(outputDir, { isEsm });
250
- this.runHooks(this.props.commandHooks?.afterBundling(this.props.projectRoot, outputDir) ?? [], this.props.projectRoot);
251
- return true;
252
- } };
253
- }
254
- runHooks(commands, cwd) {
255
- for (const cmd of commands) this.spawn(cmd, [], cwd, `Command hook '${cmd}'`, { shell: true });
256
- }
257
- runBundler(outputDir) {
258
- this.spawn("node", [
259
- resolveRolldownBridge(),
260
- this.props.bundlerConfig,
261
- this.props.entry,
262
- outputDir
263
- ], this.props.projectRoot, "Bundler 'rolldown'");
264
- }
265
- readBundleMeta(outputDir) {
266
- const metaPath = path.join(outputDir, BUNDLE_META_FILENAME);
267
- if (!fs.existsSync(metaPath)) return false;
268
- try {
269
- const parsed = parseJsonFile(metaPath);
270
- return isEsmFormat(isRecord(parsed) && typeof parsed.format === "string" ? parsed.format : void 0);
271
- } finally {
272
- fs.unlinkSync(metaPath);
273
- }
274
- }
275
- installNodeModules(outputDir, isEsm, nodeModules) {
276
- const { nearestPackageJson, packageManagerField } = readPackageManagerMeta(this.props.projectRoot);
277
- if (!nearestPackageJson) throw new ValidationError("Cannot find a package.json. Using nodeModules requires a package.json.");
278
- this.runHooks(this.props.commandHooks?.beforeInstall(this.props.projectRoot, outputDir) ?? [], this.props.projectRoot);
279
- writeOutputPackageJson(outputDir, {
280
- dependencies: extractDependencies(nearestPackageJson, nodeModules),
281
- isEsm,
282
- packageManager: packageManagerField
283
- });
284
- let stagedFiles = [];
285
- try {
286
- stagedFiles = copyWorkspaceFiles(this.props.projectRoot, outputDir, nodeModules, this.props.ignoreScripts);
287
- if (fs.existsSync(this.props.depsLockFilePath)) fs.copyFileSync(this.props.depsLockFilePath, path.join(outputDir, PNPM_LOCK));
288
- const [installBin, ...installArgs] = PNPM_INSTALL_COMMAND;
289
- this.spawn(installBin, installArgs, outputDir, "Package manager 'pnpm' install");
290
- } finally {
291
- fs.rmSync(path.join(outputDir, PNPM_LOCK), { force: true });
292
- for (const file of PNPM_WORKSPACE_FILES) fs.rmSync(path.join(outputDir, file), { force: true });
293
- for (const file of stagedFiles) {
294
- fs.rmSync(file, { force: true });
295
- removeEmptyParentDirs(path.dirname(file), outputDir);
296
- }
297
- }
298
- }
299
- spawn(bin, args, cwd, prefix, opts) {
300
- checkSpawnResult(spawnSync(bin, args, {
301
- env: process.env,
302
- stdio: [
303
- "ignore",
304
- "inherit",
305
- "pipe"
306
- ],
307
- cwd,
308
- timeout: this.props.timeout,
309
- encoding: "utf-8",
310
- maxBuffer: SPAWN_MAX_BUFFER,
311
- shell: opts?.shell
312
- }), prefix);
313
- }
314
- };
315
- //#endregion
316
- //#region src/cdk/nodejsFunction/function.ts
317
- var NodejsFunction = class extends lambda.Function {
318
- constructor(scope, id, props) {
319
- if (props.runtime && props.runtime.family !== lambda.RuntimeFamily.NODEJS) throw new ValidationError("Only NODEJS runtimes are supported.");
320
- const runtime = props.runtime ?? lambda.Runtime.NODEJS_LATEST;
321
- const entry = validateEntry(props.entry);
322
- const depsLockFilePath = findLockFile(props.depsLockFilePath);
323
- const projectRoot = path.resolve(props.projectRoot ?? path.dirname(depsLockFilePath));
324
- const bundlerConfig = findBundlerConfig(props.bundling.bundlerConfig, projectRoot);
325
- const handlerFn = resolveHandlerFn(props.handler);
326
- const { entry: _entry, bundling, depsLockFilePath: _depsLockFilePath, projectRoot: _projectRoot, handler: _handler, runtime: _runtime, ...functionOptions } = props;
327
- super(scope, id, {
328
- ...functionOptions,
329
- runtime,
330
- code: Bundling.bundle({
331
- ...bundling,
332
- bundlerConfig,
333
- entry,
334
- runtime,
335
- depsLockFilePath,
336
- projectRoot
337
- }),
338
- handler: `index.${handlerFn}`
339
- });
340
- }
341
- };
342
- const resolveHandlerFn = (handler) => {
343
- const handlerName = (handler ?? "handler").trim();
344
- const handlerFn = handlerName.slice(handlerName.lastIndexOf(".") + 1);
345
- if (!/^[A-Za-z_$][\w$]*$/.test(handlerFn)) throw new ValidationError(`Invalid handler '${handler}'. Expected an exported function name, optionally prefixed with a file part (e.g. 'handler' or 'index.handler').`);
346
- return handlerFn;
347
- };
348
- const validateEntry = (entry) => {
349
- const base = path.basename(entry);
350
- if (/\.d\.(c|m)?ts$/i.test(base) || !/\.(js|ts|mjs|mts|cts|cjs)$/i.test(base)) throw new ValidationError("Only JavaScript or TypeScript entry files are supported.");
351
- return path.resolve(entry);
352
- };
353
- const findBundlerConfig = (bundlerConfig, projectRoot) => path.isAbsolute(bundlerConfig) ? bundlerConfig : path.resolve(projectRoot, bundlerConfig);
354
- const findLockFile = (depsLockFilePath) => {
355
- if (depsLockFilePath) {
356
- const resolved = path.resolve(depsLockFilePath);
357
- if (!fs.existsSync(resolved)) throw new ValidationError(`Cannot find a pnpm-lock.yaml file at '${depsLockFilePath}'.`);
358
- return resolved;
359
- }
360
- const lockFile = findUp(PNPM_LOCK);
361
- if (!lockFile) throw new ValidationError("Cannot find a pnpm-lock.yaml file. Please specify it with `depsLockFilePath`.");
362
- return lockFile;
363
- };
364
- //#endregion
365
- export { NodejsFunction };