@lark-apaas/fullstack-cli 1.1.59-alpha.20260722041318 → 1.1.59-alpha.20260722071909

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
@@ -9829,6 +9829,22 @@ function createPreviewArtifactSwitcher(options) {
9829
9829
  }
9830
9830
 
9831
9831
  // src/commands/preview-artifact/runtime.ts
9832
+ function measure(timings, phase, operation, detail) {
9833
+ const startedAt = Date.now();
9834
+ try {
9835
+ return operation();
9836
+ } finally {
9837
+ timings.push({ phase, durationMs: Date.now() - startedAt, ...detail });
9838
+ }
9839
+ }
9840
+ async function measureAsync(timings, phase, operation, detail) {
9841
+ const startedAt = Date.now();
9842
+ try {
9843
+ return await operation();
9844
+ } finally {
9845
+ timings.push({ phase, durationMs: Date.now() - startedAt, ...detail });
9846
+ }
9847
+ }
9832
9848
  function sleep2(ms) {
9833
9849
  return new Promise((resolve9) => setTimeout(resolve9, ms));
9834
9850
  }
@@ -9937,16 +9953,21 @@ async function waitForCachedRuntime(origin, appBasePath, businessApiPath, timeou
9937
9953
  throw new Error("cached runtime readiness timed out");
9938
9954
  }
9939
9955
  async function startPreviewArtifactRuntime(options) {
9940
- const resolved = resolveCurrentPreviewArtifact({
9941
- storeRoot: options.storeRoot,
9942
- nodeVersion: process.version,
9943
- platform: process.platform,
9944
- arch: process.arch,
9945
- buildEnvironmentSha256: previewArtifactBuildEnvironmentHash(
9946
- options.environment,
9947
- options.appBasePath
9948
- )
9949
- });
9956
+ const timings = [...options.initialTimings ?? []];
9957
+ const resolved = measure(
9958
+ timings,
9959
+ "metadata_validate",
9960
+ () => resolveCurrentPreviewArtifact({
9961
+ storeRoot: options.storeRoot,
9962
+ nodeVersion: process.version,
9963
+ platform: process.platform,
9964
+ arch: process.arch,
9965
+ buildEnvironmentSha256: previewArtifactBuildEnvironmentHash(
9966
+ options.environment,
9967
+ options.appBasePath
9968
+ )
9969
+ })
9970
+ );
9950
9971
  if (!resolved.resolved) return { started: false, reasons: resolved.reasons };
9951
9972
  const runtimeRoot = path32.resolve(options.runtimeRoot);
9952
9973
  const markerFile = path32.resolve(options.markerFile);
@@ -9971,14 +9992,22 @@ async function startPreviewArtifactRuntime(options) {
9971
9992
  path32.join(runtimeRoot, `${resolved.generationId}-`)
9972
9993
  );
9973
9994
  const runtimeBundle = path32.join(runtimeDir, "server.bundle.cjs");
9974
- fs36.copyFileSync(
9975
- path32.join(resolved.generationDir, "server.bundle.cjs"),
9976
- runtimeBundle
9995
+ const serverSource = path32.join(resolved.generationDir, "server.bundle.cjs");
9996
+ measure(
9997
+ timings,
9998
+ "server_materialize",
9999
+ () => fs36.copyFileSync(serverSource, runtimeBundle),
10000
+ { bytes: resolved.manifest.files.server.bytes }
9977
10001
  );
9978
10002
  const clientRoot = path32.join(runtimeDir, "dist", "client");
9979
- extractClientArchive(
9980
- path32.join(resolved.generationDir, "client.zip"),
9981
- clientRoot
10003
+ measure(
10004
+ timings,
10005
+ "client_archive_inspect_extract",
10006
+ () => extractClientArchive(
10007
+ path32.join(resolved.generationDir, "client.zip"),
10008
+ clientRoot
10009
+ ),
10010
+ { bytes: resolved.manifest.files.client.bytes }
9982
10011
  );
9983
10012
  const cachedServerPort = options.cachedServerPort === 0 ? await reservePort2() : options.cachedServerPort;
9984
10013
  cachedRuntime = spawn3(process.execPath, [runtimeBundle], {
@@ -9992,13 +10021,25 @@ async function startPreviewArtifactRuntime(options) {
9992
10021
  }
9993
10022
  });
9994
10023
  const cachedOrigin = `http://127.0.0.1:${cachedServerPort}`;
9995
- await waitForCachedRuntime(
9996
- cachedOrigin,
9997
- options.appBasePath,
9998
- options.businessApiPath,
9999
- options.startupTimeoutMs ?? 3e4,
10000
- cachedRuntime
10024
+ await measureAsync(
10025
+ timings,
10026
+ "backend_spawn_to_business_ready",
10027
+ () => waitForCachedRuntime(
10028
+ cachedOrigin,
10029
+ options.appBasePath,
10030
+ options.businessApiPath,
10031
+ options.startupTimeoutMs ?? 3e4,
10032
+ cachedRuntime
10033
+ )
10034
+ );
10035
+ const cachedAssetFiles = measure(
10036
+ timings,
10037
+ "asset_index",
10038
+ () => collectCachedAssetFiles(clientRoot, options.appBasePath)
10001
10039
  );
10040
+ timings[timings.length - 1].fileCount = new Set(
10041
+ cachedAssetFiles.values()
10042
+ ).size;
10002
10043
  switcher = createPreviewArtifactSwitcher({
10003
10044
  listenHost: options.listenHost,
10004
10045
  listenPort: options.listenPort,
@@ -10006,13 +10047,14 @@ async function startPreviewArtifactRuntime(options) {
10006
10047
  cachedTarget: { host: "127.0.0.1", port: cachedServerPort },
10007
10048
  freshTarget: { host: "127.0.0.1", port: options.freshClientPort },
10008
10049
  freshBusinessPath: options.businessApiPath,
10009
- cachedAssetFiles: collectCachedAssetFiles(
10010
- clientRoot,
10011
- options.appBasePath
10012
- ),
10050
+ cachedAssetFiles,
10013
10051
  pollIntervalMs: options.pollIntervalMs
10014
10052
  });
10015
- const address = await switcher.start();
10053
+ const address = await measureAsync(
10054
+ timings,
10055
+ "switcher_listen",
10056
+ () => switcher.start()
10057
+ );
10016
10058
  const runtimeMarker = {
10017
10059
  schemaVersion: 1,
10018
10060
  status: "cached-serving",
@@ -10021,8 +10063,14 @@ async function startPreviewArtifactRuntime(options) {
10021
10063
  cachedServerPort,
10022
10064
  freshServerPort: options.freshServerPort,
10023
10065
  freshClientPort: options.freshClientPort,
10024
- startedAt: (/* @__PURE__ */ new Date()).toISOString()
10066
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
10067
+ timings
10025
10068
  };
10069
+ measure(
10070
+ timings,
10071
+ "marker_write",
10072
+ () => writeMarkerAtomic(markerFile, runtimeMarker)
10073
+ );
10026
10074
  writeMarkerAtomic(markerFile, runtimeMarker);
10027
10075
  const cutover = switcher.cutover.then(async (result) => {
10028
10076
  if (result.switched) {
@@ -10185,11 +10233,24 @@ var previewArtifactRuntimeCommand = {
10185
10233
  "JSON application environment passed only to cached application child"
10186
10234
  ).action(
10187
10235
  async (options) => {
10236
+ const environmentLoadStartedAt = Date.now();
10237
+ const environment = readPreviewArtifactEnvironmentFile(
10238
+ options.environmentFile
10239
+ );
10240
+ const environmentLoadDurationMs = Date.now() - environmentLoadStartedAt;
10188
10241
  const runtime = await startPreviewArtifactRuntime({
10189
10242
  ...options,
10190
- environment: readPreviewArtifactEnvironmentFile(
10191
- options.environmentFile
10192
- )
10243
+ environment,
10244
+ initialTimings: [
10245
+ {
10246
+ phase: "cli_bootstrap",
10247
+ durationMs: Math.max(0, Math.round(process.uptime() * 1e3))
10248
+ },
10249
+ {
10250
+ phase: "environment_load",
10251
+ durationMs: environmentLoadDurationMs
10252
+ }
10253
+ ]
10193
10254
  });
10194
10255
  if (!runtime.started) {
10195
10256
  console.log(JSON.stringify(runtime));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-cli",
3
- "version": "1.1.59-alpha.20260722041318",
3
+ "version": "1.1.59-alpha.20260722071909",
4
4
  "description": "CLI tool for fullstack template management",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,9 +8,7 @@ const readline = require('readline');
8
8
  const {
9
9
  applyPreviewArtifactHostOverrides,
10
10
  buildListeningPortLookupArgs,
11
- closePreviewPhaseReporterWithRetry,
12
11
  createDeferredTypecheckGate,
13
- createPreviewPhaseFrameDecoder,
14
12
  createPreviewPhaseReporter,
15
13
  normalizeTcpPort,
16
14
  parseTscWatchSummary,
@@ -201,7 +199,6 @@ function startProcess({
201
199
  args,
202
200
  cleanupPort,
203
201
  phaseDetail = {},
204
- phaseChannel = false,
205
202
  onReady,
206
203
  onOutputLine,
207
204
  }) {
@@ -239,23 +236,12 @@ function startProcess({
239
236
  }
240
237
 
241
238
  while (!stopping) {
242
- const childEnv = { ...process.env };
243
- // The parent is the only outbox writer. Child processes receive a narrow
244
- // producer channel, never the filesystem destination.
245
- delete childEnv.MIAODA_PREVIEW_PHASE_OUTBOX_ROOT;
246
- if (phaseChannel) {
247
- childEnv.MIAODA_PREVIEW_PHASE_FD = '3';
248
- } else {
249
- delete childEnv.MIAODA_PREVIEW_PHASE_FD;
250
- }
251
239
  const child = spawn(command, args, {
252
240
  detached: true,
253
- stdio: phaseChannel
254
- ? ['ignore', 'pipe', 'pipe', 'pipe']
255
- : ['ignore', 'pipe', 'pipe'],
241
+ stdio: ['ignore', 'pipe', 'pipe'],
256
242
  shell: true,
257
243
  cwd: PROJECT_ROOT,
258
- env: childEnv,
244
+ env: { ...process.env },
259
245
  });
260
246
 
261
247
  entry.pid = child.pid;
@@ -321,24 +307,13 @@ function startProcess({
321
307
 
322
308
  // Pipe stdout and stderr through readline for timestamped logging
323
309
  let typecheckSummaryReported = false;
324
- let phaseReported = false;
325
- const pipeLines = (stream, allowPhaseFallback = false) => {
310
+ const pipeLines = stream => {
326
311
  const rl = readline.createInterface({
327
312
  input: stream,
328
313
  crlfDelay: Infinity,
329
314
  });
330
315
  rl.on('line', line => {
331
316
  if (onOutputLine) onOutputLine(line);
332
- const legacyPhaseCandidate =
333
- allowPhaseFallback && line.startsWith('[MiaodaPreviewPhase] ');
334
- if (legacyPhaseCandidate && !phaseReported) {
335
- phaseReported = previewPhaseReporter.ingest(line, {
336
- producer: 'vite_plugin',
337
- allowed_phases: ['vite_http_listening'],
338
- attempt,
339
- allow_legacy_stdout: true,
340
- });
341
- }
342
317
  if (name === 'server-typecheck' && !typecheckSummaryReported) {
343
318
  const summary = parseTscWatchSummary(line);
344
319
  if (summary) {
@@ -359,38 +334,11 @@ function startProcess({
359
334
  try {
360
335
  fs.writeSync(logFd, msg);
361
336
  } catch {}
362
- // Phase fallbacks are normalized by the parent reporter before they
363
- // enter the shared log. Keep the raw child claim quarantined in the
364
- // component log so collectors never observe two representations.
365
- if (!legacyPhaseCandidate) writeOutput(msg);
337
+ writeOutput(msg);
366
338
  });
367
339
  };
368
- if (child.stdout) pipeLines(child.stdout, phaseChannel);
340
+ if (child.stdout) pipeLines(child.stdout);
369
341
  if (child.stderr) pipeLines(child.stderr);
370
- if (phaseChannel && child.stdio[3]) {
371
- let oversizedPhaseFrameReported = false;
372
- const phaseDecoder = createPreviewPhaseFrameDecoder({
373
- max_bytes: 16 * 1024,
374
- on_oversized_frame: () => {
375
- if (oversizedPhaseFrameReported) return;
376
- oversizedPhaseFrameReported = true;
377
- logEvent(
378
- 'WARN',
379
- name,
380
- 'Dropped an oversized preview phase producer frame'
381
- );
382
- },
383
- on_frame: line => {
384
- if (phaseReported) return;
385
- phaseReported = previewPhaseReporter.ingest(line, {
386
- producer: 'vite_plugin',
387
- allowed_phases: ['vite_http_listening'],
388
- attempt,
389
- });
390
- },
391
- });
392
- child.stdio[3].on('data', chunk => phaseDecoder.push(chunk));
393
- }
394
342
 
395
343
  // Wait for the direct child to exit.
396
344
  // NOTE: must use 'exit', not 'close'. With shell:true, grandchild processes
@@ -520,16 +468,6 @@ async function cleanup() {
520
468
 
521
469
  logEvent('INFO', 'main', 'All processes stopped');
522
470
 
523
- const previewPhaseSealed =
524
- await closePreviewPhaseReporterWithRetry(previewPhaseReporter);
525
- if (!previewPhaseSealed) {
526
- logEvent(
527
- 'ERROR',
528
- 'main',
529
- 'Preview phase outbox did not seal after bounded shutdown retries'
530
- );
531
- }
532
-
533
471
  try {
534
472
  fs.closeSync(devStdLogFd);
535
473
  } catch {}
@@ -537,7 +475,7 @@ async function cleanup() {
537
475
  fs.closeSync(devLogFd);
538
476
  } catch {}
539
477
 
540
- process.exit(previewPhaseSealed ? 0 : 1);
478
+ process.exit(0);
541
479
  }
542
480
 
543
481
  process.on('SIGTERM', cleanup);
@@ -706,7 +644,6 @@ async function main() {
706
644
  command: 'npm',
707
645
  args: ['run', 'dev:client'],
708
646
  cleanupPort: CLIENT_DEV_PORT,
709
- phaseChannel: true,
710
647
  });
711
648
 
712
649
  writeOutput(`📋 Dev processes running. Press Ctrl+C to stop.\n`);
@@ -720,14 +657,7 @@ async function main() {
720
657
  }
721
658
  }
722
659
 
723
- main().catch(async err => {
660
+ main().catch(err => {
724
661
  console.error('Fatal error:', err);
725
- const previewPhaseSealed =
726
- await closePreviewPhaseReporterWithRetry(previewPhaseReporter);
727
- if (!previewPhaseSealed) {
728
- console.error(
729
- 'Preview phase outbox did not seal after bounded fatal-exit retries'
730
- );
731
- }
732
662
  process.exit(1);
733
663
  });