@lark-apaas/fullstack-cli 1.1.59-alpha.20260717075919 → 1.1.59-alpha.20260717162925

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +557 -12
  2. package/package.json +4 -1
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/index.ts
2
- import fs29 from "fs";
3
- import path25 from "path";
2
+ import fs30 from "fs";
3
+ import path26 from "path";
4
4
  import { fileURLToPath as fileURLToPath5 } from "url";
5
5
  import { config as dotenvConfig } from "dotenv";
6
6
 
@@ -4921,7 +4921,7 @@ var PROMPT_PATTERNS = [
4921
4921
  { pattern: /proceed\?/i, answer: "y\n" }
4922
4922
  ];
4923
4923
  async function executeShadcnAdd(registryItemPath) {
4924
- return new Promise((resolve2) => {
4924
+ return new Promise((resolve3) => {
4925
4925
  let output = "";
4926
4926
  const args = ["--yes", "shadcn@3.8.2", "add", registryItemPath];
4927
4927
  const ptyProcess = pty.spawn("npx", args, {
@@ -4947,7 +4947,7 @@ async function executeShadcnAdd(registryItemPath) {
4947
4947
  });
4948
4948
  const timeoutId = setTimeout(() => {
4949
4949
  ptyProcess.kill();
4950
- resolve2({
4950
+ resolve3({
4951
4951
  success: false,
4952
4952
  files: [],
4953
4953
  error: "\u6267\u884C\u8D85\u65F6"
@@ -4958,7 +4958,7 @@ async function executeShadcnAdd(registryItemPath) {
4958
4958
  const success = exitCode === 0;
4959
4959
  const filePaths = parseOutput(output);
4960
4960
  const files = filePaths.map(toFileInfo);
4961
- resolve2({
4961
+ resolve3({
4962
4962
  success,
4963
4963
  files,
4964
4964
  error: success ? void 0 : output || `Process exited with code ${exitCode}`
@@ -4969,12 +4969,12 @@ async function executeShadcnAdd(registryItemPath) {
4969
4969
 
4970
4970
  // src/commands/component/add.handler.ts
4971
4971
  function runActionPluginInit() {
4972
- return new Promise((resolve2) => {
4972
+ return new Promise((resolve3) => {
4973
4973
  execFile("fullstack-cli", ["action-plugin", "init"], { cwd: process.cwd(), stdio: "ignore" }, (error) => {
4974
4974
  if (error) {
4975
4975
  debug("action-plugin init \u5931\u8D25: %s", error.message);
4976
4976
  }
4977
- resolve2();
4977
+ resolve3();
4978
4978
  });
4979
4979
  });
4980
4980
  }
@@ -8098,6 +8098,527 @@ async function preUploadStatic(options) {
8098
8098
  }
8099
8099
  }
8100
8100
 
8101
+ // src/commands/build/preview-server-artifact.handler.ts
8102
+ import * as fs29 from "fs";
8103
+ import * as os3 from "os";
8104
+ import * as path25 from "path";
8105
+ import { builtinModules, createRequire as createRequire3 } from "module";
8106
+ import { build } from "esbuild";
8107
+ import { parse as parse2 } from "acorn";
8108
+ import { simple as walkSimple } from "acorn-walk";
8109
+ var STATIC_PLUGIN_REGISTRY_SYMBOL = "@lark-apaas/nestjs-capability/static-plugin-registry";
8110
+ var STATIC_PLUGIN_REGISTRY_PROTOCOL_VERSION = 1;
8111
+ var OPTIONAL_DEPENDENCY_STUBS = [
8112
+ "@nestjs/microservices",
8113
+ "@nestjs/microservices/microservices-module",
8114
+ "@nestjs/websockets/socket-module",
8115
+ "fsevents"
8116
+ ];
8117
+ var BUILTIN_MODULES = /* @__PURE__ */ new Set([
8118
+ ...builtinModules,
8119
+ ...builtinModules.map((moduleName) => `node:${moduleName}`)
8120
+ ]);
8121
+ function toAbsolutePath(projectRoot, candidate) {
8122
+ return path25.isAbsolute(candidate) ? candidate : path25.resolve(projectRoot, candidate);
8123
+ }
8124
+ function readJson(filePath) {
8125
+ return JSON.parse(fs29.readFileSync(filePath, "utf8"));
8126
+ }
8127
+ function findPackageRoot(entryPath) {
8128
+ let current = path25.dirname(entryPath);
8129
+ const filesystemRoot = path25.parse(current).root;
8130
+ while (current !== filesystemRoot) {
8131
+ if (fs29.existsSync(path25.join(current, "package.json"))) {
8132
+ return current;
8133
+ }
8134
+ current = path25.dirname(current);
8135
+ }
8136
+ return null;
8137
+ }
8138
+ function findNativeAddons(root) {
8139
+ const nativeAddons = [];
8140
+ const pending = [root];
8141
+ while (pending.length > 0) {
8142
+ const current = pending.pop();
8143
+ if (!current) {
8144
+ continue;
8145
+ }
8146
+ for (const entry of fs29.readdirSync(current, { withFileTypes: true })) {
8147
+ const entryPath = path25.join(current, entry.name);
8148
+ if (entry.isSymbolicLink()) {
8149
+ continue;
8150
+ }
8151
+ if (entry.isDirectory()) {
8152
+ pending.push(entryPath);
8153
+ } else if (entry.isFile() && entry.name.endsWith(".node")) {
8154
+ nativeAddons.push(entryPath);
8155
+ }
8156
+ }
8157
+ }
8158
+ return nativeAddons.sort();
8159
+ }
8160
+ function resolveActionPlugins(projectRoot, packageJson) {
8161
+ const configuredPlugins = packageJson.actionPlugins;
8162
+ if (!configuredPlugins || typeof configuredPlugins !== "object") {
8163
+ return { plugins: [], reasons: [] };
8164
+ }
8165
+ const projectRequire = createRequire3(path25.join(projectRoot, "package.json"));
8166
+ const plugins = [];
8167
+ const reasons = [];
8168
+ for (const name of Object.keys(configuredPlugins).sort()) {
8169
+ let entryPath;
8170
+ try {
8171
+ entryPath = projectRequire.resolve(name);
8172
+ } catch (error) {
8173
+ const message = error instanceof Error ? error.message : String(error);
8174
+ reasons.push(`Action Plugin ${name} \u65E0\u6CD5\u89E3\u6790: ${message}`);
8175
+ continue;
8176
+ }
8177
+ const packageRoot = findPackageRoot(entryPath);
8178
+ if (!packageRoot) {
8179
+ reasons.push(`Action Plugin ${name} \u65E0\u6CD5\u5B9A\u4F4D package.json: ${entryPath}`);
8180
+ continue;
8181
+ }
8182
+ const nativeAddons = findNativeAddons(packageRoot);
8183
+ if (nativeAddons.length > 0) {
8184
+ const relativeAddons = nativeAddons.map(
8185
+ (filePath) => path25.relative(packageRoot, filePath)
8186
+ );
8187
+ reasons.push(
8188
+ `Action Plugin ${name} \u5305\u542B\u539F\u751F\u6269\u5C55\uFF0C\u4E0D\u80FD\u751F\u6210\u8DE8\u6C99\u7BB1\u5355 bundle: ${relativeAddons.join(", ")}`
8189
+ );
8190
+ continue;
8191
+ }
8192
+ const manifestPath = path25.join(packageRoot, "manifest.json");
8193
+ let manifest;
8194
+ if (fs29.existsSync(manifestPath)) {
8195
+ try {
8196
+ manifest = readJson(manifestPath);
8197
+ } catch (error) {
8198
+ const message = error instanceof Error ? error.message : String(error);
8199
+ reasons.push(
8200
+ `Action Plugin ${name} \u7684 manifest.json \u65E0\u6CD5\u89E3\u6790: ${message}`
8201
+ );
8202
+ continue;
8203
+ }
8204
+ }
8205
+ plugins.push({ name, entryPath, manifest });
8206
+ }
8207
+ if (reasons.length === 0 && plugins.length > 0) {
8208
+ try {
8209
+ const capabilityRuntime = projectRequire(
8210
+ "@lark-apaas/nestjs-capability"
8211
+ );
8212
+ if (capabilityRuntime.STATIC_PLUGIN_REGISTRY_PROTOCOL_VERSION !== STATIC_PLUGIN_REGISTRY_PROTOCOL_VERSION) {
8213
+ reasons.push(
8214
+ `@lark-apaas/nestjs-capability \u672A\u63D0\u4F9B\u517C\u5BB9\u7684 STATIC_PLUGIN_REGISTRY_PROTOCOL_VERSION=${STATIC_PLUGIN_REGISTRY_PROTOCOL_VERSION}`
8215
+ );
8216
+ }
8217
+ } catch (error) {
8218
+ const message = error instanceof Error ? error.message : String(error);
8219
+ reasons.push(
8220
+ `@lark-apaas/nestjs-capability \u65E0\u6CD5\u52A0\u8F7D\uFF0C\u7F3A\u5C11 STATIC_PLUGIN_REGISTRY_PROTOCOL_VERSION=${STATIC_PLUGIN_REGISTRY_PROTOCOL_VERSION}: ${message}`
8221
+ );
8222
+ }
8223
+ }
8224
+ return { plugins, reasons };
8225
+ }
8226
+ function generateBootstrap(entryPath, plugins) {
8227
+ const lines = [`'use strict';`, `const __staticPluginRegistry = new Map();`];
8228
+ plugins.forEach((plugin, index) => {
8229
+ const moduleVariable = `__staticPlugin${index}`;
8230
+ lines.push(
8231
+ `const ${moduleVariable} = require(${JSON.stringify(plugin.entryPath)});`
8232
+ );
8233
+ lines.push(
8234
+ `__staticPluginRegistry.set(${JSON.stringify(plugin.name)}, { module: ${moduleVariable}, manifest: ${JSON.stringify(plugin.manifest ?? null)} });`
8235
+ );
8236
+ });
8237
+ lines.push(
8238
+ `globalThis[Symbol.for(${JSON.stringify(STATIC_PLUGIN_REGISTRY_SYMBOL)})] = __staticPluginRegistry;`,
8239
+ `require(${JSON.stringify(entryPath)});`,
8240
+ ""
8241
+ );
8242
+ return lines.join("\n");
8243
+ }
8244
+ function classTransformerStorageResolver(projectRoot) {
8245
+ const projectRequire = createRequire3(path25.join(projectRoot, "package.json"));
8246
+ return {
8247
+ name: "class-transformer-storage-resolver",
8248
+ setup(esbuild) {
8249
+ esbuild.onResolve({ filter: /^class-transformer\/storage$/ }, () => {
8250
+ try {
8251
+ return {
8252
+ path: projectRequire.resolve("class-transformer/cjs/storage.js")
8253
+ };
8254
+ } catch {
8255
+ return void 0;
8256
+ }
8257
+ });
8258
+ }
8259
+ };
8260
+ }
8261
+ function optionalDependencyStubPlugin() {
8262
+ const stubbedDependencies = /* @__PURE__ */ new Set();
8263
+ const escapedNames = OPTIONAL_DEPENDENCY_STUBS.map(
8264
+ (name) => name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
8265
+ );
8266
+ const filter = new RegExp(`^(?:${escapedNames.join("|")})$`);
8267
+ return {
8268
+ stubbedDependencies,
8269
+ plugin: {
8270
+ name: "preview-optional-dependency-stubs",
8271
+ setup(esbuild) {
8272
+ esbuild.onResolve({ filter }, (args) => {
8273
+ stubbedDependencies.add(args.path);
8274
+ return {
8275
+ path: args.path,
8276
+ namespace: "preview-optional-dependency"
8277
+ };
8278
+ });
8279
+ esbuild.onLoad(
8280
+ { filter: /.*/, namespace: "preview-optional-dependency" },
8281
+ (args) => ({
8282
+ contents: `
8283
+ const error = new Error(${JSON.stringify(
8284
+ `Optional dependency is unavailable in Preview Artifact: ${args.path}`
8285
+ )});
8286
+ error.code = 'MODULE_NOT_FOUND';
8287
+ throw error;
8288
+ `,
8289
+ loader: "js"
8290
+ })
8291
+ );
8292
+ }
8293
+ }
8294
+ };
8295
+ }
8296
+ function isStaticString(node) {
8297
+ if (!node) {
8298
+ return false;
8299
+ }
8300
+ if (node.type === "Literal") {
8301
+ return typeof node.value === "string";
8302
+ }
8303
+ return node.type === "TemplateLiteral" && node.expressions.length === 0;
8304
+ }
8305
+ function staticPropertyName(node) {
8306
+ if (node.type !== "MemberExpression") {
8307
+ return void 0;
8308
+ }
8309
+ if (!node.computed && node.property.type === "Identifier") {
8310
+ return node.property.name;
8311
+ }
8312
+ if (node.computed && node.property.type === "Literal" && typeof node.property.value === "string") {
8313
+ return node.property.value;
8314
+ }
8315
+ return void 0;
8316
+ }
8317
+ function auditBundleClosure(outfile, stubbedDependencies) {
8318
+ const ast = parse2(fs29.readFileSync(outfile, "utf8"), {
8319
+ ecmaVersion: "latest",
8320
+ sourceType: "script",
8321
+ allowHashBang: true
8322
+ });
8323
+ let dynamicRequireCount = 0;
8324
+ let dynamicImportCount = 0;
8325
+ let createRequireCount = 0;
8326
+ let requireResolveCount = 0;
8327
+ let runtimeFileReadCount = 0;
8328
+ const runtimeFileReads = /* @__PURE__ */ new Set([
8329
+ "access",
8330
+ "accessSync",
8331
+ "createReadStream",
8332
+ "open",
8333
+ "openSync",
8334
+ "readFile",
8335
+ "readFileSync",
8336
+ "readdir",
8337
+ "readdirSync",
8338
+ "stat",
8339
+ "statSync"
8340
+ ]);
8341
+ walkSimple(ast, {
8342
+ CallExpression(node) {
8343
+ if (node.callee.type === "Identifier" && node.callee.name === "require" && !isStaticString(node.arguments[0])) {
8344
+ dynamicRequireCount += 1;
8345
+ }
8346
+ if (node.callee.type === "Identifier" && node.callee.name === "createRequire" || staticPropertyName(node.callee) === "createRequire") {
8347
+ createRequireCount += 1;
8348
+ }
8349
+ const propertyName = staticPropertyName(node.callee);
8350
+ if (propertyName === "resolve" && node.callee.type === "MemberExpression" && node.callee.object.type === "Identifier" && node.callee.object.name === "require") {
8351
+ requireResolveCount += 1;
8352
+ }
8353
+ if (propertyName && runtimeFileReads.has(propertyName)) {
8354
+ runtimeFileReadCount += 1;
8355
+ }
8356
+ },
8357
+ ImportExpression(node) {
8358
+ if (!isStaticString(node.source)) {
8359
+ dynamicImportCount += 1;
8360
+ }
8361
+ }
8362
+ });
8363
+ const risks = [];
8364
+ if (dynamicRequireCount > 0) {
8365
+ risks.push(`bundle retains ${dynamicRequireCount} dynamic require call(s)`);
8366
+ }
8367
+ if (dynamicImportCount > 0) {
8368
+ risks.push(`bundle retains ${dynamicImportCount} dynamic import call(s)`);
8369
+ }
8370
+ if (createRequireCount > 0 || requireResolveCount > 0) {
8371
+ risks.push(
8372
+ `bundle retains runtime module resolution (createRequire=${createRequireCount}, require.resolve=${requireResolveCount})`
8373
+ );
8374
+ }
8375
+ if (runtimeFileReadCount > 0) {
8376
+ risks.push(
8377
+ `bundle retains ${runtimeFileReadCount} runtime filesystem read call(s)`
8378
+ );
8379
+ }
8380
+ if (stubbedDependencies.length > 0) {
8381
+ risks.push(
8382
+ `bundle stubs optional dependencies: ${stubbedDependencies.join(", ")}`
8383
+ );
8384
+ }
8385
+ return risks;
8386
+ }
8387
+ function collectExternalImports(metafile, outfile) {
8388
+ const normalizedOutfile = path25.resolve(outfile);
8389
+ const output = Object.entries(metafile.outputs).find(
8390
+ ([outputPath]) => path25.resolve(outputPath) === normalizedOutfile
8391
+ )?.[1];
8392
+ if (!output) {
8393
+ return [];
8394
+ }
8395
+ return Array.from(
8396
+ new Set(
8397
+ output.imports.filter((importRecord) => importRecord.external).map((importRecord) => importRecord.path).filter(
8398
+ (importPath) => !BUILTIN_MODULES.has(importPath) && !importPath.startsWith("node:")
8399
+ )
8400
+ )
8401
+ ).sort();
8402
+ }
8403
+ function formatBuildError(error) {
8404
+ if (!error || typeof error !== "object" || !("errors" in error)) {
8405
+ return [error instanceof Error ? error.message : String(error)];
8406
+ }
8407
+ const errors = error.errors;
8408
+ if (!errors || errors.length === 0) {
8409
+ return [error instanceof Error ? error.message : String(error)];
8410
+ }
8411
+ return errors.map((item) => {
8412
+ const location = item.location?.file ? `${item.location.file}${item.location.line ? `:${item.location.line}` : ""}: ` : "";
8413
+ return `${location}${item.text ?? "unknown esbuild error"}`;
8414
+ });
8415
+ }
8416
+ function removePublishedArtifact(outfile, metadataFile) {
8417
+ fs29.rmSync(outfile, { force: true });
8418
+ fs29.rmSync(metadataFile, { force: true });
8419
+ }
8420
+ function bestEffortRemove(targetPath, options = {}) {
8421
+ if (!targetPath) {
8422
+ return;
8423
+ }
8424
+ try {
8425
+ fs29.rmSync(targetPath, { force: true, recursive: options.recursive });
8426
+ } catch {
8427
+ }
8428
+ }
8429
+ function outputPathConflicts(entryPath, packageJsonPath, outfile, metadataFile) {
8430
+ const reasons = [];
8431
+ if (outfile === metadataFile) {
8432
+ reasons.push("bundle \u4E0E metadata \u8F93\u51FA\u8DEF\u5F84\u4E0D\u80FD\u76F8\u540C");
8433
+ }
8434
+ const protectedInputs = /* @__PURE__ */ new Map([
8435
+ [entryPath, "Nest \u7F16\u8BD1\u5165\u53E3"],
8436
+ [packageJsonPath, "package.json"]
8437
+ ]);
8438
+ for (const [outputPath, outputName] of [
8439
+ [outfile, "bundle"],
8440
+ [metadataFile, "metadata"]
8441
+ ]) {
8442
+ const protectedName = protectedInputs.get(outputPath);
8443
+ if (protectedName) {
8444
+ reasons.push(
8445
+ `${outputName} \u8F93\u51FA\u8DEF\u5F84\u4E0D\u80FD\u8986\u76D6 ${protectedName}: ${outputPath}`
8446
+ );
8447
+ }
8448
+ }
8449
+ return reasons;
8450
+ }
8451
+ async function buildPreviewServerArtifact(options) {
8452
+ const startedAt = Date.now();
8453
+ const projectRoot = path25.resolve(options.projectRoot);
8454
+ const entryPath = toAbsolutePath(
8455
+ projectRoot,
8456
+ options.entry ?? "dist/main.js"
8457
+ );
8458
+ const outfile = toAbsolutePath(
8459
+ projectRoot,
8460
+ options.outfile ?? ".preview-artifact/server.bundle.cjs"
8461
+ );
8462
+ const metadataFile = toAbsolutePath(
8463
+ projectRoot,
8464
+ options.metadataFile ?? `${outfile}.meta.json`
8465
+ );
8466
+ const packageJsonPath = path25.join(projectRoot, "package.json");
8467
+ let pluginCount = 0;
8468
+ let outputCleared = false;
8469
+ let phase = "\u6821\u9A8C\u8F93\u5165";
8470
+ let tempRoot;
8471
+ let tempOutputRoot;
8472
+ let tempMetadataFile;
8473
+ const failed = (reasons) => ({
8474
+ built: false,
8475
+ elapsedMs: Date.now() - startedAt,
8476
+ pluginCount,
8477
+ reasons
8478
+ });
8479
+ const pathConflicts = outputPathConflicts(
8480
+ entryPath,
8481
+ packageJsonPath,
8482
+ outfile,
8483
+ metadataFile
8484
+ );
8485
+ if (pathConflicts.length > 0) {
8486
+ return failed(pathConflicts);
8487
+ }
8488
+ if (!fs29.existsSync(entryPath)) {
8489
+ return failed([`Nest \u7F16\u8BD1\u5165\u53E3\u4E0D\u5B58\u5728: ${entryPath}`]);
8490
+ }
8491
+ if (!fs29.existsSync(packageJsonPath)) {
8492
+ return failed([`package.json \u4E0D\u5B58\u5728: ${packageJsonPath}`]);
8493
+ }
8494
+ try {
8495
+ phase = `\u89E3\u6790 ${packageJsonPath}`;
8496
+ const packageJson = readJson(packageJsonPath);
8497
+ phase = "\u89E3\u6790 Action Plugin";
8498
+ const { plugins, reasons } = resolveActionPlugins(projectRoot, packageJson);
8499
+ pluginCount = plugins.length;
8500
+ phase = "\u6E05\u7406\u65E7 Preview Artifact";
8501
+ removePublishedArtifact(outfile, metadataFile);
8502
+ outputCleared = true;
8503
+ if (reasons.length > 0) {
8504
+ return failed(reasons);
8505
+ }
8506
+ phase = "\u521B\u5EFA Preview Artifact \u4E34\u65F6\u76EE\u5F55";
8507
+ fs29.mkdirSync(path25.dirname(outfile), { recursive: true });
8508
+ fs29.mkdirSync(path25.dirname(metadataFile), { recursive: true });
8509
+ tempRoot = fs29.mkdtempSync(
8510
+ path25.join(os3.tmpdir(), "preview-server-artifact-")
8511
+ );
8512
+ tempOutputRoot = fs29.mkdtempSync(
8513
+ path25.join(path25.dirname(outfile), ".preview-server-artifact-")
8514
+ );
8515
+ const bootstrapPath = path25.join(tempRoot, "bootstrap.cjs");
8516
+ const tempOutfile = path25.join(tempOutputRoot, path25.basename(outfile));
8517
+ tempMetadataFile = path25.join(
8518
+ path25.dirname(metadataFile),
8519
+ `.${path25.basename(metadataFile)}.${process.pid}.${Date.now()}.tmp`
8520
+ );
8521
+ fs29.writeFileSync(bootstrapPath, generateBootstrap(entryPath, plugins));
8522
+ const optionalDependencies = optionalDependencyStubPlugin();
8523
+ const buildOptions = {
8524
+ absWorkingDir: projectRoot,
8525
+ entryPoints: [bootstrapPath],
8526
+ outfile: tempOutfile,
8527
+ bundle: true,
8528
+ platform: "node",
8529
+ format: "cjs",
8530
+ target: "node22",
8531
+ treeShaking: true,
8532
+ keepNames: true,
8533
+ legalComments: "none",
8534
+ sourcemap: false,
8535
+ metafile: true,
8536
+ logLevel: "silent",
8537
+ plugins: [
8538
+ classTransformerStorageResolver(projectRoot),
8539
+ optionalDependencies.plugin
8540
+ ]
8541
+ };
8542
+ phase = "\u6267\u884C esbuild";
8543
+ const buildResult2 = await build(buildOptions);
8544
+ if (!buildResult2.metafile) {
8545
+ throw new Error("esbuild \u672A\u8FD4\u56DE metafile");
8546
+ }
8547
+ const externalImports = collectExternalImports(
8548
+ buildResult2.metafile,
8549
+ tempOutfile
8550
+ );
8551
+ if (externalImports.length > 0) {
8552
+ return failed([`bundle \u6B8B\u7559\u8FD0\u884C\u65F6\u4F9D\u8D56: ${externalImports.join(", ")}`]);
8553
+ }
8554
+ phase = "\u5BA1\u8BA1 bundle \u8FD0\u884C\u65F6\u95ED\u5305";
8555
+ const stubbedOptionalDependencies = Array.from(
8556
+ optionalDependencies.stubbedDependencies
8557
+ ).sort();
8558
+ const closureRisks = auditBundleClosure(
8559
+ tempOutfile,
8560
+ stubbedOptionalDependencies
8561
+ );
8562
+ const closureStatus = closureRisks.length === 0 ? "static-audit-clean" : "runtime-validation-required";
8563
+ const metadata = {
8564
+ version: 1,
8565
+ entry: entryPath,
8566
+ outfile,
8567
+ bundleBytes: fs29.statSync(tempOutfile).size,
8568
+ inputFiles: Object.keys(buildResult2.metafile.inputs).length,
8569
+ externalImports,
8570
+ actionPlugins: plugins.map((plugin) => plugin.name),
8571
+ closureStatus,
8572
+ closureRisks,
8573
+ stubbedOptionalDependencies,
8574
+ runtimeProbeStatus: "not-run",
8575
+ consumable: false,
8576
+ elapsedMs: Date.now() - startedAt
8577
+ };
8578
+ phase = "\u53D1\u5E03 bundle \u4E0E metadata";
8579
+ fs29.writeFileSync(
8580
+ tempMetadataFile,
8581
+ `${JSON.stringify(metadata, null, 2)}
8582
+ `
8583
+ );
8584
+ fs29.renameSync(tempOutfile, outfile);
8585
+ fs29.renameSync(tempMetadataFile, metadataFile);
8586
+ return {
8587
+ built: true,
8588
+ outfile,
8589
+ metadataFile,
8590
+ bundleBytes: metadata.bundleBytes,
8591
+ inputFiles: metadata.inputFiles,
8592
+ externalImports,
8593
+ pluginCount,
8594
+ closureStatus,
8595
+ closureRisks,
8596
+ stubbedOptionalDependencies,
8597
+ runtimeProbeStatus: "not-run",
8598
+ consumable: false,
8599
+ elapsedMs: metadata.elapsedMs
8600
+ };
8601
+ } catch (error) {
8602
+ const reasons = formatBuildError(error).map(
8603
+ (reason) => `${phase}: ${reason}`
8604
+ );
8605
+ if (outputCleared) {
8606
+ try {
8607
+ removePublishedArtifact(outfile, metadataFile);
8608
+ } catch (cleanupError) {
8609
+ reasons.push(
8610
+ `\u6E05\u7406\u5931\u8D25\u4EA7\u7269: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`
8611
+ );
8612
+ }
8613
+ }
8614
+ return failed(reasons);
8615
+ } finally {
8616
+ bestEffortRemove(tempRoot, { recursive: true });
8617
+ bestEffortRemove(tempOutputRoot, { recursive: true });
8618
+ bestEffortRemove(tempMetadataFile);
8619
+ }
8620
+ }
8621
+
8101
8622
  // src/commands/build/index.ts
8102
8623
  var getTokenCommand = {
8103
8624
  name: "get-token",
@@ -8126,10 +8647,34 @@ var preUploadStaticCommand = {
8126
8647
  });
8127
8648
  }
8128
8649
  };
8650
+ var previewServerArtifactCommand = {
8651
+ name: "preview-server-artifact",
8652
+ description: "Build and audit a single-file Nest preview server artifact",
8653
+ register(program) {
8654
+ program.command(this.name).description(this.description).option("--project-root <dir>", "Application project root", process.cwd()).option("--entry <file>", "Compiled Nest entry", "dist/main.js").option(
8655
+ "--outfile <file>",
8656
+ "Output bundle",
8657
+ ".preview-artifact/server.bundle.cjs"
8658
+ ).option("--metadata-file <file>", "Output build metadata file").action(
8659
+ async (options) => {
8660
+ const result = await buildPreviewServerArtifact(options);
8661
+ console.log(JSON.stringify(result));
8662
+ if (!result.built) {
8663
+ process.exitCode = 2;
8664
+ }
8665
+ }
8666
+ );
8667
+ }
8668
+ };
8129
8669
  var buildCommandGroup = {
8130
8670
  name: "build",
8131
8671
  description: "Build related commands",
8132
- commands: [getTokenCommand, uploadStaticCommand, preUploadStaticCommand]
8672
+ commands: [
8673
+ getTokenCommand,
8674
+ uploadStaticCommand,
8675
+ preUploadStaticCommand,
8676
+ previewServerArtifactCommand
8677
+ ]
8133
8678
  };
8134
8679
 
8135
8680
  // src/commands/index.ts
@@ -8146,12 +8691,12 @@ var commands = [
8146
8691
  ];
8147
8692
 
8148
8693
  // src/index.ts
8149
- var envPath = path25.join(process.cwd(), ".env");
8150
- if (fs29.existsSync(envPath)) {
8694
+ var envPath = path26.join(process.cwd(), ".env");
8695
+ if (fs30.existsSync(envPath)) {
8151
8696
  dotenvConfig({ path: envPath });
8152
8697
  }
8153
- var __dirname = path25.dirname(fileURLToPath5(import.meta.url));
8154
- var pkg = JSON.parse(fs29.readFileSync(path25.join(__dirname, "../package.json"), "utf-8"));
8698
+ var __dirname = path26.dirname(fileURLToPath5(import.meta.url));
8699
+ var pkg = JSON.parse(fs30.readFileSync(path26.join(__dirname, "../package.json"), "utf-8"));
8155
8700
  var cli = new FullstackCLI(pkg.version);
8156
8701
  cli.useAll(commands);
8157
8702
  cli.run();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-cli",
3
- "version": "1.1.59-alpha.20260717075919",
3
+ "version": "1.1.59-alpha.20260717162925",
4
4
  "description": "CLI tool for fullstack template management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -34,12 +34,15 @@
34
34
  "@lark-apaas/http-client": "^0.1.7",
35
35
  "@lydell/node-pty": "1.1.0",
36
36
  "@vercel/nft": "^0.30.3",
37
+ "acorn": "^8.16.0",
38
+ "acorn-walk": "^8.3.5",
37
39
  "commander": "^13.0.0",
38
40
  "debug": "^4.4.3",
39
41
  "dotenv": "^16.0.0",
40
42
  "drizzle-kit": "0.31.5",
41
43
  "drizzle-orm": "0.44.6",
42
44
  "es-toolkit": "^1.44.0",
45
+ "esbuild": "^0.27.0",
43
46
  "inflection": "^3.0.2",
44
47
  "pinyin-pro": "^3.27.0",
45
48
  "postgres": "^3.4.3",