@vmz/vmz 0.3.13 → 0.3.15

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/bin/vmz.js CHANGED
@@ -9,4 +9,8 @@ if (major < 24 || (major === 24 && minor < 12)) {
9
9
  }
10
10
  const { runCli } = await import('../dist/cli/cli.js');
11
11
  const code = await runCli(process.argv.slice(2));
12
+ // POSIX pipes flush asynchronously, so `process.exit` can drop queued
13
+ // diagnostics before CI captures them. Drain both streams first.
14
+ await new Promise((resolve) => process.stderr.write('', resolve));
15
+ await new Promise((resolve) => process.stdout.write('', resolve));
12
16
  process.exit(code ?? 0);
@@ -11,6 +11,8 @@
11
11
  { "src": "browser/direct-host-box.js", "out": "direct-host-box.js" },
12
12
  { "src": "browser/unknown-component.js", "out": "unknown-component.js" },
13
13
  { "src": "shared/dom-attr-normalize.js", "out": "dom-attr-normalize.js" },
14
+ { "src": "shared/html-digest.js", "out": "html-digest.js" },
15
+ { "src": "shared/row-key.js", "out": "row-key.js" },
14
16
  { "src": "faces/http.js", "out": "vmz-http.js" },
15
17
  { "src": "browser/client-nav.js", "out": "vmz-client-nav.js" }
16
18
  ],
package/dist/cli/cli.js CHANGED
@@ -2,11 +2,12 @@
2
2
  * Node CLI command implementations .
3
3
  */
4
4
  import { spawn } from 'node:child_process';
5
- import { existsSync, statSync } from 'node:fs';
5
+ import { existsSync, readFileSync, statSync } from 'node:fs';
6
6
  import path from 'node:path';
7
7
  import { createCli } from '@vmz/commander';
8
8
  import { registerApplicationCommands } from './application-cmd.js';
9
9
  import { assembleDelivery, emitBuildProof } from '../workspace/build-assemble.js';
10
+ import { listenLocalStaticHost } from '../workspace/cdn-policy.js';
10
11
  import { resolveCliLocalesRoot } from './cli-localize.js';
11
12
  import { normalizeDeliveryAuthoring, resolveProfileArtifactDir, selectBuildProfile } from '../delivery/delivery-profile.js';
12
13
  import { createDevSession } from '../dev/dev-session.js';
@@ -401,6 +402,14 @@ async function cmdServe(args) {
401
402
  return 1;
402
403
  }
403
404
  const outDir = resolveProfileArtifactDir(outDirRoot, selected.profile);
405
+ const host = typeof args.host === 'string' ? args.host : '127.0.0.1';
406
+ const port = Number(args.port ?? 5173);
407
+ // `web-static` assemblies are pruned for delivery: the Node runtime face, page
408
+ // modules and `_vmz/pack-node/` are deliberately absent, so spawning the SSR
409
+ // host here fails with `ERR_MODULE_NOT_FOUND`. Serve the emitted HTML instead.
410
+ if (readAssembleAssembly(outDir) === 'web-static') {
411
+ return await serveWebStaticArtifact(outDir, host, port);
412
+ }
404
413
  const hostJs = path.join(outDir, 'vmz-serve-host.mjs');
405
414
  {
406
415
  try {
@@ -412,8 +421,6 @@ async function cmdServe(args) {
412
421
  return 1;
413
422
  }
414
423
  }
415
- const host = typeof args.host === 'string' ? args.host : '127.0.0.1';
416
- const port = Number(args.port ?? 5173);
417
424
  log.info(`serve http://${host}:${port}`);
418
425
  const node = process.env.VMZ_NODE || process.execPath;
419
426
  const child = spawn(node, [hostJs], {
@@ -444,6 +451,45 @@ async function cmdServe(args) {
444
451
  });
445
452
  });
446
453
  }
454
+ /** `assembly` recorded by the last build at this artifact dir, or `''` when absent. */
455
+ function readAssembleAssembly(outDir) {
456
+ try {
457
+ const raw = JSON.parse(readFileSync(path.join(outDir, '_vmz', 'assemble-manifest.json'), 'utf8'));
458
+ return typeof raw?.assembly === 'string' ? raw.assembly : '';
459
+ }
460
+ catch {
461
+ return '';
462
+ }
463
+ }
464
+ /**
465
+ * Preview a pruned `web-static` artifact through the CDN policy of the build:
466
+ * per-route HTML, real 404 document, cache headers. No SSR host is involved.
467
+ */
468
+ async function serveWebStaticArtifact(outDir, host, port) {
469
+ if (!existsSync(path.join(outDir, 'index.html'))) {
470
+ log.error(`missing ${path.join(outDir, 'index.html')} — run \`vmz build --profile static\` first`);
471
+ return 1;
472
+ }
473
+ let policy = {};
474
+ const policyPath = path.join(outDir, '_vmz', 'cdn-policy-manifest.json');
475
+ if (existsSync(policyPath)) {
476
+ try {
477
+ policy = JSON.parse(readFileSync(policyPath, 'utf8'));
478
+ }
479
+ catch {
480
+ policy = {};
481
+ }
482
+ }
483
+ const server = await listenLocalStaticHost(outDir, policy, { host, port });
484
+ log.info(`serve static ${server.baseUrl} (web-static artifact, no SSR host)`);
485
+ return await new Promise((resolve) => {
486
+ const shutdown = () => {
487
+ server.close().then(() => resolve(0), () => resolve(1));
488
+ };
489
+ process.once('SIGINT', shutdown);
490
+ process.once('SIGTERM', shutdown);
491
+ });
492
+ }
447
493
  async function cmdDev(args) {
448
494
  const pathArg = args._[0] ?? '.';
449
495
  const { project, outDir: outDirRoot } = resolveWorkspaceDirs({
@@ -36,14 +36,12 @@ export interface DevReloadPayload {
36
36
  islandHmr?: boolean;
37
37
  rerunLoaders?: string[];
38
38
  staticRevision?: string;
39
- skipEntryRewrite?: boolean;
40
39
  outputRevision?: string;
41
40
  }
42
41
  export declare function parseHmrPlan(raw: string | object | null | undefined): HmrPlanWire | null;
43
42
  export declare function hmrRerunLoaders(plan: HmrPlanWire | null | undefined): string[];
44
43
  export declare function buildReloadPayload(report: BuildReportWire, hmrPlan: HmrPlanWire | null, opts?: {
45
44
  staticRevision?: string;
46
- skipEntryRewrite?: boolean;
47
45
  }): DevReloadPayload;
48
46
  export declare function shouldSoftReload(report: BuildReportWire, lastOutputRevision: string | null, opts?: {
49
47
  force?: boolean;
@@ -38,7 +38,6 @@ export function buildReloadPayload(report, hmrPlan, opts = {}) {
38
38
  islandHmr: islandHmr && !full,
39
39
  rerunLoaders,
40
40
  staticRevision: opts.staticRevision,
41
- skipEntryRewrite: opts.skipEntryRewrite,
42
41
  outputRevision: report.outputRevision ?? report.output_revision,
43
42
  };
44
43
  }
@@ -11,6 +11,7 @@
11
11
  */
12
12
  import { createWorkspace } from '../workspace/public-api.js';
13
13
  import { type ConfigCycle } from './config-cycle.js';
14
+ import { packFromDeploymentIr } from '../workspace/pack.js';
14
15
  interface DevSessionOptions {
15
16
  project: string;
16
17
  outDir: string;
@@ -28,7 +29,9 @@ interface DevSessionOptions {
28
29
  host: string;
29
30
  port: number;
30
31
  }) => import('node:child_process').ChildProcess;
31
- softReloadFn?: (host: string, port: number, payload?: object) => Promise<void>;
32
+ softReloadFn?: (body: Record<string, unknown>) => Promise<Record<string, unknown>>;
33
+ /** Test seam for the browser pack stage (defaults to `packFromDeploymentIr`). */
34
+ packFn?: typeof packFromDeploymentIr;
32
35
  /** Override the detached config build process (tests). */
33
36
  configCycleFn?: (opts: {
34
37
  project: string;
@@ -38,6 +41,55 @@ interface DevSessionOptions {
38
41
  /** Built config cycle worker path (defaults to `dist/dev/config-cycle-worker.js`). */
39
42
  configCycleWorkerPath?: string;
40
43
  }
44
+ export interface PackManifestView {
45
+ chunks?: Array<{
46
+ fileName?: string;
47
+ sourceMap?: string;
48
+ modules?: unknown[];
49
+ }>;
50
+ styles?: Array<{
51
+ fileName?: string;
52
+ sourcePaths?: unknown[];
53
+ }>;
54
+ assets?: Array<{
55
+ fileName?: string;
56
+ }>;
57
+ entryFiles?: Array<{
58
+ file?: string;
59
+ }>;
60
+ dynamicFiles?: Array<{
61
+ from?: string;
62
+ to?: string;
63
+ }>;
64
+ unitChunks?: Array<{
65
+ fileName?: string | null;
66
+ }>;
67
+ }
68
+ export interface PackInputSnapshot {
69
+ files: Array<{
70
+ path: string;
71
+ digest: string;
72
+ }>;
73
+ listings: Array<{
74
+ dir: string;
75
+ names: string[];
76
+ }>;
77
+ deploymentOrigins: string;
78
+ lockfile: {
79
+ path: string;
80
+ digest: string;
81
+ };
82
+ manifest: {
83
+ path: string;
84
+ digest: string;
85
+ };
86
+ }
87
+ /** 记下决定 pack 产物的全部输入;任何一项取不到就放弃快照(等同于永远重打包)。 */
88
+ export declare function capturePackInputSnapshot(manifest: PackManifestView, outDir: string, project: string): PackInputSnapshot | null;
89
+ /** 返回 null 表示全部输入字节全等;否则返回第一个变化原因。 */
90
+ export declare function packInputsChangedReason(snapshot: PackInputSnapshot, outDir: string): string | null;
91
+ /** 复用上次 manifest 前确认 entry/chunk/island 查表指向的文件仍在盘上;缺任何一个就退回真实 pack。 */
92
+ export declare function missingPackOutput(manifest: PackManifestView, outDir: string): string | null;
41
93
  export declare function createDevSession(options: DevSessionOptions): {
42
94
  ws: any;
43
95
  rebuild: (changes?: Array<{