@lark-apaas/fullstack-cli 1.1.64-alpha.20260902123941 → 1.1.64

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/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/index.ts
2
- import fs31 from "fs";
3
- import path27 from "path";
4
- import { fileURLToPath as fileURLToPath6 } from "url";
2
+ import fs29 from "fs";
3
+ import path25 from "path";
4
+ import { fileURLToPath as fileURLToPath5 } from "url";
5
5
  import { config as dotenvConfig } from "dotenv";
6
6
 
7
7
  // src/cli.ts
@@ -2483,36 +2483,12 @@ import fs7 from "fs";
2483
2483
  import { fileURLToPath as fileURLToPath3 } from "url";
2484
2484
 
2485
2485
  // src/config/sync.ts
2486
- function hasStartupBundleEnrollment(packageJson) {
2487
- if (!packageJson || typeof packageJson !== "object" || Array.isArray(packageJson)) {
2488
- return false;
2489
- }
2490
- const config = packageJson.miaodaStartupBundle;
2491
- return Boolean(
2492
- config && typeof config === "object" && !Array.isArray(config) && config.schemaVersion === 1
2493
- );
2494
- }
2495
- var DEFAULT_SYNCED_SCRIPT_FILES = [
2496
- "build.sh",
2497
- "dev-local.js",
2498
- "dev.sh",
2499
- "lint.js",
2500
- "prune-smart.js",
2501
- "run.sh"
2502
- ];
2503
2486
  function buildDefaultRules(opts) {
2504
2487
  const rules = [
2505
- // 1. 显式同步通用 scripts。禁止目录级 wholesale copy,避免将今后新增的
2506
- // 冷启动专属文件意外回灌到未入组的存量应用。
2507
- ...DEFAULT_SYNCED_SCRIPT_FILES.map((file) => ({
2508
- from: `templates/scripts/${file}`,
2509
- to: `scripts/${file}`,
2510
- type: "file",
2511
- overwrite: true
2512
- })),
2488
+ // 1. 派生 scripts 目录(总是覆盖;递归同步,包含 scripts/hooks/run-precommit.js)
2513
2489
  {
2514
- from: "templates/scripts/hooks",
2515
- to: "scripts/hooks",
2490
+ from: "templates/scripts",
2491
+ to: "scripts",
2516
2492
  type: "directory",
2517
2493
  overwrite: true
2518
2494
  },
@@ -2614,14 +2590,6 @@ function buildDefaultRules(opts) {
2614
2590
  ifStartsWith: "concurrently "
2615
2591
  }
2616
2592
  ];
2617
- if (opts.startupBundleEnrolled) {
2618
- rules.unshift({
2619
- from: "templates/scripts/dev.js",
2620
- to: "scripts/dev.js",
2621
- type: "file",
2622
- overwrite: true
2623
- });
2624
- }
2625
2593
  if (!opts.disableGenOpenapi) {
2626
2594
  rules.push({
2627
2595
  from: "templates/helper/gen-openapi.ts",
@@ -2798,14 +2766,10 @@ async function run2(options) {
2798
2766
  process.exit(0);
2799
2767
  }
2800
2768
  const stack = resolveStack(userProjectRoot);
2801
- const startupBundleEnrolled = resolveStartupBundleEnrollment(userPackageJson);
2802
2769
  try {
2803
- console.log(
2804
- `[fullstack-cli] Starting sync${stack ? ` (stack: ${stack})` : ""}...`
2805
- );
2770
+ console.log(`[fullstack-cli] Starting sync${stack ? ` (stack: ${stack})` : ""}...`);
2806
2771
  const config = genSyncConfig(stack, {
2807
- disableGenOpenapi: options.disableGenOpenapi ?? false,
2808
- startupBundleEnrolled
2772
+ disableGenOpenapi: options.disableGenOpenapi ?? false
2809
2773
  });
2810
2774
  if (!config || !config.sync) {
2811
2775
  console.warn("[fullstack-cli] No sync configuration found");
@@ -2822,9 +2786,7 @@ async function run2(options) {
2822
2786
  activateGitHooks(userProjectRoot);
2823
2787
  } catch (error) {
2824
2788
  const message = error instanceof Error ? error.message : String(error);
2825
- console.warn(
2826
- `[fullstack-cli] \u26A0 Failed to activate git hooks: ${message}`
2827
- );
2789
+ console.warn(`[fullstack-cli] \u26A0 Failed to activate git hooks: ${message}`);
2828
2790
  }
2829
2791
  }
2830
2792
  console.log("[fullstack-cli] Sync completed successfully \u2705");
@@ -2834,19 +2796,6 @@ async function run2(options) {
2834
2796
  process.exit(1);
2835
2797
  }
2836
2798
  }
2837
- function resolveStartupBundleEnrollment(packageJsonPath) {
2838
- try {
2839
- return hasStartupBundleEnrollment(
2840
- JSON.parse(fs7.readFileSync(packageJsonPath, "utf-8"))
2841
- );
2842
- } catch (error) {
2843
- const message = error instanceof Error ? error.message : String(error);
2844
- console.warn(
2845
- `[fullstack-cli] \u26A0 Failed to inspect startup bundle enrollment, using legacy sync: ${message}`
2846
- );
2847
- return false;
2848
- }
2849
- }
2850
2799
  function resolveStack(userProjectRoot) {
2851
2800
  const sparkMetaPath = path5.join(userProjectRoot, ".spark", "meta.json");
2852
2801
  if (!fs7.existsSync(sparkMetaPath)) {
@@ -2857,9 +2806,7 @@ function resolveStack(userProjectRoot) {
2857
2806
  return typeof meta.stack === "string" ? meta.stack : void 0;
2858
2807
  } catch (error) {
2859
2808
  const message = error instanceof Error ? error.message : String(error);
2860
- console.warn(
2861
- `[fullstack-cli] \u26A0 Failed to read .spark/meta.json, fallback to default sync: ${message}`
2862
- );
2809
+ console.warn(`[fullstack-cli] \u26A0 Failed to read .spark/meta.json, fallback to default sync: ${message}`);
2863
2810
  return void 0;
2864
2811
  }
2865
2812
  }
@@ -2880,12 +2827,7 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
2880
2827
  }
2881
2828
  if (rule.type === "add-script") {
2882
2829
  const packageJsonPath = path5.join(userProjectRoot, "package.json");
2883
- addScript(
2884
- packageJsonPath,
2885
- rule.name,
2886
- rule.command,
2887
- rule.overwrite ?? false
2888
- );
2830
+ addScript(packageJsonPath, rule.name, rule.command, rule.overwrite ?? false);
2889
2831
  return;
2890
2832
  }
2891
2833
  if (rule.type === "patch-script") {
@@ -2918,12 +2860,7 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
2918
2860
  syncDirectory(srcPath, destPath, rule.overwrite ?? true);
2919
2861
  break;
2920
2862
  case "file":
2921
- syncFile(
2922
- srcPath,
2923
- destPath,
2924
- rule.overwrite ?? true,
2925
- rule.onlyIfExists ?? false
2926
- );
2863
+ syncFile(srcPath, destPath, rule.overwrite ?? true, rule.onlyIfExists ?? false);
2927
2864
  break;
2928
2865
  case "append":
2929
2866
  appendToFile(srcPath, destPath);
@@ -2932,9 +2869,7 @@ async function syncRule(rule, pluginRoot, userProjectRoot) {
2932
2869
  }
2933
2870
  function syncFile(src, dest, overwrite = true, onlyIfExists = false) {
2934
2871
  if (onlyIfExists && !fs7.existsSync(dest)) {
2935
- console.log(
2936
- `[fullstack-cli] \u25CB ${path5.basename(dest)} (skipped, target not exists)`
2937
- );
2872
+ console.log(`[fullstack-cli] \u25CB ${path5.basename(dest)} (skipped, target not exists)`);
2938
2873
  return;
2939
2874
  }
2940
2875
  const destDir = path5.dirname(dest);
@@ -2942,9 +2877,7 @@ function syncFile(src, dest, overwrite = true, onlyIfExists = false) {
2942
2877
  fs7.mkdirSync(destDir, { recursive: true });
2943
2878
  }
2944
2879
  if (fs7.existsSync(dest) && !overwrite) {
2945
- console.log(
2946
- `[fullstack-cli] \u25CB ${path5.basename(dest)} (skipped, already exists)`
2947
- );
2880
+ console.log(`[fullstack-cli] \u25CB ${path5.basename(dest)} (skipped, already exists)`);
2948
2881
  return;
2949
2882
  }
2950
2883
  fs7.copyFileSync(src, dest);
@@ -2971,9 +2904,7 @@ function syncDirectory(src, dest, overwrite = true) {
2971
2904
  }
2972
2905
  });
2973
2906
  if (count > 0) {
2974
- console.log(
2975
- `[fullstack-cli] Synced ${count} files to ${path5.basename(dest)}/`
2976
- );
2907
+ console.log(`[fullstack-cli] Synced ${count} files to ${path5.basename(dest)}/`);
2977
2908
  }
2978
2909
  }
2979
2910
  function appendToFile(src, dest) {
@@ -2983,9 +2914,7 @@ function appendToFile(src, dest) {
2983
2914
  existingContent = fs7.readFileSync(dest, "utf-8");
2984
2915
  }
2985
2916
  if (existingContent.includes(content.trim())) {
2986
- console.log(
2987
- `[fullstack-cli] \u25CB ${path5.basename(dest)} (already contains content)`
2988
- );
2917
+ console.log(`[fullstack-cli] \u25CB ${path5.basename(dest)} (already contains content)`);
2989
2918
  return;
2990
2919
  }
2991
2920
  fs7.appendFileSync(dest, content);
@@ -3071,9 +3000,7 @@ function patchScript(packageJsonPath, name, to, ifStartsWith) {
3071
3000
  console.log(`[fullstack-cli] \u2713 Patched scripts.${name}`);
3072
3001
  } catch (error) {
3073
3002
  const message = error instanceof Error ? error.message : String(error);
3074
- console.warn(
3075
- `[fullstack-cli] \u26A0 Could not patch scripts.${name}: ${message}`
3076
- );
3003
+ console.warn(`[fullstack-cli] \u26A0 Could not patch scripts.${name}: ${message}`);
3077
3004
  }
3078
3005
  }
3079
3006
  function addLineToFile(filePath, line) {
@@ -3371,11 +3298,8 @@ function getCliVersion() {
3371
3298
  }
3372
3299
 
3373
3300
  // src/commands/upgrade/get-upgrade-files.ts
3374
- function getUpgradeFilesToStage(disableGenOpenapi = true, startupBundleEnrolled = false) {
3375
- const syncConfig = genSyncConfig(void 0, {
3376
- disableGenOpenapi,
3377
- startupBundleEnrolled
3378
- });
3301
+ function getUpgradeFilesToStage(disableGenOpenapi = true) {
3302
+ const syncConfig = genSyncConfig(void 0, { disableGenOpenapi });
3379
3303
  const filesToStage = /* @__PURE__ */ new Set();
3380
3304
  syncConfig.sync.forEach((rule) => {
3381
3305
  if (rule.type === "file" || rule.type === "directory" || rule.type === "merge-json") {
@@ -3409,15 +3333,10 @@ async function run3(options = {}) {
3409
3333
  if (shouldCommit) {
3410
3334
  console.log("[fullstack-cli] Step 3/3: Committing changes...");
3411
3335
  const version = getCliVersion();
3412
- const filesToStage = getUpgradeFilesToStage(
3413
- options.disableGenOpenapi ?? true,
3414
- hasStartupBundleEnrollment(readPackageJson(userProjectRoot))
3415
- );
3336
+ const filesToStage = getUpgradeFilesToStage(options.disableGenOpenapi ?? true);
3416
3337
  autoCommitUpgradeChanges(version, userProjectRoot, filesToStage);
3417
3338
  } else {
3418
- console.log(
3419
- "[fullstack-cli] Step 3/3: Skipping commit (--no-commit flag)"
3420
- );
3339
+ console.log("[fullstack-cli] Step 3/3: Skipping commit (--no-commit flag)");
3421
3340
  }
3422
3341
  console.log("[fullstack-cli] Upgrade completed successfully \u2705");
3423
3342
  } catch (error) {
@@ -8341,2489 +8260,23 @@ async function preUploadStatic(options) {
8341
8260
  }
8342
8261
  }
8343
8262
 
8344
- // src/commands/build/server-startup-bundle.handler.ts
8345
- import fs30 from "fs";
8346
- import http from "http";
8347
- import net from "net";
8348
- import os3 from "os";
8349
- import path26 from "path";
8350
- import { createRequire as createRequire4 } from "module";
8351
- import { spawn as spawn2 } from "child_process";
8352
- import { createHash, randomUUID } from "crypto";
8353
-
8354
- // src/commands/build/server-startup-static-bundle.ts
8355
- import fs29 from "fs";
8356
- import path25 from "path";
8357
- import { builtinModules, createRequire as createRequire3 } from "module";
8358
- import { fileURLToPath as fileURLToPath5, pathToFileURL } from "url";
8359
- import { build } from "esbuild";
8360
- import { parse } from "acorn";
8361
- import { simple as walkSimple } from "acorn-walk";
8362
- var ACTION_PLUGIN_LOADER_PACKAGE = "@lark-apaas/nestjs-capability";
8363
- var ENROLLMENT_SCHEMA_VERSION = 1;
8364
- var MAX_PACKAGE_JSON_BYTES = 1024 * 1024;
8365
- var BUILTINS = /* @__PURE__ */ new Set([
8366
- ...builtinModules,
8367
- ...builtinModules.map((name) => `node:${name}`)
8368
- ]);
8369
- function isInside(root, candidate) {
8370
- const relative = path25.relative(root, candidate);
8371
- return relative === "" || !relative.startsWith("..") && !path25.isAbsolute(relative);
8372
- }
8373
- function readBounded(file, maximum, description) {
8374
- if (!fs29.existsSync(file)) throw new Error(`${description} is unavailable`);
8375
- const stats = fs29.lstatSync(file);
8376
- if (stats.isSymbolicLink() || !stats.isFile() || stats.size > maximum) {
8377
- throw new Error(`${description} exceeds the supported metadata size`);
8378
- }
8379
- const contents = fs29.readFileSync(file);
8380
- if (contents.length !== stats.size) {
8381
- throw new Error(`${description} changed while reading`);
8382
- }
8383
- return contents;
8384
- }
8385
- function stringRecord(value) {
8386
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
8387
- return Object.fromEntries(
8388
- Object.entries(value).filter(
8389
- (entry) => typeof entry[1] === "string"
8390
- )
8391
- );
8392
- }
8393
- function packageNameIsValid(name) {
8394
- return /^(?:@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)$/i.test(
8395
- name
8396
- );
8397
- }
8398
- function findPackageRoot(projectRoot, entry) {
8399
- const nodeModulesRoot = path25.join(projectRoot, "node_modules");
8400
- let current = path25.dirname(entry);
8401
- while (isInside(nodeModulesRoot, current) && current !== nodeModulesRoot) {
8402
- const packageFile = path25.join(current, "package.json");
8403
- if (fs29.existsSync(packageFile) && fs29.statSync(packageFile).isFile()) {
8404
- return current;
8405
- }
8406
- current = path25.dirname(current);
8407
- }
8408
- return void 0;
8409
- }
8410
- function assertSafePackageRoot(projectRoot, packageRoot) {
8411
- const nodeModulesRoot = path25.join(projectRoot, "node_modules");
8412
- if (!isInside(nodeModulesRoot, packageRoot)) {
8413
- throw new Error(`package escaped project node_modules: ${packageRoot}`);
8414
- }
8415
- let current = projectRoot;
8416
- for (const segment of path25.relative(projectRoot, packageRoot).split(path25.sep)) {
8417
- if (!segment) continue;
8418
- current = path25.join(current, segment);
8419
- if (fs29.lstatSync(current).isSymbolicLink()) {
8420
- throw new Error(`package symlink is unsupported: ${packageRoot}`);
8421
- }
8422
- }
8423
- }
8424
- function resolveActionPlugins(projectRoot, configured) {
8425
- const projectRequire = createRequire3(path25.join(projectRoot, "package.json"));
8426
- return Object.entries(configured).sort(([left], [right]) => left.localeCompare(right)).map(([specifier, version]) => {
8427
- if (!packageNameIsValid(specifier) || !version) {
8428
- throw new Error(
8429
- `Action Plugin has an invalid configured version: ${specifier}`
8430
- );
8431
- }
8432
- let entry;
8433
- try {
8434
- entry = projectRequire.resolve(specifier);
8435
- } catch (error) {
8436
- throw new Error(
8437
- `Action Plugin cannot be statically resolved: ${specifier}: ${error instanceof Error ? error.message : String(error)}`
8438
- );
8439
- }
8440
- const packageRoot = findPackageRoot(projectRoot, entry);
8441
- if (!packageRoot) {
8442
- throw new Error(`Action Plugin package root not found: ${specifier}`);
8443
- }
8444
- assertSafePackageRoot(projectRoot, packageRoot);
8445
- const packageContents = readBounded(
8446
- path25.join(packageRoot, "package.json"),
8447
- MAX_PACKAGE_JSON_BYTES,
8448
- `Action Plugin package.json ${specifier}`
8449
- );
8450
- const packageJson = JSON.parse(packageContents.toString("utf8"));
8451
- if (packageJson.name !== specifier || packageJson.version !== version) {
8452
- throw new Error(
8453
- `Action Plugin identity mismatch: ${specifier}@${version}`
8454
- );
8455
- }
8456
- const manifestContents = readBounded(
8457
- path25.join(packageRoot, "manifest.json"),
8458
- MAX_PACKAGE_JSON_BYTES,
8459
- `Action Plugin manifest ${specifier}`
8460
- );
8461
- const manifest = JSON.parse(manifestContents.toString("utf8"));
8462
- if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) {
8463
- throw new Error(
8464
- `Action Plugin manifest must be an object: ${specifier}`
8465
- );
8466
- }
8467
- const manifestObject = manifest;
8468
- if (manifestObject.name !== void 0 && manifestObject.name !== specifier || manifestObject.version !== void 0 && manifestObject.version !== version) {
8469
- throw new Error(
8470
- `Action Plugin manifest identity mismatch: ${specifier}`
8471
- );
8472
- }
8473
- return {
8474
- specifier,
8475
- version,
8476
- entry,
8477
- packageRoot,
8478
- manifest: manifestObject
8479
- };
8480
- });
8481
- }
8482
- function readDependencyState(projectRoot) {
8483
- const packageFile = path25.join(projectRoot, "package.json");
8484
- const packageContents = readBounded(
8485
- packageFile,
8486
- MAX_PACKAGE_JSON_BYTES,
8487
- "package.json"
8488
- );
8489
- const packageJson = JSON.parse(packageContents.toString("utf8"));
8490
- if (!packageJson || typeof packageJson !== "object" || Array.isArray(packageJson)) {
8491
- throw new Error("package.json must contain an object");
8492
- }
8493
- const packageObject = packageJson;
8494
- const enrollment = packageObject.miaodaStartupBundle;
8495
- if (!enrollment || typeof enrollment !== "object" || Array.isArray(enrollment) || enrollment.schemaVersion !== ENROLLMENT_SCHEMA_VERSION) {
8496
- throw new Error(
8497
- `package.json miaodaStartupBundle.schemaVersion must be ${ENROLLMENT_SCHEMA_VERSION}`
8498
- );
8499
- }
8500
- const configuredPlugins = packageObject.actionPlugins;
8501
- if (configuredPlugins !== void 0 && (!configuredPlugins || typeof configuredPlugins !== "object" || Array.isArray(configuredPlugins))) {
8502
- throw new Error("package.json actionPlugins must be an object");
8503
- }
8504
- const actionPlugins = stringRecord(configuredPlugins);
8505
- if (configuredPlugins && Object.keys(actionPlugins).length !== Object.keys(configuredPlugins).length) {
8506
- throw new Error("package.json actionPlugins versions must be strings");
8507
- }
8508
- return {
8509
- plugins: resolveActionPlugins(projectRoot, actionPlugins)
8510
- };
8511
- }
8512
- function parseJavaScript(source) {
8513
- try {
8514
- return parse(source, {
8515
- ecmaVersion: "latest",
8516
- sourceType: "module",
8517
- allowHashBang: true
8263
+ // src/commands/build/index.ts
8264
+ var getTokenCommand = {
8265
+ name: "get-token",
8266
+ description: "Get artifact upload credential (STI token)",
8267
+ register(program) {
8268
+ program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").requiredOption("--scene <scene>", "Build scene (pipeline, static)").option("--commit-id <id>", "Git commit ID (required for pipeline scene)").action(async (options) => {
8269
+ await getToken(options);
8518
8270
  });
8519
- } catch {
8520
- try {
8521
- return parse(source, {
8522
- ecmaVersion: "latest",
8523
- sourceType: "script",
8524
- allowHashBang: true,
8525
- allowReturnOutsideFunction: true
8526
- });
8527
- } catch {
8528
- return void 0;
8529
- }
8530
- }
8531
- }
8532
- function staticPropertyName(node) {
8533
- if (node?.type !== "MemberExpression") return void 0;
8534
- if (!node.computed && node.property?.type === "Identifier") {
8535
- return node.property.name;
8536
- }
8537
- if (node.computed && node.property?.type === "Literal" && typeof node.property.value === "string") {
8538
- return node.property.value;
8539
- }
8540
- return void 0;
8541
- }
8542
- function staticString(node, bindings) {
8543
- if (!node) return void 0;
8544
- if (node.type === "Literal" && typeof node.value === "string")
8545
- return node.value;
8546
- if (node.type === "Identifier") return bindings.get(node.name);
8547
- if (node.type === "TemplateLiteral") {
8548
- let value = "";
8549
- for (let index = 0; index < node.quasis.length; index += 1) {
8550
- value += node.quasis[index]?.value?.cooked ?? "";
8551
- if (index < node.expressions.length) {
8552
- const expression = staticString(node.expressions[index], bindings);
8553
- if (expression === void 0) return void 0;
8554
- value += expression;
8555
- }
8556
- }
8557
- return value;
8558
- }
8559
- if (node.type === "BinaryExpression" && node.operator === "+") {
8560
- const left = staticString(node.left, bindings);
8561
- const right = staticString(node.right, bindings);
8562
- return left === void 0 || right === void 0 ? void 0 : left + right;
8563
- }
8564
- return void 0;
8565
- }
8566
- function recordBindingPattern(node, counts) {
8567
- if (!node) return;
8568
- if (node.type === "Identifier") {
8569
- counts.set(node.name, (counts.get(node.name) ?? 0) + 1);
8570
- return;
8571
- }
8572
- if (node.type === "RestElement") {
8573
- recordBindingPattern(node.argument, counts);
8574
- return;
8575
- }
8576
- if (node.type === "AssignmentPattern") {
8577
- recordBindingPattern(node.left, counts);
8578
- return;
8579
- }
8580
- if (node.type === "ArrayPattern") {
8581
- for (const element of node.elements ?? [])
8582
- recordBindingPattern(element, counts);
8583
- return;
8584
- }
8585
- if (node.type === "ObjectPattern") {
8586
- for (const property of node.properties ?? []) {
8587
- recordBindingPattern(
8588
- property.type === "RestElement" ? property.argument : property.value,
8589
- counts
8590
- );
8591
- }
8592
- }
8593
- }
8594
- function declaredBindingCounts(ast) {
8595
- const counts = /* @__PURE__ */ new Map();
8596
- walkSimple(ast, {
8597
- VariableDeclarator(node) {
8598
- recordBindingPattern(node.id, counts);
8599
- },
8600
- FunctionDeclaration(node) {
8601
- recordBindingPattern(node.id, counts);
8602
- for (const parameter of node.params ?? [])
8603
- recordBindingPattern(parameter, counts);
8604
- },
8605
- FunctionExpression(node) {
8606
- recordBindingPattern(node.id, counts);
8607
- for (const parameter of node.params ?? [])
8608
- recordBindingPattern(parameter, counts);
8609
- },
8610
- ArrowFunctionExpression(node) {
8611
- for (const parameter of node.params ?? [])
8612
- recordBindingPattern(parameter, counts);
8613
- },
8614
- ClassDeclaration(node) {
8615
- recordBindingPattern(node.id, counts);
8616
- },
8617
- ClassExpression(node) {
8618
- recordBindingPattern(node.id, counts);
8619
- },
8620
- ImportDeclaration(node) {
8621
- for (const specifier of node.specifiers ?? []) {
8622
- recordBindingPattern(specifier.local, counts);
8623
- }
8624
- },
8625
- CatchClause(node) {
8626
- recordBindingPattern(node.param, counts);
8627
- },
8628
- AssignmentExpression(node) {
8629
- recordBindingPattern(node.left, counts);
8630
- },
8631
- UpdateExpression(node) {
8632
- recordBindingPattern(node.argument, counts);
8633
- }
8634
- });
8635
- return counts;
8636
- }
8637
- function collectStaticBindings(ast, counts) {
8638
- const declarations = [];
8639
- for (const statement of ast.body ?? []) {
8640
- const declaration = statement.type === "VariableDeclaration" ? statement : statement.type === "ExportNamedDeclaration" && statement.declaration?.type === "VariableDeclaration" ? statement.declaration : void 0;
8641
- if (declaration?.kind !== "const") continue;
8642
- for (const item of declaration.declarations ?? []) {
8643
- if (item.id?.type === "Identifier" && item.init && counts.get(item.id.name) === 1) {
8644
- declarations.push({ name: item.id.name, value: item.init });
8645
- }
8646
- }
8647
- }
8648
- const bindings = /* @__PURE__ */ new Map();
8649
- for (let pass = 0; pass <= declarations.length; pass += 1) {
8650
- let changed = false;
8651
- for (const declaration of declarations) {
8652
- if (bindings.has(declaration.name)) continue;
8653
- const value = staticString(declaration.value, bindings);
8654
- if (value !== void 0) {
8655
- bindings.set(declaration.name, value);
8656
- changed = true;
8657
- }
8658
- }
8659
- if (!changed) break;
8660
- }
8661
- return bindings;
8662
- }
8663
- function runtimeBuiltinModule(specifier) {
8664
- if (typeof specifier !== "string") return void 0;
8665
- const normalized = specifier.startsWith("node:") ? specifier.slice("node:".length) : specifier;
8666
- return [
8667
- "child_process",
8668
- "fs",
8669
- "fs/promises",
8670
- "path",
8671
- "url",
8672
- "worker_threads"
8673
- ].includes(normalized) ? normalized : void 0;
8674
- }
8675
- function literalString(node) {
8676
- return node?.type === "Literal" && typeof node.value === "string" ? node.value : void 0;
8677
- }
8678
- function builtinRequire(node, bindingCounts) {
8679
- if (node?.type !== "CallExpression" || node.callee?.type !== "Identifier" || node.callee.name !== "require" || bindingCounts.has("require") || node.arguments.length !== 1) {
8680
- return void 0;
8681
- }
8682
- const module = runtimeBuiltinModule(literalString(node.arguments[0]));
8683
- return module ? { module, members: [] } : void 0;
8684
- }
8685
- function recordBuiltinPattern(pattern, origin, counts, bindings) {
8686
- if (!pattern) return;
8687
- if (pattern.type === "Identifier") {
8688
- if (counts.get(pattern.name) === 1) bindings.set(pattern.name, origin);
8689
- return;
8690
- }
8691
- if (pattern.type === "AssignmentPattern") {
8692
- recordBuiltinPattern(pattern.left, origin, counts, bindings);
8693
- return;
8694
- }
8695
- if (pattern.type !== "ObjectPattern") return;
8696
- for (const property of pattern.properties ?? []) {
8697
- if (property.type !== "Property") continue;
8698
- const member = property.key?.type === "Identifier" ? property.key.name : literalString(property.key);
8699
- if (!member) continue;
8700
- recordBuiltinPattern(
8701
- property.value,
8702
- { module: origin.module, members: [...origin.members, member] },
8703
- counts,
8704
- bindings
8705
- );
8706
- }
8707
- }
8708
- function collectBuiltinBindings(ast, counts) {
8709
- const bindings = /* @__PURE__ */ new Map();
8710
- for (const statement of ast.body ?? []) {
8711
- if (statement.type === "ImportDeclaration") {
8712
- const module = runtimeBuiltinModule(literalString(statement.source));
8713
- if (!module) continue;
8714
- for (const specifier of statement.specifiers ?? []) {
8715
- if (specifier.local?.type !== "Identifier") continue;
8716
- const origin = specifier.type === "ImportSpecifier" ? {
8717
- module,
8718
- members: [
8719
- specifier.imported?.type === "Identifier" ? specifier.imported.name : literalString(specifier.imported) ?? ""
8720
- ]
8721
- } : { module, members: [] };
8722
- if (origin.members.every(Boolean) && counts.get(specifier.local.name) === 1) {
8723
- bindings.set(specifier.local.name, origin);
8724
- }
8725
- }
8726
- continue;
8727
- }
8728
- const declaration = statement.type === "VariableDeclaration" ? statement : statement.type === "ExportNamedDeclaration" && statement.declaration?.type === "VariableDeclaration" ? statement.declaration : void 0;
8729
- if (!declaration) continue;
8730
- for (const item of declaration.declarations ?? []) {
8731
- let origin = builtinRequire(item.init, counts);
8732
- if (!origin && item.init?.type === "MemberExpression" && staticPropertyName(item.init)) {
8733
- const required = builtinRequire(item.init.object, counts);
8734
- if (required) {
8735
- origin = {
8736
- module: required.module,
8737
- members: [...required.members, staticPropertyName(item.init)]
8738
- };
8739
- }
8740
- }
8741
- if (origin) recordBuiltinPattern(item.id, origin, counts, bindings);
8742
- }
8743
- }
8744
- return bindings;
8745
- }
8746
- function analyzeSource(ast) {
8747
- const bindingCounts = declaredBindingCounts(ast);
8748
- return {
8749
- bindingCounts,
8750
- builtinBindings: collectBuiltinBindings(ast, bindingCounts),
8751
- strings: collectStaticBindings(ast, bindingCounts)
8752
- };
8753
- }
8754
- function unwrapZeroSequence(node) {
8755
- if (node?.type === "SequenceExpression" && node.expressions.length === 2 && node.expressions[0]?.type === "Literal" && node.expressions[0].value === 0) {
8756
- return node.expressions[1];
8757
- }
8758
- return node;
8759
- }
8760
- function builtinReference(node, analysis) {
8761
- const target = unwrapZeroSequence(node);
8762
- if (!target) return void 0;
8763
- if (target.type === "Identifier") {
8764
- return analysis.builtinBindings.get(target.name);
8765
- }
8766
- if (target.type !== "MemberExpression")
8767
- return builtinRequire(target, analysis.bindingCounts);
8768
- const member = staticPropertyName(target);
8769
- if (!member) return void 0;
8770
- const parent = builtinReference(target.object, analysis);
8771
- return parent ? { module: parent.module, members: [...parent.members, member] } : void 0;
8772
- }
8773
- function builtinMethod(node, analysis, module) {
8774
- const reference = builtinReference(node, analysis);
8775
- if (!reference || reference.module !== module) return void 0;
8776
- return reference.members.length === 1 ? reference.members[0] : void 0;
8777
- }
8778
- function fsMethod(node, analysis) {
8779
- const reference = builtinReference(node, analysis);
8780
- if (!reference) return void 0;
8781
- if (reference.module === "fs/promises" && reference.members.length === 1) {
8782
- return reference.members[0];
8783
- }
8784
- if (reference.module !== "fs") return void 0;
8785
- if (reference.members.length === 1) return reference.members[0];
8786
- return reference.members.length === 2 && reference.members[0] === "promises" ? reference.members[1] : void 0;
8787
- }
8788
- function isDirectRequire(node, analysis) {
8789
- return isUnshadowedIdentifier(node, "require", analysis);
8790
- }
8791
- function isRequireResolve(node, analysis) {
8792
- return node?.type === "MemberExpression" && staticPropertyName(node) === "resolve" && isDirectRequire(node.object, analysis);
8793
- }
8794
- function isLayoutHelperCall(node, analysis) {
8795
- const pathMethod = builtinMethod(node, analysis, "path");
8796
- const urlMethod = builtinMethod(node, analysis, "url");
8797
- return pathMethod === "dirname" || pathMethod === "join" || pathMethod === "resolve" || urlMethod === "fileURLToPath";
8798
- }
8799
- function staticModuleReference(sourceFile, node, analysis) {
8800
- const specifier = staticString(node, analysis.strings);
8801
- if (specifier !== void 0) return specifier;
8802
- if (isUrlObjectExpression(node, analysis) && isImportMetaUrl(node?.arguments[1])) {
8803
- const relative = staticString(node.arguments[0], analysis.strings);
8804
- if (relative !== void 0) {
8805
- const moduleUrl = new URL(relative, pathToFileURL(sourceFile));
8806
- if (moduleUrl.search || moduleUrl.hash) {
8807
- throw new Error(
8808
- `module URL search or hash is unsupported in a static startup bundle: ${sourceFile}`
8809
- );
8810
- }
8811
- }
8812
- }
8813
- const layout = evaluateLayoutPath(sourceFile, node, analysis);
8814
- return layout?.kind === "static" && layout.anchor === "directory" ? layout.value : void 0;
8815
- }
8816
- function isUrlObjectExpression(node, analysis) {
8817
- return Boolean(
8818
- node?.type === "NewExpression" && (isUnshadowedIdentifier(node.callee, "URL", analysis) || builtinMethod(node.callee, analysis, "url") === "URL")
8819
- );
8820
- }
8821
- function staticModuleReferencePlugin() {
8822
- return {
8823
- name: "miaoda-static-module-references",
8824
- setup(esbuild) {
8825
- esbuild.onLoad({ filter: /\.(?:cjs|mjs|js)$/ }, (args) => {
8826
- const source = fs29.readFileSync(args.path, "utf8");
8827
- const ast = parseJavaScript(source);
8828
- if (!ast) return void 0;
8829
- const analysis = analyzeSource(ast);
8830
- const replacements = [];
8831
- const rewriteCode = (node, value) => {
8832
- if (!node) return;
8833
- replacements.push({
8834
- start: node.start,
8835
- end: node.end,
8836
- value
8837
- });
8838
- };
8839
- const rewriteString = (node, value) => {
8840
- if (node?.type === "Literal" && node.value === value) return;
8841
- rewriteCode(node, JSON.stringify(value));
8842
- };
8843
- walkSimple(ast, {
8844
- CallExpression(node) {
8845
- const directRequire = isDirectRequire(node.callee, analysis);
8846
- const requireResolve = isRequireResolve(node.callee, analysis);
8847
- if (directRequire || requireResolve) {
8848
- const argument2 = node.arguments[0];
8849
- if (directRequire && isUrlObjectExpression(argument2, analysis)) {
8850
- throw new Error(
8851
- `require(URL) is unsupported in a static startup bundle: ${args.path}`
8852
- );
8853
- }
8854
- const specifier = staticModuleReference(
8855
- args.path,
8856
- argument2,
8857
- analysis
8858
- );
8859
- if (specifier === void 0) return;
8860
- if (requireResolve) {
8861
- throw new Error(
8862
- `require.resolve is unsupported in a static startup bundle: ${args.path}`
8863
- );
8864
- }
8865
- rewriteString(argument2, specifier);
8866
- return;
8867
- }
8868
- const method = fsMethod(node.callee, analysis);
8869
- if (!method || !COPYABLE_FS_METHODS.has(method) || !readOptionsAreSafe(method, node, analysis) || !canRewritePayloadPath(analysis)) {
8870
- return;
8871
- }
8872
- const argument = node.arguments[0];
8873
- const layout = classifyLayoutPath(args.path, argument, analysis);
8874
- if (layout.kind !== "static") return;
8875
- rewriteCode(
8876
- argument,
8877
- `require("node:path").join(__dirname, ${JSON.stringify(
8878
- layout.asset.destination
8879
- )})`
8880
- );
8881
- },
8882
- ImportExpression(node) {
8883
- const specifier = staticModuleReference(
8884
- args.path,
8885
- node.source,
8886
- analysis
8887
- );
8888
- if (specifier !== void 0) rewriteString(node.source, specifier);
8889
- }
8890
- });
8891
- if (replacements.length === 0) return void 0;
8892
- let contents = source;
8893
- for (const replacement of replacements.sort(
8894
- (left, right) => right.start - left.start
8895
- )) {
8896
- contents = contents.slice(0, replacement.start) + replacement.value + contents.slice(replacement.end);
8897
- }
8898
- return { contents, loader: "js", resolveDir: path25.dirname(args.path) };
8899
- });
8900
- }
8901
- };
8902
- }
8903
- function isImportMetaUrl(node) {
8904
- return Boolean(
8905
- node?.type === "MemberExpression" && staticPropertyName(node) === "url" && node.object?.type === "MetaProperty" && node.object.meta?.name === "import" && node.object.property?.name === "meta"
8906
- );
8907
- }
8908
- function isUnshadowedIdentifier(node, name, analysis) {
8909
- return node?.type === "Identifier" && node.name === name && !analysis.bindingCounts.has(name);
8910
- }
8911
- function containsRawLayoutPrimitive(node) {
8912
- if (!node) return false;
8913
- if (node.type === "Identifier" && (node.name === "__dirname" || node.name === "__filename") || isImportMetaUrl(node)) {
8914
- return true;
8915
- }
8916
- if (node.type === "BinaryExpression" || node.type === "LogicalExpression") {
8917
- return containsRawLayoutPrimitive(node.left) || containsRawLayoutPrimitive(node.right);
8918
- }
8919
- if (node.type === "ConditionalExpression") {
8920
- return containsRawLayoutPrimitive(node.test) || containsRawLayoutPrimitive(node.consequent) || containsRawLayoutPrimitive(node.alternate);
8921
- }
8922
- if (node.type === "TemplateLiteral") {
8923
- return node.expressions.some(containsRawLayoutPrimitive);
8924
- }
8925
- if (node.type === "MemberExpression") {
8926
- return containsRawLayoutPrimitive(node.object) || node.computed && containsRawLayoutPrimitive(node.property);
8927
- }
8928
- if (node.type === "CallExpression" || node.type === "NewExpression") {
8929
- return containsRawLayoutPrimitive(node.callee) || node.arguments.some(containsRawLayoutPrimitive);
8930
- }
8931
- if (node.type === "ChainExpression") {
8932
- return containsRawLayoutPrimitive(node.expression);
8933
- }
8934
- return false;
8935
- }
8936
- function canRewritePayloadPath(analysis) {
8937
- return !analysis.bindingCounts.has("require") && !analysis.bindingCounts.has("__dirname");
8938
- }
8939
- function canonicalAssetPath(value) {
8940
- const normalized = value.split(path25.sep).join("/").replace(/^\.\//, "");
8941
- if (!normalized || normalized === "." || normalized !== path25.posix.normalize(normalized) || normalized.startsWith("../") || path25.posix.isAbsolute(normalized) || normalized.includes("\\")) {
8942
- return void 0;
8943
- }
8944
- return normalized;
8945
- }
8946
- function evaluateLayoutPath(sourceFile, node, analysis) {
8947
- if (!node) return void 0;
8948
- if (isUnshadowedIdentifier(node, "__dirname", analysis)) {
8949
- return {
8950
- kind: "static",
8951
- value: path25.dirname(sourceFile),
8952
- anchor: "directory"
8953
- };
8954
- }
8955
- if (isUnshadowedIdentifier(node, "__filename", analysis) || isImportMetaUrl(node)) {
8956
- return { kind: "static", value: sourceFile, anchor: "file" };
8957
- }
8958
- if (node.type === "NewExpression" && (isUnshadowedIdentifier(node.callee, "URL", analysis) || builtinMethod(node.callee, analysis, "url") === "URL") && isImportMetaUrl(node.arguments[1])) {
8959
- const relative = staticString(node.arguments[0], analysis.strings);
8960
- if (relative === void 0) return { kind: "dynamic" };
8961
- try {
8962
- const value = fileURLToPath5(new URL(relative, pathToFileURL(sourceFile)));
8963
- return {
8964
- kind: "static",
8965
- value,
8966
- anchor: path25.resolve(value) === path25.resolve(sourceFile) ? "file" : "directory"
8967
- };
8968
- } catch {
8969
- throw new Error(`static runtime URL is unsupported: ${sourceFile}`);
8970
- }
8971
- }
8972
- if (node.type === "BinaryExpression" && node.operator === "+") {
8973
- const leftLayout = evaluateLayoutPath(sourceFile, node.left, analysis);
8974
- const rightLayout = evaluateLayoutPath(sourceFile, node.right, analysis);
8975
- if (leftLayout?.kind === "dynamic" || rightLayout?.kind === "dynamic") {
8976
- return { kind: "dynamic" };
8977
- }
8978
- if (!leftLayout && !rightLayout) return void 0;
8979
- const left = leftLayout?.value ?? staticString(node.left, analysis.strings);
8980
- const right = rightLayout?.value ?? staticString(node.right, analysis.strings);
8981
- if (left === void 0 || right === void 0) {
8982
- return { kind: "dynamic" };
8983
- }
8984
- return {
8985
- kind: "static",
8986
- value: left + right,
8987
- anchor: leftLayout?.anchor === "file" || rightLayout?.anchor === "file" ? "file" : "directory"
8988
- };
8989
- }
8990
- if (node.type === "TemplateLiteral") {
8991
- let value = node.quasis[0]?.value?.cooked ?? "";
8992
- let hasLayout = false;
8993
- let anchor = "directory";
8994
- let dynamic = false;
8995
- for (let index = 0; index < node.expressions.length; index += 1) {
8996
- const expression = node.expressions[index];
8997
- const layout = evaluateLayoutPath(sourceFile, expression, analysis);
8998
- if (layout?.kind === "dynamic") {
8999
- dynamic = true;
9000
- } else if (layout) {
9001
- hasLayout = true;
9002
- if (layout.anchor === "file") anchor = "file";
9003
- value += layout.value;
9004
- } else {
9005
- const plain = staticString(expression, analysis.strings);
9006
- if (plain === void 0) dynamic = true;
9007
- else value += plain;
9008
- }
9009
- value += node.quasis[index + 1]?.value?.cooked ?? "";
9010
- }
9011
- if (!hasLayout) return void 0;
9012
- return dynamic ? { kind: "dynamic" } : { kind: "static", value, anchor };
9013
- }
9014
- if (node.type !== "CallExpression") {
9015
- return void 0;
9016
- }
9017
- const urlMethod = builtinMethod(node.callee, analysis, "url");
9018
- if (urlMethod === "fileURLToPath") {
9019
- return evaluateLayoutPath(sourceFile, node.arguments[0], analysis);
9020
- }
9021
- const pathMethod = builtinMethod(node.callee, analysis, "path");
9022
- if (pathMethod === "dirname") {
9023
- const target = evaluateLayoutPath(sourceFile, node.arguments[0], analysis);
9024
- if (!target || target.kind === "dynamic") return target;
9025
- return {
9026
- kind: "static",
9027
- value: path25.dirname(target.value),
9028
- anchor: "directory"
9029
- };
9030
- }
9031
- if (pathMethod === "join" || pathMethod === "resolve") {
9032
- const values = [];
9033
- let hasLayout = false;
9034
- let anchor = "directory";
9035
- let hasUnknownSegment = false;
9036
- for (const argument of node.arguments) {
9037
- const layout = evaluateLayoutPath(sourceFile, argument, analysis);
9038
- if (layout?.kind === "dynamic") return layout;
9039
- if (layout) {
9040
- hasLayout = true;
9041
- if (layout.anchor === "file") anchor = "file";
9042
- values.push(layout.value);
9043
- continue;
9044
- }
9045
- const value = staticString(argument, analysis.strings);
9046
- if (value === void 0) {
9047
- hasUnknownSegment = true;
9048
- continue;
9049
- }
9050
- values.push(value);
9051
- }
9052
- if (!hasLayout) return void 0;
9053
- if (hasUnknownSegment) return { kind: "dynamic" };
9054
- return {
9055
- kind: "static",
9056
- value: pathMethod === "resolve" ? path25.resolve(...values) : path25.join(...values),
9057
- anchor
9058
- };
9059
8271
  }
9060
- return node.arguments.some(
9061
- (argument) => evaluateLayoutPath(sourceFile, argument, analysis) !== void 0
9062
- ) ? { kind: "dynamic" } : void 0;
9063
- }
9064
- function classifyLayoutPath(sourceFile, node, analysis) {
9065
- const evaluated = evaluateLayoutPath(sourceFile, node, analysis);
9066
- if (!evaluated) {
9067
- return containsRawLayoutPrimitive(node) ? { kind: "unsafe" } : { kind: "none" };
9068
- }
9069
- if (evaluated.kind === "dynamic" || evaluated.anchor === "file") {
9070
- return { kind: "unsafe" };
9071
- }
9072
- const sourceDirectory = path25.dirname(sourceFile);
9073
- const relative = path25.relative(sourceDirectory, evaluated.value);
9074
- const destination = canonicalAssetPath(relative);
9075
- if (!destination) {
9076
- throw new Error(
9077
- `static runtime asset must be a strict descendant: ${sourceFile}`
9078
- );
9079
- }
9080
- return {
9081
- kind: "static",
9082
- asset: { source: evaluated.value, destination }
9083
- };
9084
- }
9085
- var COPYABLE_FS_METHODS = /* @__PURE__ */ new Set([
9086
- "readFile",
9087
- "readFileSync",
9088
- "createReadStream",
9089
- "readdir",
9090
- "readdirSync",
9091
- "opendir",
9092
- "opendirSync",
9093
- "exists",
9094
- "existsSync"
9095
- ]);
9096
- var NON_COPYABLE_FS_METHODS = /* @__PURE__ */ new Set([
9097
- "access",
9098
- "accessSync",
9099
- "appendFile",
9100
- "appendFileSync",
9101
- "chmod",
9102
- "chmodSync",
9103
- "chown",
9104
- "chownSync",
9105
- "copyFile",
9106
- "copyFileSync",
9107
- "cp",
9108
- "cpSync",
9109
- "createWriteStream",
9110
- "glob",
9111
- "globSync",
9112
- "link",
9113
- "linkSync",
9114
- "lstat",
9115
- "lstatSync",
9116
- "mkdir",
9117
- "mkdirSync",
9118
- "open",
9119
- "openSync",
9120
- "readlink",
9121
- "readlinkSync",
9122
- "realpath",
9123
- "realpathSync",
9124
- "rename",
9125
- "renameSync",
9126
- "rm",
9127
- "rmSync",
9128
- "rmdir",
9129
- "rmdirSync",
9130
- "stat",
9131
- "statSync",
9132
- "statfs",
9133
- "statfsSync",
9134
- "symlink",
9135
- "symlinkSync",
9136
- "truncate",
9137
- "truncateSync",
9138
- "unlink",
9139
- "unlinkSync",
9140
- "unwatchFile",
9141
- "utimes",
9142
- "utimesSync",
9143
- "watch",
9144
- "watchFile",
9145
- "writeFile",
9146
- "writeFileSync"
9147
- ]);
9148
- function isFsPathMethod(method) {
9149
- return Boolean(
9150
- method && (COPYABLE_FS_METHODS.has(method) || NON_COPYABLE_FS_METHODS.has(method))
9151
- );
9152
- }
9153
- function readOptionsAreSafe(method, call, analysis) {
9154
- if (!["readFile", "readFileSync", "createReadStream"].includes(method)) {
9155
- return true;
9156
- }
9157
- const options = call.arguments[1];
9158
- if (!options) return true;
9159
- if (method === "readFile" && ["ArrowFunctionExpression", "FunctionExpression"].includes(options.type)) {
9160
- return true;
9161
- }
9162
- if (options.type === "Identifier" && options.name === "undefined" && !analysis.bindingCounts.has("undefined")) {
9163
- return true;
9164
- }
9165
- if (options.type === "Literal") {
9166
- return options.value === null || typeof options.value === "string";
9167
- }
9168
- if (options.type !== "ObjectExpression") return false;
9169
- const accessFlagKey = method === "createReadStream" ? "flags" : "flag";
9170
- for (const property of options.properties ?? []) {
9171
- if (property.type !== "Property" || property.kind !== "init") return false;
9172
- const key = !property.computed && property.key?.type === "Identifier" ? property.key.name : literalString(property.key);
9173
- if (!key) return false;
9174
- const stringValue = staticString(property.value, analysis.strings);
9175
- const literalValue = property.value?.type === "Literal" && (property.value.value === null || ["boolean", "number", "string"].includes(typeof property.value.value));
9176
- if (key === accessFlagKey) {
9177
- if (stringValue !== "r" && stringValue !== "rs") return false;
9178
- } else if (stringValue === void 0 && !literalValue) {
9179
- return false;
9180
- }
9181
- }
9182
- return true;
9183
- }
9184
- function reserveAssetBudget(file, size, budget, limits) {
9185
- if (size > limits.maxFileBytes) {
9186
- throw new Error(`generation file exceeds 64 MiB: ${file}`);
9187
- }
9188
- if (budget.fileCount + 1 > limits.maxFiles) {
9189
- throw new Error(`generation exceeds ${limits.maxFiles} files`);
9190
- }
9191
- if (budget.totalBytes + size > limits.maxTotalBytes) {
9192
- throw new Error("generation exceeds 256 MiB");
9193
- }
9194
- budget.fileCount += 1;
9195
- budget.totalBytes += size;
9196
- }
9197
- function assertSafeAssetPath(projectRoot, source) {
9198
- if (!isInside(projectRoot, source)) {
9199
- throw new Error(`static runtime asset escaped project: ${source}`);
9200
- }
9201
- let current = projectRoot;
9202
- for (const segment of path25.relative(projectRoot, source).split(path25.sep)) {
9203
- if (!segment) continue;
9204
- current = path25.join(current, segment);
9205
- if (fs29.lstatSync(current).isSymbolicLink()) {
9206
- throw new Error(`static runtime asset symlink is unsupported: ${source}`);
9207
- }
9208
- }
9209
- }
9210
- function normalizeAssetCandidates(candidates) {
9211
- const byDestination = /* @__PURE__ */ new Map();
9212
- for (const candidate of candidates) {
9213
- const source = path25.resolve(candidate.source);
9214
- const previous = byDestination.get(candidate.destination);
9215
- if (previous && previous !== source) {
9216
- throw new Error(
9217
- `static runtime asset collision: ${candidate.destination}`
9218
- );
9219
- }
9220
- byDestination.set(candidate.destination, source);
9221
- }
9222
- const normalized = [...byDestination].map(([destination, source]) => ({
9223
- destination,
9224
- source
9225
- }));
9226
- normalized.sort((left, right) => {
9227
- const depth = left.destination.split("/").length - right.destination.split("/").length;
9228
- return depth || left.destination.localeCompare(right.destination);
9229
- });
9230
- const accepted = /* @__PURE__ */ new Map();
9231
- for (const candidate of normalized) {
9232
- const segments = candidate.destination.split("/");
9233
- for (let length = segments.length - 1; length > 0; length -= 1) {
9234
- const ancestor = segments.slice(0, length).join("/");
9235
- const ancestorSource = accepted.get(ancestor);
9236
- if (!ancestorSource) continue;
9237
- const expected = path25.resolve(ancestorSource, ...segments.slice(length));
9238
- if (expected !== candidate.source) {
9239
- throw new Error(
9240
- `static runtime asset tree collision: ${candidate.destination}`
9241
- );
9242
- }
9243
- break;
9244
- }
9245
- accepted.set(candidate.destination, candidate.source);
9246
- }
9247
- return normalized;
9248
- }
9249
- function seedPayloadBudget(payloadRoot, limits, budget) {
9250
- const files = /* @__PURE__ */ new Set();
9251
- const visit = (current) => {
9252
- for (const entry of fs29.readdirSync(current, { withFileTypes: true })) {
9253
- const target = path25.join(current, entry.name);
9254
- if (entry.isSymbolicLink()) {
9255
- throw new Error(`generation symlink is unsupported: ${target}`);
9256
- }
9257
- if (entry.isDirectory()) {
9258
- visit(target);
9259
- continue;
9260
- }
9261
- if (!entry.isFile()) {
9262
- throw new Error(`generation special file is unsupported: ${target}`);
9263
- }
9264
- const stats = fs29.lstatSync(target);
9265
- if (!stats.isFile()) {
9266
- throw new Error(`generation special file is unsupported: ${target}`);
9267
- }
9268
- reserveAssetBudget(target, stats.size, budget, limits);
9269
- files.add(path25.relative(payloadRoot, target).split(path25.sep).join("/"));
9270
- }
9271
- };
9272
- visit(payloadRoot);
9273
- return files;
9274
- }
9275
- function planAssetFiles(projectRoot, candidates, reserved, limits, budget) {
9276
- const planned = /* @__PURE__ */ new Map();
9277
- const visit = (source, destination) => {
9278
- if (!fs29.existsSync(source)) {
9279
- throw new Error(`static runtime asset is unavailable: ${source}`);
9280
- }
9281
- assertSafeAssetPath(projectRoot, source);
9282
- const reservedCollision = [...reserved].find(
9283
- (item) => item === destination || item.startsWith(`${destination}/`) || destination.startsWith(`${item}/`)
9284
- );
9285
- if (reservedCollision) {
9286
- throw new Error(
9287
- `static runtime asset collides with bundle output: ${reservedCollision}`
9288
- );
9289
- }
9290
- const stats = fs29.lstatSync(source);
9291
- if (stats.isDirectory()) {
9292
- const entries = fs29.readdirSync(source).sort();
9293
- if (entries.length === 0) {
9294
- throw new Error(
9295
- `static runtime asset empty directory is unsupported: ${source}`
9296
- );
9297
- }
9298
- for (const entry of entries) {
9299
- visit(path25.join(source, entry), path25.posix.join(destination, entry));
9300
- }
9301
- return;
9302
- }
9303
- if (!stats.isFile()) {
9304
- throw new Error(`static runtime asset type is unsupported: ${source}`);
9305
- }
9306
- const previous = planned.get(destination);
9307
- if (previous && previous.source !== source) {
9308
- throw new Error(`static runtime asset collision: ${destination}`);
9309
- }
9310
- if (previous) return;
9311
- reserveAssetBudget(source, stats.size, budget, limits);
9312
- planned.set(destination, {
9313
- destination,
9314
- mode: stats.mode & 73 ? 493 : 420,
9315
- size: stats.size,
9316
- source
9317
- });
9318
- };
9319
- for (const candidate of candidates) {
9320
- visit(candidate.source, candidate.destination);
9321
- }
9322
- return [...planned.values()].sort(
9323
- (left, right) => left.destination.localeCompare(right.destination)
9324
- );
9325
- }
9326
- function copyPlannedAssets(projectRoot, assets, destinationRoot) {
9327
- for (const asset of assets) {
9328
- assertSafeAssetPath(projectRoot, asset.source);
9329
- const stats = fs29.lstatSync(asset.source);
9330
- if (stats.isSymbolicLink() || !stats.isFile() || stats.size !== asset.size) {
9331
- throw new Error(
9332
- `static runtime asset changed before copy: ${asset.source}`
9333
- );
9334
- }
9335
- const contents = fs29.readFileSync(asset.source);
9336
- if (contents.length !== asset.size) {
9337
- throw new Error(
9338
- `static runtime asset changed while reading: ${asset.source}`
9339
- );
9340
- }
9341
- const target = path25.join(destinationRoot, ...asset.destination.split("/"));
9342
- fs29.mkdirSync(path25.dirname(target), { recursive: true });
9343
- fs29.writeFileSync(target, contents, { mode: asset.mode });
9344
- }
9345
- }
9346
- function materializeStaticAssets(projectRoot, metafile, payloadRoot, limits) {
9347
- const budget = { fileCount: 0, totalBytes: 0 };
9348
- const reserved = seedPayloadBudget(payloadRoot, limits, budget);
9349
- const candidates = [];
9350
- for (const input of Object.keys(metafile.inputs).sort()) {
9351
- if (!/\.(?:cjs|mjs|js)$/.test(input)) continue;
9352
- const sourceFile = path25.isAbsolute(input) ? input : path25.resolve(projectRoot, input);
9353
- if (!fs29.existsSync(sourceFile) || !fs29.statSync(sourceFile).isFile())
9354
- continue;
9355
- const source = fs29.readFileSync(sourceFile, "utf8");
9356
- const ast = parseJavaScript(source);
9357
- if (!ast) continue;
9358
- const analysis = analyzeSource(ast);
9359
- const classify = (node) => classifyLayoutPath(sourceFile, node, analysis);
9360
- walkSimple(ast, {
9361
- CallExpression(node) {
9362
- const method = fsMethod(node.callee, analysis);
9363
- const forkMethod = builtinMethod(
9364
- node.callee,
9365
- analysis,
9366
- "child_process"
9367
- );
9368
- if (forkMethod === "fork") {
9369
- const target = node.arguments[0];
9370
- const layout = classify(target);
9371
- if (staticString(target, analysis.strings) !== void 0 || layout.kind === "static") {
9372
- throw new Error(
9373
- `static child runtime entry is unsupported: ${sourceFile}`
9374
- );
9375
- }
9376
- if (layout.kind === "unsafe") {
9377
- throw new Error(
9378
- `child runtime entry has an unknown bundle-relative path: ${sourceFile}`
9379
- );
9380
- }
9381
- return;
9382
- }
9383
- if (method && COPYABLE_FS_METHODS.has(method)) {
9384
- const layout = classify(node.arguments[0]);
9385
- if (layout.kind === "none") return;
9386
- if (layout.kind === "unsafe") {
9387
- throw new Error(
9388
- `runtime asset has an unknown bundle-relative path: ${sourceFile}`
9389
- );
9390
- }
9391
- if (!readOptionsAreSafe(method, node, analysis)) {
9392
- throw new Error(
9393
- `runtime filesystem read options are not statically read-only: ${sourceFile}`
9394
- );
9395
- }
9396
- if (!canRewritePayloadPath(analysis)) {
9397
- throw new Error(
9398
- `runtime asset path cannot be rewritten without capturing a local binding: ${sourceFile}`
9399
- );
9400
- }
9401
- candidates.push(layout.asset);
9402
- return;
9403
- }
9404
- if (method && NON_COPYABLE_FS_METHODS.has(method)) {
9405
- if (node.arguments.some((argument) => classify(argument).kind !== "none")) {
9406
- throw new Error(
9407
- `runtime filesystem operation cannot preserve a bundle-relative path: ${sourceFile}`
9408
- );
9409
- }
9410
- return;
9411
- }
9412
- if (isDirectRequire(node.callee, analysis) || isRequireResolve(node.callee, analysis) || isLayoutHelperCall(node.callee, analysis)) {
9413
- return;
9414
- }
9415
- if (node.arguments.some((argument) => classify(argument).kind !== "none")) {
9416
- throw new Error(
9417
- `unknown runtime call observes a bundle-relative path: ${sourceFile}`
9418
- );
9419
- }
9420
- },
9421
- NewExpression(node) {
9422
- const workerMethod = builtinMethod(
9423
- node.callee,
9424
- analysis,
9425
- "worker_threads"
9426
- );
9427
- const isWorker = workerMethod === "Worker";
9428
- const isSharedWorker = isUnshadowedIdentifier(
9429
- node.callee,
9430
- "SharedWorker",
9431
- analysis
9432
- );
9433
- const isUrl = isUnshadowedIdentifier(node.callee, "URL", analysis) || builtinMethod(node.callee, analysis, "url") === "URL";
9434
- if (isUrl) return;
9435
- if (!isWorker && !isSharedWorker) {
9436
- if (node.arguments.some((argument) => classify(argument).kind !== "none")) {
9437
- throw new Error(
9438
- `unknown runtime constructor observes a bundle-relative path: ${sourceFile}`
9439
- );
9440
- }
9441
- return;
9442
- }
9443
- const options = node.arguments[1];
9444
- const evaluatesSource = Boolean(
9445
- isWorker && options?.type === "ObjectExpression" && options.properties?.some(
9446
- (property) => property.type === "Property" && (property.key?.type === "Identifier" && property.key.name === "eval" || property.key?.type === "Literal" && property.key.value === "eval") && property.value?.type === "Literal" && property.value.value === true
9447
- )
9448
- );
9449
- if (evaluatesSource) return;
9450
- const target = node.arguments[0];
9451
- const layout = classify(target);
9452
- if (staticString(target, analysis.strings) !== void 0 || layout.kind === "static") {
9453
- throw new Error(
9454
- `static child runtime entry is unsupported: ${sourceFile}`
9455
- );
9456
- }
9457
- if (layout.kind === "unsafe") {
9458
- throw new Error(
9459
- `child runtime entry has an unknown bundle-relative path: ${sourceFile}`
9460
- );
9461
- }
9462
- }
9463
- });
9464
- }
9465
- const normalized = normalizeAssetCandidates(candidates);
9466
- const assets = planAssetFiles(
9467
- projectRoot,
9468
- normalized,
9469
- reserved,
9470
- limits,
9471
- budget
9472
- );
9473
- copyPlannedAssets(projectRoot, assets, payloadRoot);
9474
- }
9475
- function isBareSpecifier(specifier) {
9476
- return !specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.startsWith("file:");
9477
- }
9478
- function expressionSignalsRelativeSpecifier(node, analysis) {
9479
- const known = staticString(node, analysis.strings);
9480
- if (known !== void 0)
9481
- return known.startsWith(".") || known.startsWith("/");
9482
- if (node?.type === "TemplateLiteral") {
9483
- return (node.quasis[0]?.value?.cooked ?? "").startsWith(".");
9484
- }
9485
- if (node?.type === "BinaryExpression" && node.operator === "+") {
9486
- return expressionSignalsRelativeSpecifier(node.left, analysis) || expressionSignalsRelativeSpecifier(node.right, analysis);
9487
- }
9488
- if (node?.type === "CallExpression" && builtinMethod(node.callee, analysis, "path") === "join") {
9489
- const prefix = [];
9490
- for (const argument of node.arguments) {
9491
- const value = staticString(argument, analysis.strings);
9492
- if (value === void 0) break;
9493
- prefix.push(value);
9494
- }
9495
- if (prefix.length > 0) {
9496
- const normalized = path25.join(...prefix);
9497
- return normalized === "." || normalized === ".." || normalized.startsWith(`.${path25.sep}`) || normalized.startsWith(`..${path25.sep}`) || path25.isAbsolute(normalized);
9498
- }
9499
- }
9500
- return false;
9501
- }
9502
- function hasUnknownBundleRelativeReference(file) {
9503
- if (!/\.(?:cjs|mjs|js)$/.test(file) || !fs29.existsSync(file)) return false;
9504
- const source = fs29.readFileSync(file, "utf8");
9505
- const ast = parseJavaScript(source);
9506
- if (!ast) return false;
9507
- const analysis = analyzeSource(ast);
9508
- let unsafe = false;
9509
- walkSimple(ast, {
9510
- CallExpression(node) {
9511
- const directRequire = isDirectRequire(node.callee, analysis);
9512
- const requireResolve = isRequireResolve(node.callee, analysis);
9513
- if (directRequire || requireResolve) {
9514
- const layout = classifyLayoutPath(file, node.arguments[0], analysis);
9515
- const staticTarget = staticModuleReference(
9516
- file,
9517
- node.arguments[0],
9518
- analysis
9519
- );
9520
- if (staticTarget === void 0 && (layout.kind === "unsafe" || expressionSignalsRelativeSpecifier(node.arguments[0], analysis))) {
9521
- unsafe = true;
9522
- }
9523
- return;
9524
- }
9525
- const method = fsMethod(node.callee, analysis);
9526
- if (isFsPathMethod(method)) {
9527
- const layouts = node.arguments.map(
9528
- (argument) => classifyLayoutPath(file, argument, analysis)
9529
- );
9530
- const pathLayout = layouts[0] ?? { kind: "none" };
9531
- if (pathLayout.kind === "unsafe" || method !== void 0 && COPYABLE_FS_METHODS.has(method) && pathLayout.kind === "static" && (!readOptionsAreSafe(method, node, analysis) || !canRewritePayloadPath(analysis)) || method !== void 0 && NON_COPYABLE_FS_METHODS.has(method) && layouts.some((layout) => layout.kind !== "none")) {
9532
- unsafe = true;
9533
- }
9534
- return;
9535
- }
9536
- if (isLayoutHelperCall(node.callee, analysis)) return;
9537
- if (node.arguments.some(
9538
- (argument) => classifyLayoutPath(file, argument, analysis).kind !== "none"
9539
- )) {
9540
- unsafe = true;
9541
- }
9542
- },
9543
- ImportExpression(node) {
9544
- const layout = classifyLayoutPath(file, node.source, analysis);
9545
- const staticTarget = staticModuleReference(file, node.source, analysis);
9546
- if (staticTarget === void 0 && (layout.kind === "unsafe" || expressionSignalsRelativeSpecifier(node.source, analysis))) {
9547
- unsafe = true;
9548
- }
9549
- }
9550
- });
9551
- return unsafe;
9552
- }
9553
- function hasUnbundleableNativeEdge(file) {
9554
- if (!/\.(?:cjs|mjs|js)$/.test(file) || !fs29.existsSync(file)) return false;
9555
- const source = fs29.readFileSync(file, "utf8");
9556
- const ast = parseJavaScript(source);
9557
- if (!ast) return false;
9558
- const analysis = analyzeSource(ast);
9559
- let nativeEdge = false;
9560
- walkSimple(ast, {
9561
- CallExpression(node) {
9562
- if (!isDirectRequire(node.callee, analysis)) {
9563
- return;
9564
- }
9565
- const specifier = staticString(node.arguments[0], analysis.strings);
9566
- if (specifier?.endsWith(".node")) nativeEdge = true;
9567
- }
9568
- });
9569
- return nativeEdge;
9570
- }
9571
- function runtimeBoundaryPlugin(projectRoot) {
9572
- const decisions = /* @__PURE__ */ new Map();
9573
- const realProjectRoot = fs29.realpathSync(projectRoot);
9574
- const resolutionError = (candidate) => {
9575
- if (!isInside(projectRoot, candidate)) {
9576
- return `runtime dependency resolved outside project root: ${candidate}`;
9577
- }
9578
- let current = projectRoot;
9579
- try {
9580
- for (const segment of path25.relative(projectRoot, candidate).split(path25.sep)) {
9581
- if (!segment) continue;
9582
- current = path25.join(current, segment);
9583
- if (fs29.lstatSync(current).isSymbolicLink()) {
9584
- return `runtime dependency symlink is unsupported: ${candidate}`;
9585
- }
9586
- }
9587
- const realCandidate = fs29.realpathSync(candidate);
9588
- if (!isInside(realProjectRoot, realCandidate)) {
9589
- return `runtime dependency resolved outside project root: ${candidate}`;
9590
- }
9591
- } catch (error) {
9592
- return `runtime dependency path is unavailable: ${candidate}: ${error instanceof Error ? error.message : String(error)}`;
9593
- }
9594
- return void 0;
9595
- };
9596
- return {
9597
- name: "miaoda-runtime-owner-boundary",
9598
- setup(esbuild) {
9599
- esbuild.onResolve({ filter: /.*/ }, async (args) => {
9600
- const pluginData = args.pluginData;
9601
- if (pluginData?.miaodaBoundarySkip || args.kind === "entry-point")
9602
- return void 0;
9603
- if (BUILTINS.has(args.path)) return { path: args.path, external: true };
9604
- const importerOwner = args.importer ? findPackageRoot(projectRoot, args.importer) : void 0;
9605
- const resolved = await esbuild.resolve(args.path, {
9606
- importer: args.importer,
9607
- kind: args.kind,
9608
- namespace: args.namespace,
9609
- resolveDir: isBareSpecifier(args.path) && !importerOwner ? projectRoot : args.resolveDir,
9610
- pluginData: { miaodaBoundarySkip: true }
9611
- });
9612
- if (resolved.errors.length > 0) {
9613
- return isBareSpecifier(args.path) ? { path: args.path, external: true } : resolved;
9614
- }
9615
- if (resolved.external) return resolved;
9616
- const unsafeResolution = resolutionError(resolved.path);
9617
- if (unsafeResolution) {
9618
- return {
9619
- errors: [
9620
- {
9621
- text: `${unsafeResolution}: ${args.path}`
9622
- }
9623
- ]
9624
- };
9625
- }
9626
- const owner = findPackageRoot(projectRoot, resolved.path);
9627
- if (!owner) {
9628
- if (hasUnknownBundleRelativeReference(resolved.path)) {
9629
- return {
9630
- errors: [
9631
- {
9632
- text: `application runtime has an unknown bundle-relative reference: ${resolved.path}`
9633
- }
9634
- ]
9635
- };
9636
- }
9637
- return resolved;
9638
- }
9639
- const decisionKey = `${owner}\0${resolved.path}`;
9640
- let external = decisions.get(decisionKey);
9641
- if (external === void 0) {
9642
- external = hasUnknownBundleRelativeReference(resolved.path) || hasUnbundleableNativeEdge(resolved.path);
9643
- decisions.set(decisionKey, external);
9644
- }
9645
- if (!external) return resolved;
9646
- if (!isBareSpecifier(args.path)) {
9647
- return {
9648
- errors: [
9649
- {
9650
- text: `runtime owner with an unknown bundle-relative reference must be imported by package name: ${args.path}`
9651
- }
9652
- ]
9653
- };
9654
- }
9655
- if (importerOwner) {
9656
- const rootResolved = await esbuild.resolve(args.path, {
9657
- kind: args.kind,
9658
- namespace: "file",
9659
- resolveDir: projectRoot,
9660
- pluginData: { miaodaBoundarySkip: true }
9661
- });
9662
- let resolvesToSameRootPackage = false;
9663
- if (rootResolved.errors.length === 0 && !rootResolved.external) {
9664
- try {
9665
- resolvesToSameRootPackage = fs29.realpathSync(rootResolved.path) === fs29.realpathSync(resolved.path);
9666
- } catch {
9667
- resolvesToSameRootPackage = false;
9668
- }
9669
- }
9670
- if (!resolvesToSameRootPackage) {
9671
- return {
9672
- errors: [
9673
- {
9674
- text: `runtime owner with an unknown bundle-relative reference must resolve to the same package from the bundle root: ${args.path}`
9675
- }
9676
- ]
9677
- };
9678
- }
9679
- }
9680
- return { path: args.path, external: true };
9681
- });
9682
- }
9683
- };
9684
- }
9685
- function staticActionPluginRegistry(projectRoot, plugins) {
9686
- if (plugins.length === 0) {
9687
- return { name: "miaoda-static-action-plugin-registry", setup() {
9688
- } };
9689
- }
9690
- const projectRequire = createRequire3(path25.join(projectRoot, "package.json"));
9691
- const capabilityEntry = projectRequire.resolve(ACTION_PLUGIN_LOADER_PACKAGE);
9692
- const imports = plugins.map(
9693
- (plugin, index) => `const __miaodaPlugin${index} = require(${JSON.stringify(plugin.entry)});`
9694
- );
9695
- const registrations = plugins.map(
9696
- (plugin, index) => `{ pluginKey: ${JSON.stringify(plugin.specifier)}, manifest: ${JSON.stringify(
9697
- plugin.manifest
9698
- )}, module: __miaodaPlugin${index} }`
9699
- );
9700
- const contents = [
9701
- `const __miaodaCapability = require(${JSON.stringify(capabilityEntry)});`,
9702
- "module.exports = __miaodaCapability;",
9703
- ...imports,
9704
- `const __miaodaRegistrations = [${registrations.join(",")}];`,
9705
- "if (typeof __miaodaCapability.registerStaticActionPlugins !== 'function') throw new Error('MIAODA_STATIC_ACTION_PLUGIN_REGISTRY_UNSUPPORTED');",
9706
- "__miaodaCapability.registerStaticActionPlugins(__miaodaRegistrations);"
9707
- ].join("\n");
9708
- return {
9709
- name: "miaoda-static-action-plugin-registry",
9710
- setup(esbuild) {
9711
- esbuild.onResolve({ filter: /^@lark-apaas\/nestjs-capability$/ }, () => ({
9712
- path: ACTION_PLUGIN_LOADER_PACKAGE,
9713
- namespace: "miaoda-static-action-plugin-registry"
9714
- }));
9715
- esbuild.onLoad(
9716
- { filter: /.*/, namespace: "miaoda-static-action-plugin-registry" },
9717
- () => ({ contents, loader: "js", resolveDir: projectRoot })
9718
- );
9719
- }
9720
- };
9721
- }
9722
- function startupEntryPlugin(entryFile, hasActionPlugins) {
9723
- const contents = hasActionPlugins ? [
9724
- `require(${JSON.stringify(ACTION_PLUGIN_LOADER_PACKAGE)});`,
9725
- `require(${JSON.stringify(entryFile)});`
9726
- ].join("\n") : `require(${JSON.stringify(entryFile)});`;
9727
- return {
9728
- name: "miaoda-startup-entry",
9729
- setup(esbuild) {
9730
- esbuild.onResolve({ filter: /^miaoda:startup-entry$/ }, () => ({
9731
- path: "miaoda:startup-entry",
9732
- namespace: "miaoda-startup-entry"
9733
- }));
9734
- esbuild.onLoad(
9735
- { filter: /.*/, namespace: "miaoda-startup-entry" },
9736
- () => ({ contents, loader: "js", resolveDir: path25.dirname(entryFile) })
9737
- );
9738
- }
9739
- };
9740
- }
9741
- async function buildStaticStartupPayload(options) {
9742
- const state = readDependencyState(options.projectRoot);
9743
- fs29.rmSync(options.outputFile, { force: true });
9744
- const result = await build({
9745
- absWorkingDir: options.projectRoot,
9746
- entryPoints: ["miaoda:startup-entry"],
9747
- outfile: options.outputFile,
9748
- bundle: true,
9749
- platform: "node",
9750
- format: "cjs",
9751
- target: `node${process.versions.node.split(".")[0]}`,
9752
- conditions: ["miaoda-startup"],
9753
- treeShaking: true,
9754
- keepNames: true,
9755
- legalComments: "none",
9756
- logLevel: "silent",
9757
- preserveSymlinks: true,
9758
- sourcemap: false,
9759
- metafile: true,
9760
- define: {
9761
- "import.meta.url": "__miaoda_startup_import_meta_url__"
9762
- },
9763
- banner: {
9764
- js: 'const __miaoda_startup_import_meta_url__ = require("node:url").pathToFileURL(__filename).href;'
9765
- },
9766
- plugins: [
9767
- startupEntryPlugin(options.entryFile, state.plugins.length > 0),
9768
- staticActionPluginRegistry(options.projectRoot, state.plugins),
9769
- staticModuleReferencePlugin(),
9770
- runtimeBoundaryPlugin(options.projectRoot)
9771
- ]
9772
- });
9773
- if (!result.metafile) throw new Error("esbuild metafile missing");
9774
- const nativeInputs = Object.keys(result.metafile.inputs).filter(
9775
- (input) => input.endsWith(".node")
9776
- );
9777
- if (nativeInputs.length > 0) {
9778
- throw new Error(
9779
- `native addons are unsupported: ${nativeInputs.join(", ")}`
9780
- );
9781
- }
9782
- materializeStaticAssets(
9783
- options.projectRoot,
9784
- result.metafile,
9785
- options.payloadRoot,
9786
- options.limits
9787
- );
9788
- }
9789
-
9790
- // src/commands/build/server-startup-bundle.handler.ts
9791
- var SCHEMA_VERSION = 7;
9792
- var STARTUP_BUNDLE_ENROLLMENT_SCHEMA_VERSION = 1;
9793
- var STARTUP_BUNDLE_FILE = "payload/server.bundle.cjs";
9794
- var MAX_GENERATION_FILES = 5e4;
9795
- var MAX_GENERATION_BYTES = 256 * 1024 * 1024;
9796
- var MAX_GENERATION_FILE_BYTES = 64 * 1024 * 1024;
9797
- var MAX_FILE_INDEX_BYTES = 16 * 1024 * 1024;
9798
- var MAX_MANIFEST_BYTES = 1024 * 1024;
9799
- var MAX_PACKAGE_MANIFEST_BYTES = 1024 * 1024;
9800
- var MAX_READINESS_RESPONSE_BYTES = 64 * 1024;
9801
- var ROOT_SOURCE_HASH_IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([
9802
- ".agents",
9803
- ".claude",
9804
- ".git",
9805
- ".miaoda-cache",
9806
- ".miaoda-runtime",
9807
- ".turbo",
9808
- "coverage",
9809
- "dist",
9810
- "logs"
9811
- ]);
9812
- var probeIdentities = /* @__PURE__ */ new WeakMap();
9813
- function sha256(contents) {
9814
- return createHash("sha256").update(contents).digest("hex");
9815
- }
9816
- function stableJson(value) {
9817
- if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
9818
- if (value && typeof value === "object") {
9819
- return `{${Object.entries(value).sort(([left], [right]) => compareCodeUnits(left, right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
9820
- }
9821
- return JSON.stringify(value);
9822
- }
9823
- function compareCodeUnits(left, right) {
9824
- return left < right ? -1 : left > right ? 1 : 0;
9825
- }
9826
- function isCapabilityReadinessPayload(contents, expectedCapabilityIds = []) {
9827
- if (contents.length > MAX_READINESS_RESPONSE_BYTES) return false;
9828
- try {
9829
- const payload = JSON.parse(contents.toString("utf8"));
9830
- if (!(payload && typeof payload === "object" && payload.status_code === "0" && payload.data && typeof payload.data === "object" && !Array.isArray(payload.data) && Array.isArray(payload.data.capabilities))) {
9831
- return false;
9832
- }
9833
- const actualIds = new Set(
9834
- (payload.data.capabilities ?? []).map(
9835
- (capability) => capability && typeof capability === "object" ? capability.id : void 0
9836
- ).filter((id) => typeof id === "string" && id.length > 0)
9837
- );
9838
- return expectedCapabilityIds.every((id) => actualIds.has(id));
9839
- } catch {
9840
- return false;
9841
- }
9842
- }
9843
- function resolveExpectedCapabilityIds(projectRoot) {
9844
- const capabilitiesRoot = path26.join(projectRoot, "server", "capabilities");
9845
- if (!fs30.existsSync(capabilitiesRoot)) return [];
9846
- const rootStats = fs30.lstatSync(capabilitiesRoot);
9847
- if (rootStats.isSymbolicLink() || !rootStats.isDirectory()) {
9848
- throw new Error("workspace capability directory is unsafe");
9849
- }
9850
- const realRoot = fs30.realpathSync(capabilitiesRoot);
9851
- if (!isInside2(projectRoot, realRoot)) {
9852
- throw new Error("workspace capability directory escaped project root");
9853
- }
9854
- const ids = /* @__PURE__ */ new Set();
9855
- for (const entry of fs30.readdirSync(realRoot, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name))) {
9856
- if (!entry.name.endsWith(".json") || entry.name === "capabilities.json") {
9857
- continue;
9858
- }
9859
- const file = path26.join(realRoot, entry.name);
9860
- if (entry.isSymbolicLink() || !entry.isFile()) {
9861
- throw new Error(`workspace capability file is unsafe: ${entry.name}`);
9862
- }
9863
- const config = readJsonObject(file, `workspace capability ${entry.name}`);
9864
- if (typeof config.id !== "string" || config.id.length === 0 || config.id.length > 256) {
9865
- throw new Error(
9866
- `workspace capability file has no valid id: ${entry.name}`
9867
- );
9868
- }
9869
- if (ids.has(config.id)) {
9870
- throw new Error(`workspace capability id is duplicated: ${config.id}`);
9871
- }
9872
- ids.add(config.id);
9873
- }
9874
- return [...ids].sort();
9875
- }
9876
- function isInside2(root, candidate) {
9877
- const relative = path26.relative(root, candidate);
9878
- return relative === "" || !relative.startsWith("..") && !path26.isAbsolute(relative);
9879
- }
9880
- function toPosixRelative(root, file) {
9881
- return path26.relative(root, file).split(path26.sep).join("/");
9882
- }
9883
- function assertNoSymlinkComponents(root, candidate, message) {
9884
- if (!isInside2(root, candidate)) throw new Error(`${message}: escaped root`);
9885
- let current = root;
9886
- for (const segment of path26.relative(root, candidate).split(path26.sep)) {
9887
- if (!segment) continue;
9888
- current = path26.join(current, segment);
9889
- if (fs30.existsSync(current) && fs30.lstatSync(current).isSymbolicLink()) {
9890
- throw new Error(message);
9891
- }
9892
- }
9893
- }
9894
- function walkSourceFiles(root, directory, output) {
9895
- if (!fs30.existsSync(directory)) return;
9896
- for (const entry of fs30.readdirSync(directory, { withFileTypes: true })) {
9897
- if (entry.name === "node_modules" || directory === root && ROOT_SOURCE_HASH_IGNORED_DIRECTORIES.has(entry.name)) {
9898
- continue;
9899
- }
9900
- const candidate = path26.join(directory, entry.name);
9901
- if (entry.isSymbolicLink()) {
9902
- throw new Error(
9903
- `source symlink is unsupported: ${toPosixRelative(root, candidate)}`
9904
- );
9905
- }
9906
- if (entry.isDirectory()) walkSourceFiles(root, candidate, output);
9907
- else if (entry.isFile()) output.push(candidate);
9908
- else {
9909
- throw new Error(
9910
- `source special file is unsupported: ${toPosixRelative(root, candidate)}`
9911
- );
9912
- }
9913
- }
9914
- }
9915
- function workspaceSourceSha256(projectRoot) {
9916
- const files = [];
9917
- walkSourceFiles(projectRoot, projectRoot, files);
9918
- const hash = createHash("sha256");
9919
- for (const file of files.sort()) {
9920
- hash.update(toPosixRelative(projectRoot, file));
9921
- hash.update("\0");
9922
- updateHashFromFile(hash, file);
9923
- hash.update("\0");
9924
- }
9925
- return hash.digest("hex");
9926
- }
9927
- function updateHashFromFile(hash, file) {
9928
- const descriptor = fs30.openSync(file, "r");
9929
- const buffer = Buffer.allocUnsafe(1024 * 1024);
9930
- try {
9931
- const before = fs30.fstatSync(descriptor);
9932
- let position = 0;
9933
- while (position < before.size) {
9934
- const bytesRead = fs30.readSync(
9935
- descriptor,
9936
- buffer,
9937
- 0,
9938
- Math.min(buffer.length, before.size - position),
9939
- position
9940
- );
9941
- if (bytesRead === 0) break;
9942
- hash.update(buffer.subarray(0, bytesRead));
9943
- position += bytesRead;
9944
- }
9945
- const after = fs30.fstatSync(descriptor);
9946
- if (position !== before.size || after.size !== before.size || after.mtimeMs !== before.mtimeMs) {
9947
- throw new Error(`source changed while hashing: ${file}`);
9948
- }
9949
- } finally {
9950
- fs30.closeSync(descriptor);
9951
- }
9952
- }
9953
- function runtimeIdentity() {
9954
- const report = process.report?.getReport();
9955
- const header = report?.header;
9956
- return {
9957
- nodeVersion: process.versions.node,
9958
- nodeModulesAbi: process.versions.modules,
9959
- platform: process.platform,
9960
- arch: process.arch,
9961
- libc: typeof header?.glibcVersionRuntime === "string" ? `glibc-${header.glibcVersionRuntime}` : process.platform === "linux" ? "linux-unknown-libc" : "not-applicable"
9962
- };
9963
- }
9964
- function resolveEntry(projectRoot, requested) {
9965
- const entry = path26.resolve(projectRoot, requested);
9966
- if (!isInside2(projectRoot, entry))
9967
- throw new Error("compiled entry escaped project root");
9968
- if (!fs30.existsSync(entry))
9969
- throw new Error(`compiled entry is not a file: ${entry}`);
9970
- if (fs30.lstatSync(entry).isSymbolicLink()) {
9971
- throw new Error("compiled entry symlink is unsupported");
9972
- }
9973
- const realEntry = fs30.realpathSync(entry);
9974
- if (!isInside2(projectRoot, realEntry))
9975
- throw new Error("compiled entry escaped project root");
9976
- if (!fs30.statSync(realEntry).isFile())
9977
- throw new Error(`compiled entry is not a file: ${entry}`);
9978
- return realEntry;
9979
- }
9980
- function resolveNestTsconfig(projectRoot) {
9981
- const nestConfigFile = path26.join(projectRoot, "nest-cli.json");
9982
- let configured;
9983
- if (fs30.existsSync(nestConfigFile)) {
9984
- const nestConfig = JSON.parse(fs30.readFileSync(nestConfigFile, "utf8"));
9985
- configured = nestConfig.compilerOptions?.tsConfigPath;
9986
- if (configured !== void 0 && typeof configured !== "string") {
9987
- throw new Error("nest-cli.json compilerOptions.tsConfigPath is invalid");
9988
- }
9989
- }
9990
- const candidates = typeof configured === "string" ? [configured] : ["tsconfig.build.json", "tsconfig.node.json", "tsconfig.json"];
9991
- const selected = candidates.map((candidate) => path26.resolve(projectRoot, candidate)).find((candidate) => fs30.existsSync(candidate));
9992
- if (!selected) {
9993
- throw new Error(`Nest TypeScript config missing: ${candidates.join(", ")}`);
9994
- }
9995
- if (!isInside2(projectRoot, selected))
9996
- throw new Error("Nest TypeScript config escaped project root");
9997
- if (fs30.lstatSync(selected).isSymbolicLink())
9998
- throw new Error("Nest TypeScript config symlink is unsupported");
9999
- const realConfig = fs30.realpathSync(selected);
10000
- if (!isInside2(projectRoot, realConfig) || !fs30.statSync(realConfig).isFile()) {
10001
- throw new Error("Nest TypeScript config escaped project root");
10002
- }
10003
- return realConfig;
10004
- }
10005
- function resolveNestCli(projectRoot) {
10006
- const projectRequire = createRequire4(path26.join(projectRoot, "package.json"));
10007
- try {
10008
- return projectRequire.resolve("@nestjs/cli/bin/nest.js");
10009
- } catch (directError) {
10010
- try {
10011
- const packageFile = projectRequire.resolve("@nestjs/cli/package.json");
10012
- const packageJson = JSON.parse(fs30.readFileSync(packageFile, "utf8"));
10013
- const relativeBin = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.nest;
10014
- if (!relativeBin) throw new Error("@nestjs/cli has no nest binary");
10015
- const cliFile = path26.resolve(path26.dirname(packageFile), relativeBin);
10016
- if (!fs30.statSync(cliFile).isFile())
10017
- throw new Error("@nestjs/cli nest binary is not a file");
10018
- return cliFile;
10019
- } catch (packageError) {
10020
- throw new Error(
10021
- `project @nestjs/cli is unavailable: ${packageError instanceof Error ? packageError.message : String(packageError)}; direct=${directError instanceof Error ? directError.message : String(directError)}`
10022
- );
10023
- }
10024
- }
10025
- }
10026
- function readLinuxProcessIdentity(pid) {
10027
- if (process.platform !== "linux") return void 0;
10028
- try {
10029
- const stat = fs30.readFileSync(`/proc/${pid}/stat`, "utf8");
10030
- const commandEnd = stat.lastIndexOf(")");
10031
- if (commandEnd < 0) return void 0;
10032
- const fields = stat.slice(commandEnd + 1).trim().split(/\s+/);
10033
- return /^\d+$/.test(fields[19] || "") && /^\d+$/.test(fields[2] || "") ? { processStartTicks: fields[19], processGroupId: Number(fields[2]) } : void 0;
10034
- } catch {
10035
- return void 0;
10036
- }
10037
- }
10038
- function registerProbe(child) {
10039
- if (!child.pid) throw new Error("isolated process pid unavailable");
10040
- const identity = readLinuxProcessIdentity(child.pid);
10041
- if (process.platform === "linux" && !identity) {
10042
- child.kill("SIGKILL");
10043
- throw new Error("isolated process birth identity unavailable");
10044
- }
10045
- probeIdentities.set(child, {
10046
- pid: child.pid,
10047
- processStartTicks: identity?.processStartTicks
10048
- });
10049
- }
10050
- function probeGroupRunning(child) {
10051
- const registered = probeIdentities.get(child);
10052
- if (!registered) return false;
10053
- if (process.platform === "linux") {
10054
- const current = readLinuxProcessIdentity(registered.pid);
10055
- if (current) {
10056
- if (current.processStartTicks !== registered.processStartTicks || current.processGroupId !== registered.pid) {
10057
- return false;
10058
- }
10059
- } else {
10060
- try {
10061
- process.kill(registered.pid, 0);
10062
- return false;
10063
- } catch (error) {
10064
- if (error.code !== "ESRCH") return false;
10065
- }
10066
- }
10067
- }
10068
- try {
10069
- process.kill(-registered.pid, 0);
10070
- return true;
10071
- } catch (error) {
10072
- return error.code === "EPERM";
10073
- }
10074
- }
10075
- async function waitForProbeGroup(child, timeoutMs) {
10076
- const deadline = Date.now() + timeoutMs;
10077
- while (probeGroupRunning(child) && Date.now() < deadline) {
10078
- await new Promise((resolve2) => setTimeout(resolve2, 25));
10079
- }
10080
- return !probeGroupRunning(child);
10081
- }
10082
- async function stopProbe(child) {
10083
- const registered = probeIdentities.get(child);
10084
- if (!registered) return;
10085
- if (probeGroupRunning(child)) {
10086
- try {
10087
- process.kill(-registered.pid, "SIGTERM");
10088
- } catch {
10089
- }
10090
- }
10091
- if (!await waitForProbeGroup(child, 500)) {
10092
- if (probeGroupRunning(child)) {
10093
- try {
10094
- process.kill(-registered.pid, "SIGKILL");
10095
- } catch {
10096
- }
10097
- }
10098
- if (!await waitForProbeGroup(child, 500)) {
10099
- throw new Error(
10100
- `isolated probe process group did not exit: ${registered.pid}`
10101
- );
10102
- }
10103
- }
10104
- if (child.exitCode === null && child.signalCode === null) {
10105
- const exited = await new Promise((resolve2) => {
10106
- let settled = false;
10107
- let timer;
10108
- const finish = (result) => {
10109
- if (settled) return;
10110
- settled = true;
10111
- if (timer) clearTimeout(timer);
10112
- child.off("exit", onExit);
10113
- child.off("error", onError);
10114
- resolve2(result);
10115
- };
10116
- const onExit = () => finish(true);
10117
- const onError = () => finish(false);
10118
- child.once("exit", onExit);
10119
- child.once("error", onError);
10120
- timer = setTimeout(() => finish(false), 5e3);
10121
- if (child.exitCode !== null || child.signalCode !== null) finish(true);
10122
- });
10123
- if (!exited) {
10124
- throw new Error(
10125
- `isolated probe child did not publish exit after group cleanup: ${registered.pid}`
10126
- );
10127
- }
10128
- }
10129
- }
10130
- function collectChildOutput(child, stream) {
10131
- let output = "";
10132
- child[stream]?.setEncoding("utf8");
10133
- child[stream]?.on("data", (chunk) => {
10134
- output = `${output}${String(chunk)}`.slice(-64 * 1024);
10135
- });
10136
- return () => output;
10137
- }
10138
- async function waitForCommand(child, timeoutMs, description) {
10139
- let timer;
10140
- try {
10141
- return await new Promise((resolve2, reject) => {
10142
- let settled = false;
10143
- const finish = (callback) => {
10144
- if (settled) return;
10145
- settled = true;
10146
- if (timer) clearTimeout(timer);
10147
- callback();
10148
- };
10149
- child.once("error", (error) => finish(() => reject(error)));
10150
- child.once(
10151
- "exit",
10152
- (code, signal) => finish(
10153
- () => signal ? reject(new Error(`${description} exited by ${signal}`)) : resolve2(code ?? 1)
10154
- )
10155
- );
10156
- timer = setTimeout(
10157
- () => finish(() => reject(new Error(`${description} timeout`))),
10158
- timeoutMs
10159
- );
10160
- });
10161
- } finally {
10162
- if (timer) clearTimeout(timer);
10163
- }
10164
- }
10165
- async function compileNestSource(projectRoot, stagingRoot, timeoutMs, sourceConfig) {
10166
- const cliFile = resolveNestCli(projectRoot);
10167
- const compileRoot = path26.join(stagingRoot, ".compiled");
10168
- const outputRoot = path26.join(compileRoot, "output");
10169
- fs30.mkdirSync(outputRoot, { recursive: true });
10170
- const isolatedConfig = path26.join(compileRoot, "tsconfig.json");
10171
- fs30.writeFileSync(
10172
- isolatedConfig,
10173
- `${JSON.stringify(
10174
- {
10175
- extends: sourceConfig,
10176
- compilerOptions: {
10177
- outDir: outputRoot,
10178
- incremental: false,
10179
- composite: false,
10180
- declaration: false,
10181
- declarationMap: false,
10182
- sourceMap: false,
10183
- inlineSourceMap: false
10184
- }
10185
- },
10186
- null,
10187
- 2
10188
- )}
10189
- `,
10190
- { mode: 384 }
10191
- );
10192
- const child = spawn2(
10193
- process.execPath,
10194
- [cliFile, "build", "--path", path26.relative(projectRoot, isolatedConfig)],
10195
- {
10196
- cwd: projectRoot,
10197
- detached: true,
10198
- stdio: ["ignore", "pipe", "pipe"],
10199
- env: { ...process.env, NODE_ENV: "production" }
10200
- }
10201
- );
10202
- registerProbe(child);
10203
- const stdout = collectChildOutput(child, "stdout");
10204
- const stderr = collectChildOutput(child, "stderr");
10205
- try {
10206
- const code = await waitForCommand(
10207
- child,
10208
- timeoutMs,
10209
- "isolated Nest compilation"
10210
- );
10211
- if (code !== 0) {
10212
- throw new Error(
10213
- `isolated Nest compilation failed with exit ${code}: ${stderr().trim() || stdout().trim()}`
10214
- );
10215
- }
10216
- } finally {
10217
- await stopProbe(child);
10218
- }
10219
- const candidates = [
10220
- path26.join(outputRoot, "server", "main.js"),
10221
- path26.join(outputRoot, "main.js")
10222
- ].filter((candidate) => fs30.existsSync(candidate));
10223
- if (candidates.length !== 1) {
10224
- throw new Error(
10225
- candidates.length === 0 ? "isolated Nest compiled entry missing; checked server/main.js and main.js" : "isolated Nest compiled entry is ambiguous"
10226
- );
10227
- }
10228
- const entry = fs30.realpathSync(candidates[0]);
10229
- if (!isInside2(fs30.realpathSync(outputRoot), entry) || !fs30.statSync(entry).isFile()) {
10230
- throw new Error("isolated Nest compiled entry escaped output root");
10231
- }
10232
- return { entry, applicationRoot: outputRoot };
10233
- }
10234
- function copyRegularFile(source, target) {
10235
- const stats = fs30.lstatSync(source);
10236
- if (stats.isSymbolicLink()) {
10237
- throw new Error(`runtime tree symlink is unsupported: ${source}`);
10238
- }
10239
- if (!stats.isFile()) {
10240
- throw new Error(`runtime tree special file is unsupported: ${source}`);
10241
- }
10242
- fs30.mkdirSync(path26.dirname(target), { recursive: true });
10243
- fs30.copyFileSync(source, target, fs30.constants.COPYFILE_FICLONE);
10244
- fs30.chmodSync(target, stats.mode & 73 ? 493 : 420);
10245
- }
10246
- function copyDirectoryContents(sourceRoot, targetRoot) {
10247
- const visit = (source, target) => {
10248
- const stats = fs30.lstatSync(source);
10249
- if (stats.isSymbolicLink()) {
10250
- throw new Error(`runtime tree symlink is unsupported: ${source}`);
10251
- }
10252
- if (stats.isFile()) {
10253
- copyRegularFile(source, target);
10254
- return;
10255
- }
10256
- if (!stats.isDirectory()) {
10257
- throw new Error(`runtime tree special file is unsupported: ${source}`);
10258
- }
10259
- fs30.mkdirSync(target, { recursive: true, mode: 493 });
10260
- for (const entry of fs30.readdirSync(source, { withFileTypes: true })) {
10261
- if (entry.name === "node_modules") {
10262
- throw new Error("startup payload must not contain node_modules");
10263
- }
10264
- visit(path26.join(source, entry.name), path26.join(target, entry.name));
10265
- }
10266
- };
10267
- visit(sourceRoot, targetRoot);
10268
- }
10269
- function reserveGenerationBudget(file, size, budget) {
10270
- if (size > MAX_GENERATION_FILE_BYTES) {
10271
- throw new Error(`generation file exceeds 64 MiB: ${file}`);
10272
- }
10273
- if (budget.fileCount + 1 > MAX_GENERATION_FILES) {
10274
- throw new Error(`generation exceeds ${MAX_GENERATION_FILES} files`);
10275
- }
10276
- if (budget.totalBytes + size > MAX_GENERATION_BYTES) {
10277
- throw new Error("generation exceeds 256 MiB");
10278
- }
10279
- budget.fileCount += 1;
10280
- budget.totalBytes += size;
10281
- }
10282
- function copyProbeWorkspace(projectRoot, probeProjectRoot) {
10283
- const files = [];
10284
- walkSourceFiles(projectRoot, projectRoot, files);
10285
- const budget = { fileCount: 0, totalBytes: 0 };
10286
- for (const file of files) {
10287
- reserveGenerationBudget(file, fs30.lstatSync(file).size, budget);
10288
- copyRegularFile(
10289
- file,
10290
- path26.join(
10291
- probeProjectRoot,
10292
- ...toPosixRelative(projectRoot, file).split("/")
10293
- )
10294
- );
10295
- }
10296
- }
10297
- function readJsonObject(file, description) {
10298
- const parsed = JSON.parse(
10299
- readBoundedFile(file, MAX_PACKAGE_MANIFEST_BYTES, description).toString(
10300
- "utf8"
10301
- )
10302
- );
10303
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
10304
- throw new Error(`${description} must be a JSON object`);
10305
- }
10306
- return parsed;
10307
- }
10308
- function readBoundedFile(file, maxBytes, description) {
10309
- const stats = fs30.lstatSync(file);
10310
- if (stats.isSymbolicLink() || !stats.isFile() || stats.size > maxBytes) {
10311
- throw new Error(`${description} exceeds the supported metadata size`);
10312
- }
10313
- const contents = fs30.readFileSync(file);
10314
- if (contents.length !== stats.size) {
10315
- throw new Error(`${description} changed while reading`);
10316
- }
10317
- return contents;
10318
- }
10319
- function assertStartupBundleEnrollment(projectRoot) {
10320
- const packageFile = path26.join(projectRoot, "package.json");
10321
- if (!fs30.existsSync(packageFile) || fs30.lstatSync(packageFile).isSymbolicLink()) {
10322
- throw new Error("package.json is unavailable");
10323
- }
10324
- const packageJson = readJsonObject(packageFile, "package.json");
10325
- const enrollment = packageJson.miaodaStartupBundle;
10326
- if (!enrollment || typeof enrollment !== "object" || Array.isArray(enrollment) || enrollment.schemaVersion !== STARTUP_BUNDLE_ENROLLMENT_SCHEMA_VERSION) {
10327
- throw new Error(
10328
- `package.json miaodaStartupBundle.schemaVersion must be ${STARTUP_BUNDLE_ENROLLMENT_SCHEMA_VERSION}`
10329
- );
10330
- }
10331
- }
10332
- function indexPayload(payloadRoot) {
10333
- const files = [];
10334
- const budget = { fileCount: 0, totalBytes: 0 };
10335
- const visit = (directory) => {
10336
- for (const entry of fs30.readdirSync(directory, { withFileTypes: true })) {
10337
- const candidate = path26.join(directory, entry.name);
10338
- if (entry.isSymbolicLink()) {
10339
- throw new Error(`generation symlink is unsupported: ${candidate}`);
10340
- }
10341
- if (entry.isDirectory()) {
10342
- visit(candidate);
10343
- continue;
10344
- }
10345
- if (!entry.isFile()) {
10346
- throw new Error(`generation special file is unsupported: ${candidate}`);
10347
- }
10348
- const stats = fs30.lstatSync(candidate);
10349
- if (!stats.isFile()) {
10350
- throw new Error(`generation special file is unsupported: ${candidate}`);
10351
- }
10352
- reserveGenerationBudget(candidate, stats.size, budget);
10353
- const contents = fs30.readFileSync(candidate);
10354
- if (contents.length !== stats.size) {
10355
- throw new Error(
10356
- `generation file changed while indexing: ${toPosixRelative(payloadRoot, candidate)}`
10357
- );
10358
- }
10359
- files.push({
10360
- path: `payload/${toPosixRelative(payloadRoot, candidate)}`,
10361
- sha256: sha256(contents),
10362
- size: contents.length,
10363
- mode: stats.mode & 511
10364
- });
10365
- }
10366
- };
10367
- visit(payloadRoot);
10368
- files.sort((left, right) => compareCodeUnits(left.path, right.path));
10369
- return files;
10370
- }
10371
- function reservePort() {
10372
- return new Promise((resolve2, reject) => {
10373
- const server = net.createServer();
10374
- server.once("error", reject);
10375
- server.listen(0, "127.0.0.1", () => {
10376
- const address = server.address();
10377
- if (!address || typeof address === "string") {
10378
- server.close(
10379
- () => reject(new Error("isolated probe failed to reserve a port"))
10380
- );
10381
- return;
10382
- }
10383
- server.close((error) => error ? reject(error) : resolve2(address.port));
10384
- });
10385
- });
10386
- }
10387
- async function isolatedProbe(projectRoot, payloadRoot, entry, timeoutMs, expectedCapabilityIds) {
10388
- const probeRoot = fs30.mkdtempSync(
10389
- path26.join(os3.tmpdir(), "miaoda-server-generation-probe-")
10390
- );
10391
- const probeWorkspaceRoot = path26.join(probeRoot, "workspace");
10392
- const probeProjectRoot = path26.join(probeWorkspaceRoot, "code");
10393
- copyProbeWorkspace(projectRoot, probeProjectRoot);
10394
- const probeGenerationRoot = path26.join(
10395
- probeProjectRoot,
10396
- ".miaoda-cache",
10397
- "server",
10398
- "generations",
10399
- "probe"
10400
- );
10401
- const probePayload = path26.join(probeGenerationRoot, "payload");
10402
- copyDirectoryContents(payloadRoot, probePayload);
10403
- const probeEntry = path26.join(probeGenerationRoot, ...entry.split("/"));
10404
- const probeResolutionGuard = path26.join(
10405
- probeRoot,
10406
- "probe-module-resolution-guard.cjs"
10407
- );
10408
- const probeEsmResolutionLoader = path26.join(
10409
- probeRoot,
10410
- "probe-module-resolution-loader.mjs"
10411
- );
10412
- const allowedPayloadRoot = fs30.realpathSync(probePayload);
10413
- fs30.writeFileSync(
10414
- probeResolutionGuard,
10415
- `'use strict';
10416
- const fs = require('node:fs');
10417
- const Module = require('node:module');
10418
- const path = require('node:path');
10419
- const allowedRoot = ${JSON.stringify(allowedPayloadRoot)};
10420
- const builtins = new Set(Module.builtinModules.flatMap(name => [name, 'node:' + name]));
10421
- const originalResolveFilename = Module._resolveFilename;
10422
- Module._resolveFilename = function miaodaProbeResolve(request, parent, isMain, options) {
10423
- const resolved = originalResolveFilename.call(this, request, parent, isMain, options);
10424
- if (builtins.has(request)) return resolved;
10425
- if (typeof resolved !== 'string' || !path.isAbsolute(resolved)) {
10426
- const error = new Error('MIAODA_ISOLATED_PROBE_MODULE_REJECTED:' + request + ':' + resolved);
10427
- error.code = 'MODULE_NOT_FOUND';
10428
- throw error;
10429
- }
10430
- const realResolved = fs.realpathSync(resolved);
10431
- const relative = path.relative(allowedRoot, realResolved);
10432
- if (relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))) {
10433
- return resolved;
10434
- }
10435
- const error = new Error('MIAODA_ISOLATED_PROBE_MODULE_REJECTED:' + request + ':' + realResolved);
10436
- error.code = 'MODULE_NOT_FOUND';
10437
- throw error;
10438
- };
10439
- `,
10440
- { mode: 384 }
10441
- );
10442
- fs30.writeFileSync(
10443
- probeEsmResolutionLoader,
10444
- `import fs from 'node:fs';
10445
- import path from 'node:path';
10446
- import { fileURLToPath } from 'node:url';
10447
-
10448
- const allowedRoot = ${JSON.stringify(allowedPayloadRoot)};
10449
-
10450
- export async function resolve(specifier, context, nextResolve) {
10451
- const resolved = await nextResolve(specifier, context);
10452
- if (resolved.url.startsWith('node:')) return resolved;
10453
- if (!resolved.url.startsWith('file:')) {
10454
- throw new Error('MIAODA_ISOLATED_PROBE_ESM_REJECTED:' + specifier + ':' + resolved.url);
10455
- }
10456
- const realResolved = fs.realpathSync(fileURLToPath(resolved.url));
10457
- const relative = path.relative(allowedRoot, realResolved);
10458
- if (relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))) {
10459
- return resolved;
10460
- }
10461
- const error = new Error('MIAODA_ISOLATED_PROBE_ESM_REJECTED:' + specifier + ':' + resolved.url);
10462
- error.code = 'ERR_MODULE_NOT_FOUND';
10463
- throw error;
10464
- }
10465
- `,
10466
- { mode: 384 }
10467
- );
10468
- const port = await reservePort();
10469
- const configuredBasePath = process.env.CLIENT_BASE_PATH;
10470
- const basePath = configuredBasePath?.startsWith("/") && !configuredBasePath.startsWith("//") ? configuredBasePath.replace(/\/+$/, "") : "";
10471
- const readinessPath = `${basePath}/__innerapi__/capability/list`;
10472
- const probeNodeOptions = [
10473
- `--require=${JSON.stringify(probeResolutionGuard)}`,
10474
- `--experimental-loader=${JSON.stringify(probeEsmResolutionLoader)}`
10475
- ].join(" ");
10476
- const child = spawn2(process.execPath, [probeEntry], {
10477
- cwd: probeProjectRoot,
10478
- detached: true,
10479
- stdio: ["ignore", "pipe", "pipe"],
10480
- env: {
10481
- ...process.env,
10482
- NODE_PATH: "",
10483
- NODE_OPTIONS: probeNodeOptions,
10484
- PWD: probeProjectRoot,
10485
- WORKSPACE_DIR: probeWorkspaceRoot,
10486
- MIAODA_WORKSPACE_ROOT: probeProjectRoot,
10487
- NODE_ENV: "development",
10488
- SERVER_HOST: "127.0.0.1",
10489
- SERVER_PORT: String(port),
10490
- DEPRECATED_SKIP_INIT_DB_CONNECTION: process.env.DEPRECATED_SKIP_INIT_DB_CONNECTION ?? "true",
10491
- FORCE_AUTHN_INNERAPI_DOMAIN: process.env.FORCE_AUTHN_INNERAPI_DOMAIN ?? "http://127.0.0.1",
10492
- FORCE_AUTHN_ACCESS_KEY: process.env.FORCE_AUTHN_ACCESS_KEY ?? "server-startup-probe",
10493
- FORCE_AUTHN_ACCESS_SECRET: process.env.FORCE_AUTHN_ACCESS_SECRET ?? "server-startup-probe"
10494
- }
10495
- });
10496
- registerProbe(child);
10497
- const stdout = collectChildOutput(child, "stdout");
10498
- const stderr = collectChildOutput(child, "stderr");
10499
- try {
10500
- await new Promise((resolve2, reject) => {
10501
- const deadline = Date.now() + timeoutMs;
10502
- let settled = false;
10503
- let retryTimer;
10504
- const detail = () => `${stderr()}
10505
- ${stdout()}`.trim();
10506
- const finish = (error) => {
10507
- if (settled) return;
10508
- settled = true;
10509
- if (retryTimer) clearTimeout(retryTimer);
10510
- if (error) reject(error);
10511
- else resolve2();
10512
- };
10513
- const retry = () => {
10514
- const remaining = deadline - Date.now();
10515
- if (remaining <= 0) {
10516
- finish(
10517
- new Error(
10518
- `isolated generation readiness timeout${detail() ? `: ${detail()}` : ""}`
10519
- )
10520
- );
10521
- return;
10522
- }
10523
- retryTimer = setTimeout(attempt, Math.min(25, remaining));
10524
- };
10525
- const attempt = () => {
10526
- if (settled) return;
10527
- if (child.exitCode !== null || child.signalCode !== null) {
10528
- finish(
10529
- new Error(
10530
- `isolated generation exited before readiness${detail() ? `: ${detail()}` : ""}`
10531
- )
10532
- );
10533
- return;
10534
- }
10535
- const remaining = deadline - Date.now();
10536
- if (remaining <= 0) return retry();
10537
- let requestSettled = false;
10538
- const request = http.get(
10539
- { host: "127.0.0.1", port, path: readinessPath },
10540
- (response) => {
10541
- if (requestSettled || settled) {
10542
- response.destroy();
10543
- return;
10544
- }
10545
- if (response.statusCode !== 200) {
10546
- requestSettled = true;
10547
- response.resume();
10548
- retry();
10549
- return;
10550
- }
10551
- const chunks = [];
10552
- let responseBytes = 0;
10553
- response.on("data", (chunk) => {
10554
- if (requestSettled || settled) return;
10555
- const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
10556
- responseBytes += buffer.length;
10557
- if (responseBytes > MAX_READINESS_RESPONSE_BYTES) {
10558
- requestSettled = true;
10559
- response.destroy();
10560
- retry();
10561
- return;
10562
- }
10563
- chunks.push(buffer);
10564
- });
10565
- response.once("end", () => {
10566
- if (requestSettled || settled) return;
10567
- requestSettled = true;
10568
- if (isCapabilityReadinessPayload(
10569
- Buffer.concat(chunks),
10570
- expectedCapabilityIds
10571
- ))
10572
- finish();
10573
- else retry();
10574
- });
10575
- response.once("error", () => {
10576
- if (requestSettled || settled) return;
10577
- requestSettled = true;
10578
- retry();
10579
- });
10580
- }
10581
- );
10582
- request.setTimeout(
10583
- remaining,
10584
- () => request.destroy(new Error("isolated generation readiness timeout"))
10585
- );
10586
- request.once("error", () => {
10587
- if (requestSettled || settled) return;
10588
- requestSettled = true;
10589
- retry();
10590
- });
10591
- };
10592
- attempt();
10593
- });
10594
- } finally {
10595
- await stopProbe(child);
10596
- fs30.rmSync(probeRoot, { recursive: true, force: true });
10597
- }
10598
- }
10599
- function writeBoundedJson(file, value, maxBytes, description) {
10600
- const contents = `${JSON.stringify(value, null, 2)}
10601
- `;
10602
- if (Buffer.byteLength(contents) > maxBytes) {
10603
- throw new Error(`${description} exceeds ${maxBytes} bytes`);
10604
- }
10605
- fs30.writeFileSync(file, contents, {
10606
- mode: 384
10607
- });
10608
- }
10609
- function removeLegacyPointer(cacheRoot) {
10610
- fs30.rmSync(path26.join(cacheRoot, "current.json"), { force: true });
10611
- }
10612
- function removeLegacyDependencyArtifacts(cacheRoot) {
10613
- for (const name of ["node_modules", "dependencies.json"]) {
10614
- const target = path26.join(cacheRoot, name);
10615
- if (!fs30.existsSync(target)) continue;
10616
- const stats = fs30.lstatSync(target);
10617
- if (stats.isDirectory() && !stats.isSymbolicLink()) {
10618
- fs30.rmSync(target, { recursive: true, force: true });
10619
- } else {
10620
- fs30.rmSync(target, { force: true });
10621
- }
10622
- }
10623
- }
10624
- function removeStaleBuildArtifacts(cacheRoot) {
10625
- for (const entry of fs30.readdirSync(cacheRoot)) {
10626
- if (!/^\.(?:staging|retired)-[a-z0-9-]+$/.test(entry)) continue;
10627
- const target = path26.join(cacheRoot, entry);
10628
- const stats = fs30.lstatSync(target);
10629
- if (stats.isDirectory() && !stats.isSymbolicLink()) {
10630
- fs30.rmSync(target, { recursive: true, force: true });
10631
- } else {
10632
- fs30.rmSync(target, { force: true });
10633
- }
10634
- }
10635
- }
10636
- async function buildServerStartupBundle(options) {
10637
- const startedAt = Date.now();
10638
- let stagingRoot;
10639
- let cacheRoot;
10640
- try {
10641
- const projectRoot = fs30.realpathSync(path26.resolve(options.projectRoot));
10642
- assertStartupBundleEnrollment(projectRoot);
10643
- cacheRoot = path26.resolve(
10644
- projectRoot,
10645
- options.cacheRoot ?? ".miaoda-cache/server"
10646
- );
10647
- if (!isInside2(projectRoot, cacheRoot))
10648
- throw new Error("cache root escaped project root");
10649
- assertNoSymlinkComponents(
10650
- projectRoot,
10651
- cacheRoot,
10652
- "cache path symlink is unsupported"
10653
- );
10654
- fs30.mkdirSync(cacheRoot, { recursive: true, mode: 448 });
10655
- removeLegacyPointer(cacheRoot);
10656
- removeLegacyDependencyArtifacts(cacheRoot);
10657
- removeStaleBuildArtifacts(cacheRoot);
10658
- const timeoutMs = options.probeTimeoutMs ?? 1e4;
10659
- const compileTimeoutMs = options.compileTimeoutMs ?? 12e4;
10660
- if (!Number.isFinite(timeoutMs) || timeoutMs <= 0)
10661
- throw new Error("probe timeout must be positive");
10662
- if (!Number.isFinite(compileTimeoutMs) || compileTimeoutMs <= 0)
10663
- throw new Error("compile timeout must be positive");
10664
- const expectedCapabilityIds = resolveExpectedCapabilityIds(projectRoot);
10665
- const sourceSha256 = workspaceSourceSha256(projectRoot);
10666
- stagingRoot = path26.join(cacheRoot, `.staging-${randomUUID()}`);
10667
- fs30.mkdirSync(stagingRoot, { recursive: false, mode: 448 });
10668
- const explicitEntry = options.entry ? resolveEntry(projectRoot, options.entry) : void 0;
10669
- const distRoot = path26.join(projectRoot, "dist");
10670
- const compiled = explicitEntry ? {
10671
- entry: explicitEntry,
10672
- applicationRoot: isInside2(distRoot, explicitEntry) ? distRoot : path26.dirname(explicitEntry)
10673
- } : await compileNestSource(
10674
- projectRoot,
10675
- stagingRoot,
10676
- compileTimeoutMs,
10677
- resolveNestTsconfig(projectRoot)
10678
- );
10679
- if (workspaceSourceSha256(projectRoot) !== sourceSha256) {
10680
- throw new Error("source changed during isolated Nest compilation");
10681
- }
10682
- const payloadRoot = path26.join(stagingRoot, "payload");
10683
- fs30.mkdirSync(payloadRoot, { recursive: true, mode: 493 });
10684
- const entry = STARTUP_BUNDLE_FILE;
10685
- const bundleFile = path26.join(
10686
- stagingRoot,
10687
- ...STARTUP_BUNDLE_FILE.split("/")
10688
- );
10689
- await buildStaticStartupPayload({
10690
- projectRoot,
10691
- entryFile: compiled.entry,
10692
- outputFile: bundleFile,
10693
- payloadRoot,
10694
- limits: {
10695
- maxFileBytes: MAX_GENERATION_FILE_BYTES,
10696
- maxFiles: MAX_GENERATION_FILES,
10697
- maxTotalBytes: MAX_GENERATION_BYTES
10698
- }
10699
- });
10700
- const files = indexPayload(payloadRoot);
10701
- const fileIndexContents = `${JSON.stringify(files, null, 2)}
10702
- `;
10703
- if (Buffer.byteLength(fileIndexContents) > MAX_FILE_INDEX_BYTES) {
10704
- throw new Error("generation file index exceeds 16 MiB");
10705
- }
10706
- fs30.writeFileSync(
10707
- path26.join(stagingRoot, "files.mtree.json"),
10708
- fileIndexContents,
10709
- { mode: 384 }
10710
- );
10711
- const runtime = runtimeIdentity();
10712
- const fileIndexSha256 = sha256(fileIndexContents);
10713
- const identity = {
10714
- schemaVersion: SCHEMA_VERSION,
10715
- sourceSha256,
10716
- expectedCapabilityIds,
10717
- runtime,
10718
- fileIndexSha256
10719
- };
10720
- const generationId = sha256(stableJson(identity));
10721
- await isolatedProbe(
10722
- projectRoot,
10723
- payloadRoot,
10724
- entry,
10725
- timeoutMs,
10726
- expectedCapabilityIds
10727
- );
10728
- if (workspaceSourceSha256(projectRoot) !== sourceSha256) {
10729
- throw new Error("source changed while building startup generation");
10730
- }
10731
- const manifest = {
10732
- generationId,
10733
- ...identity
10734
- };
10735
- writeBoundedJson(
10736
- path26.join(stagingRoot, "manifest.json"),
10737
- manifest,
10738
- MAX_MANIFEST_BYTES,
10739
- "startup generation manifest"
10740
- );
10741
- fs30.rmSync(path26.join(stagingRoot, ".compiled"), {
10742
- recursive: true,
10743
- force: true
10744
- });
10745
- const generationsRoot = path26.join(cacheRoot, "generations");
10746
- fs30.mkdirSync(generationsRoot, { recursive: true, mode: 448 });
10747
- const generationRoot = path26.join(generationsRoot, generationId);
10748
- const previousGenerations = fs30.readdirSync(generationsRoot);
10749
- if (previousGenerations.length > 1) {
10750
- throw new Error("startup generation directory is ambiguous");
10751
- }
10752
- const previous = previousGenerations[0];
10753
- const previousRoot = previous ? path26.join(generationsRoot, previous) : void 0;
10754
- const retiredRoot = previousRoot ? path26.join(cacheRoot, `.retired-${randomUUID()}`) : void 0;
10755
- if (previousRoot && retiredRoot) {
10756
- fs30.renameSync(previousRoot, retiredRoot);
10757
- }
10758
- try {
10759
- fs30.renameSync(stagingRoot, generationRoot);
10760
- } catch (publishError) {
10761
- if (previousRoot && retiredRoot && fs30.existsSync(retiredRoot)) {
10762
- fs30.renameSync(retiredRoot, previousRoot);
10763
- }
10764
- throw publishError;
10765
- }
10766
- if (previousRoot && retiredRoot) {
10767
- try {
10768
- fs30.rmSync(retiredRoot, { recursive: true, force: true });
10769
- } catch (pruneError) {
10770
- fs30.rmSync(generationRoot, { recursive: true, force: true });
10771
- fs30.renameSync(retiredRoot, previousRoot);
10772
- throw pruneError;
10773
- }
10774
- }
10775
- stagingRoot = void 0;
10776
- return {
10777
- built: true,
10778
- generationId,
10779
- generationRoot,
10780
- entryFile: path26.join(generationRoot, ...entry.split("/")),
10781
- manifestFile: path26.join(generationRoot, "manifest.json"),
10782
- reasons: [],
10783
- elapsedMs: Date.now() - startedAt
10784
- };
10785
- } catch (error) {
10786
- if (stagingRoot) fs30.rmSync(stagingRoot, { recursive: true, force: true });
10787
- if (cacheRoot) removeLegacyPointer(cacheRoot);
10788
- return {
10789
- built: false,
10790
- reasons: [error instanceof Error ? error.message : String(error)],
10791
- elapsedMs: Date.now() - startedAt
10792
- };
10793
- }
10794
- }
10795
-
10796
- // src/commands/build/index.ts
10797
- var getTokenCommand = {
10798
- name: "get-token",
10799
- description: "Get artifact upload credential (STI token)",
10800
- register(program) {
10801
- program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").requiredOption("--scene <scene>", "Build scene (pipeline, static)").option("--commit-id <id>", "Git commit ID (required for pipeline scene)").action(
10802
- async (options) => {
10803
- await getToken(options);
10804
- }
10805
- );
10806
- }
10807
- };
10808
- var uploadStaticCommand = {
10809
- name: "upload-static",
10810
- description: "Upload shared/static files to TOS",
10811
- register(program) {
10812
- program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").option(
10813
- "--static-dir <dir>",
10814
- "Static files directory",
10815
- UPLOAD_STATIC_DEFAULTS.staticDir
10816
- ).option(
10817
- "--tosutil-path <path>",
10818
- "Path to tosutil binary",
10819
- UPLOAD_STATIC_DEFAULTS.tosutilPath
10820
- ).option(
10821
- "--endpoint <endpoint>",
10822
- "TOS endpoint",
10823
- UPLOAD_STATIC_DEFAULTS.endpoint
10824
- ).option("--region <region>", "TOS region", UPLOAD_STATIC_DEFAULTS.region).action(async (options) => {
10825
- await uploadStatic(options);
10826
- });
8272
+ };
8273
+ var uploadStaticCommand = {
8274
+ name: "upload-static",
8275
+ description: "Upload shared/static files to TOS",
8276
+ register(program) {
8277
+ program.command(this.name).description(this.description).requiredOption("--app-id <id>", "Application ID").option("--static-dir <dir>", "Static files directory", UPLOAD_STATIC_DEFAULTS.staticDir).option("--tosutil-path <path>", "Path to tosutil binary", UPLOAD_STATIC_DEFAULTS.tosutilPath).option("--endpoint <endpoint>", "TOS endpoint", UPLOAD_STATIC_DEFAULTS.endpoint).option("--region <region>", "TOS region", UPLOAD_STATIC_DEFAULTS.region).action(async (options) => {
8278
+ await uploadStatic(options);
8279
+ });
10827
8280
  }
10828
8281
  };
10829
8282
  var preUploadStaticCommand = {
@@ -10835,39 +8288,10 @@ var preUploadStaticCommand = {
10835
8288
  });
10836
8289
  }
10837
8290
  };
10838
- var serverStartupBundleCommand = {
10839
- name: "server-startup-bundle",
10840
- description: "Build and isolate-probe a recycle-only NestJS startup generation",
10841
- register(program) {
10842
- program.command(this.name).description(this.description).option("--project-root <dir>", "Application project root", process.cwd()).option(
10843
- "--probe-timeout-ms <ms>",
10844
- "Isolated availability probe timeout in milliseconds",
10845
- "10000"
10846
- ).action(
10847
- async (options) => {
10848
- const probeTimeoutMs = Number(options.probeTimeoutMs);
10849
- if (!Number.isFinite(probeTimeoutMs) || probeTimeoutMs <= 0) {
10850
- throw new Error("--probe-timeout-ms must be a positive number");
10851
- }
10852
- const result = await buildServerStartupBundle({
10853
- projectRoot: options.projectRoot,
10854
- probeTimeoutMs
10855
- });
10856
- console.log(JSON.stringify(result));
10857
- if (!result.built) process.exitCode = 2;
10858
- }
10859
- );
10860
- }
10861
- };
10862
8291
  var buildCommandGroup = {
10863
8292
  name: "build",
10864
8293
  description: "Build related commands",
10865
- commands: [
10866
- getTokenCommand,
10867
- uploadStaticCommand,
10868
- preUploadStaticCommand,
10869
- serverStartupBundleCommand
10870
- ]
8294
+ commands: [getTokenCommand, uploadStaticCommand, preUploadStaticCommand]
10871
8295
  };
10872
8296
 
10873
8297
  // src/commands/index.ts
@@ -10885,13 +8309,13 @@ var commands = [
10885
8309
 
10886
8310
  // src/index.ts
10887
8311
  for (const filename of [".env.local", ".env"]) {
10888
- const envPath = path27.join(process.cwd(), filename);
10889
- if (fs31.existsSync(envPath)) {
8312
+ const envPath = path25.join(process.cwd(), filename);
8313
+ if (fs29.existsSync(envPath)) {
10890
8314
  dotenvConfig({ path: envPath });
10891
8315
  }
10892
8316
  }
10893
- var __dirname = path27.dirname(fileURLToPath6(import.meta.url));
10894
- var pkg = JSON.parse(fs31.readFileSync(path27.join(__dirname, "../package.json"), "utf-8"));
8317
+ var __dirname = path25.dirname(fileURLToPath5(import.meta.url));
8318
+ var pkg = JSON.parse(fs29.readFileSync(path25.join(__dirname, "../package.json"), "utf-8"));
10895
8319
  var cli = new FullstackCLI(pkg.version);
10896
8320
  cli.useAll(commands);
10897
8321
  cli.run();