@vmz/vmz 0.1.29 → 0.1.31

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/cli.js CHANGED
@@ -4,30 +4,31 @@
4
4
  import { spawn } from 'node:child_process';
5
5
  import { existsSync } from 'node:fs';
6
6
  import path from 'node:path';
7
- import { HOST_PROTOCOL, createWorkspace, getProtocolVersions, materializeServeHostRuntime, resolveCoreRuntimeDist, resolveNativePath, } from './index.js';
7
+ import { createCli } from '@vmz/commander';
8
+ import { registerApplicationCommands } from './application-cmd.js';
9
+ import { assembleDelivery, emitBuildProof } from './build-assemble.js';
10
+ import { resolveCliLocalesRoot } from './cli-localize.js';
11
+ import { normalizeDeliveryAuthoring, resolveProfileArtifactDir, selectBuildProfile } from './delivery-profile.js';
8
12
  import { createDevSession } from './dev-session.js';
9
- import { gateGlobalProjectCommand, getInvocationContext, isGlobalAllowedCommand } from './invocation.js';
10
- import { log } from './log.js';
11
- import { findAvailablePort } from './port.js';
12
- import { readPackageMeta, resolveWorkspaceDirs } from './resolve.js';
13
- import { registerTestCommand } from './test-cmd.js';
14
13
  import { registerDocumentCommands } from './document-cmd.js';
15
14
  import { buildIntegratedDocuments, projectHasDocuments } from './document-integrate.js';
16
- import { registerLocaleCommands } from './locale-cmd.js';
15
+ import { registerExplainCommand } from './explain-cmd.js';
16
+ import { registerGithubActionsCommand } from './github-actions-cmd.js';
17
+ import { createWorkspace, getProtocolVersions, HOST_PROTOCOL, materializeServeHostRuntime, resolveCoreRuntimeDist, resolveNativePath, } from './index.js';
18
+ import { gateGlobalProjectCommand, getInvocationContext, isGlobalAllowedCommand } from './invocation.js';
17
19
  import { emitLocaleRuntimeModules, localeHasErrors } from './locale-check.js';
20
+ import { registerLocaleCommands } from './locale-cmd.js';
18
21
  import { emitLocaleRouteRealization } from './locale-route-emit.js';
19
- import { registerApplicationCommands } from './application-cmd.js';
20
- import { registerArtifactCommands } from './release-cmd.js';
21
- import { registerRefactorCommands } from './refactor-cmd.js';
22
- import { registerExplainCommand } from './explain-cmd.js';
22
+ import { log } from './log.js';
23
+ import { packFromDeploymentIr } from './pack.js';
23
24
  import { registerPlanCommands } from './plan-cmd.js';
24
- import { registerGithubActionsCommand } from './github-actions-cmd.js';
25
25
  import { loadVmzConfig } from './plugin-host.js';
26
- import { normalizeDeliveryAuthoring, resolveProfileArtifactDir, selectBuildProfile } from './delivery-profile.js';
27
- import { packFromDeploymentIr } from './pack.js';
28
- import { assembleDelivery, emitBuildProof } from './build-assemble.js';
29
- import { createCli } from '@vmz/commander';
30
- import { resolveCliLocalesRoot } from './cli-localize.js';
26
+ import { findAvailablePort } from './port.js';
27
+ import { registerRefactorCommands } from './refactor-cmd.js';
28
+ import { registerArtifactCommands } from './release-cmd.js';
29
+ import { readPackageMeta, resolveWorkspaceDirs } from './resolve.js';
30
+ import { emitRouteCatalog } from './route-catalog-emit.js';
31
+ import { registerTestCommand } from './test-cmd.js';
31
32
  export function printGlobalHelp() {
32
33
  return buildProductCli({ mode: 'global' }).parse(['help']);
33
34
  }
@@ -224,6 +225,14 @@ async function cmdBuild(args) {
224
225
  if (localeRoutes.written.length) {
225
226
  log.info(`locale route realization (${localeRoutes.written.length} artifact(s))`);
226
227
  }
228
+ const routeCatalog = emitRouteCatalog(outDir);
229
+ if (!routeCatalog.ok) {
230
+ log.error(routeCatalog.error || 'route catalog emit failed');
231
+ return 1;
232
+ }
233
+ if (routeCatalog.written.length) {
234
+ log.info(`route catalog (${routeCatalog.written.length} artifact(s))`);
235
+ }
227
236
  if (projectHasDocuments(project)) {
228
237
  const docs = await buildIntegratedDocuments({ projectRoot: project, outDir });
229
238
  if (!docs.ok)
@@ -409,7 +418,7 @@ async function cmdDev(args) {
409
418
  }
410
419
  const outDir = resolveProfileArtifactDir(outDirRoot, selected.profile);
411
420
  const host = typeof args.host === 'string' ? args.host : '127.0.0.1';
412
- const portLocked = Object.prototype.hasOwnProperty.call(args, 'port');
421
+ const portLocked = Object.hasOwn(args, 'port');
413
422
  let port;
414
423
  if (portLocked) {
415
424
  port = Number(args.port);
package/dist/index.d.ts CHANGED
@@ -30,9 +30,9 @@ export declare function getProtocolVersions(): ProtocolVersions;
30
30
  export declare function handshake(host?: ProtocolVersions): void;
31
31
  /** Resolve `@vmz/core` package `dist/` for runtime JS copies into app outDir. */
32
32
  export declare function resolveCoreRuntimeDist(): string | null;
33
- /** Runtime companions required by dist/vmz-serve-host.mjs relative imports. */
33
+ /** Runtime companions required by dist/_vmz/host/vmz-serve-host.mjs relative imports. */
34
34
  export declare const SERVE_HOST_RUNTIME_FILES: ReadonlyArray<readonly [string, string]>;
35
- /** Copy serve-host + registry bootstrap modules from `@vmz/core` into app outDir. */
35
+ /** Copy serve-host + registry bootstrap modules from `@vmz/core` into `_vmz/host/`. */
36
36
  export declare function materializeServeHostRuntime(outDir: string, coreDist?: string | null): void;
37
37
  /** Create a long-lived compile workspace. */
38
38
  export declare function createWorkspace(options: WorkspaceOptions): VmzNativeAddon;
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Coarse-grained only — no transform hooks / per-AST callbacks.
4
4
  */
5
5
  import { createRequire } from 'node:module';
6
- import { copyFileSync, existsSync } from 'node:fs';
6
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
7
7
  import path from 'node:path';
8
8
  import { fileURLToPath } from 'node:url';
9
9
  import { materializeWechatPackaging } from './wechat-packaging.js';
@@ -119,17 +119,17 @@ export function resolveCoreRuntimeDist() {
119
119
  return nested;
120
120
  return null;
121
121
  }
122
- /** Runtime companions required by dist/vmz-serve-host.mjs relative imports. */
122
+ /** Runtime companions required by dist/_vmz/host/vmz-serve-host.mjs relative imports. */
123
123
  export const SERVE_HOST_RUNTIME_FILES = [
124
- ['serve-host.mjs', 'vmz-serve-host.mjs'],
125
- ['native-addon.js', 'native-addon.js'],
126
- ['list-client-components.js', 'list-client-components.js'],
127
- ['deployment-registry.js', 'deployment-registry.js'],
128
- ['render-host.js', 'render-host.js'],
129
- ['route-layout-chain.js', 'route-layout-chain.js'],
130
- ['localize-body-links.js', 'localize-body-links.js'],
124
+ ['serve-host.mjs', '_vmz/host/vmz-serve-host.mjs'],
125
+ ['native-addon.js', '_vmz/host/native-addon.js'],
126
+ ['list-client-components.js', '_vmz/host/list-client-components.js'],
127
+ ['deployment-registry.js', '_vmz/host/deployment-registry.js'],
128
+ ['render-host.js', '_vmz/host/render-host.js'],
129
+ ['route-layout-chain.js', '_vmz/host/route-layout-chain.js'],
130
+ ['localize-body-links.js', '_vmz/host/localize-body-links.js'],
131
131
  ];
132
- /** Copy serve-host + registry bootstrap modules from `@vmz/core` into app outDir. */
132
+ /** Copy serve-host + registry bootstrap modules from `@vmz/core` into `_vmz/host/`. */
133
133
  export function materializeServeHostRuntime(outDir, coreDist = resolveCoreRuntimeDist()) {
134
134
  if (!coreDist) {
135
135
  throw new Error('materializeServeHostRuntime: @vmz/core dist not found');
@@ -140,8 +140,18 @@ export function materializeServeHostRuntime(outDir, coreDist = resolveCoreRuntim
140
140
  if (!existsSync(src)) {
141
141
  throw new Error(`materializeServeHostRuntime: missing ${src}`);
142
142
  }
143
- copyFileSync(src, dst);
143
+ mkdirSync(path.dirname(dst), { recursive: true });
144
+ if (srcName === 'serve-host.mjs') {
145
+ // Nested under `_vmz/host/`: delivery-root `vmz-runtime.js` is two levels up.
146
+ const text = readFileSync(src, 'utf8').replace(/from\s+(['"])\.\/vmz-runtime\.js\1/g, 'from $1../../vmz-runtime.js$1');
147
+ writeFileSync(dst, text, 'utf8');
148
+ }
149
+ else {
150
+ copyFileSync(src, dst);
151
+ }
144
152
  }
153
+ const stub = path.join(outDir, 'vmz-serve-host.mjs');
154
+ writeFileSync(stub, "// Generated launcher — host companions live under `_vmz/host/` (0.1.31).\nimport './_vmz/host/vmz-serve-host.mjs';\n", 'utf8');
145
155
  }
146
156
  /** Create a long-lived compile workspace. */
147
157
  export function createWorkspace(options) {
@@ -2,7 +2,10 @@
2
2
  * Emit RouteId × LocaleId realization (+ PageMeta / hreflang seed) into dist/_vmz.
3
3
  * Consumed by serve-host + static-emit; LocaleId stays out of stable RouteId.
4
4
  */
5
+ import { LOCALE_LINK_PLAN_SCHEMA } from '@vmz/core/localize-body-links';
5
6
  export declare const LOCALE_ROUTE_REALIZATION_ARTIFACT_SCHEMA = "vmz.locale.route_realization.v0";
7
+ export declare const LOCALE_LINK_PLAN_REL = "_vmz/locale-link-plan.json";
8
+ export { LOCALE_LINK_PLAN_SCHEMA };
6
9
  export interface EmitLocaleRouteRealizationOpts {
7
10
  origin?: string;
8
11
  }
@@ -46,6 +49,7 @@ export declare function emitLocaleRouteRealization(projectRoot: string, distDir:
46
49
  diagnostics: import("./locale-router.js").LocaleDiagnostic[];
47
50
  status: string;
48
51
  }[];
52
+ linkRouteAliases: import("@vmz/core/localize-body-links").LinkRouteAlias[];
49
53
  };
50
54
  diagnostics: any[];
51
55
  };
@@ -4,11 +4,14 @@
4
4
  */
5
5
  import fs from 'node:fs';
6
6
  import path from 'node:path';
7
+ import { buildLocaleLinkPlan, LOCALE_LINK_PLAN_SCHEMA, linkRouteAliasesFromUnits } from '@vmz/core/localize-body-links';
7
8
  import { checkLocales, localeHasErrors } from './locale-check.js';
8
9
  import { buildLocalePageMeta, buildLocaleRouteRealizationTable } from './locale-router.js';
9
10
  import { writePrettyJsonFile } from './pretty-json.js';
10
11
  import { listPublicPageUnits, unitBrowserPathPattern } from './route-path.js';
11
12
  export const LOCALE_ROUTE_REALIZATION_ARTIFACT_SCHEMA = 'vmz.locale.route_realization.v0';
13
+ export const LOCALE_LINK_PLAN_REL = '_vmz/locale-link-plan.json';
14
+ export { LOCALE_LINK_PLAN_SCHEMA };
12
15
  export function emitLocaleRouteRealization(projectRoot, distDir, opts = {}) {
13
16
  const report = checkLocales({ projectRoot, checkUnused: false });
14
17
  if (localeHasErrors(report)) {
@@ -81,6 +84,7 @@ export function emitLocaleRouteRealization(projectRoot, distDir, opts = {}) {
81
84
  routes,
82
85
  realizations: table.realizations,
83
86
  pageMetas,
87
+ linkRouteAliases: linkRouteAliasesFromUnits(pages),
84
88
  };
85
89
  const vmzDir = path.join(distDir, '_vmz');
86
90
  fs.mkdirSync(vmzDir, { recursive: true });
@@ -93,9 +97,14 @@ export function emitLocaleRouteRealization(projectRoot, distDir, opts = {}) {
93
97
  locales: artifact.locales,
94
98
  routing: artifact.routing,
95
99
  });
100
+ const linkPlan = buildLocaleLinkPlan(artifact);
101
+ writePrettyJsonFile(path.join(distDir, ...LOCALE_LINK_PLAN_REL.split('/')), {
102
+ schema: LOCALE_LINK_PLAN_SCHEMA,
103
+ rows: linkPlan.rows,
104
+ });
96
105
  return {
97
106
  ok: true,
98
- written: ['_vmz/locale-route-realization.json', '_vmz/locale-manifest.json'],
107
+ written: ['_vmz/locale-route-realization.json', '_vmz/locale-manifest.json', LOCALE_LINK_PLAN_REL],
99
108
  artifact,
100
109
  diagnostics: [],
101
110
  };
package/dist/pack.js CHANGED
@@ -20,7 +20,7 @@ export const PACK_MANIFEST_SCHEMA = 'vmz.pack.manifest.v0';
20
20
  export function ensureRuntimeCompanions(outDir, coreDist) {
21
21
  if (!coreDist)
22
22
  return [];
23
- const names = ['dom-core.js', 'dom-ssr.js', 'dom.client.js', 'direct-host-box.js', 'unknown-component.js'];
23
+ const names = ['dom-core.js', 'dom-ssr.js', 'dom.client.js', 'dom.browser.js', 'direct-host-box.js', 'unknown-component.js'];
24
24
  const copied = [];
25
25
  for (const name of names) {
26
26
  const src = path.join(coreDist, name);
@@ -11,6 +11,7 @@ import { emitLocaleRuntimeModules, localeHasErrors } from './locale-check.js';
11
11
  import { emitLocaleRouteRealization } from './locale-route-emit.js';
12
12
  import { packFromDeploymentIr } from './pack.js';
13
13
  import { loadVmzConfig } from './plugin-host.js';
14
+ import { emitRouteCatalog } from './route-catalog-emit.js';
14
15
  function dedupeDiagnostics(list) {
15
16
  const seen = new Set();
16
17
  const out = [];
@@ -129,6 +130,17 @@ export async function buildProjectToOutDirRoot(project, outDirRoot, opts = {}) {
129
130
  error: 'locale route realization emit failed',
130
131
  };
131
132
  }
133
+ const routeCatalog = emitRouteCatalog(artifactDir);
134
+ if (!routeCatalog.ok) {
135
+ return {
136
+ ok: false,
137
+ outDirRoot: root,
138
+ artifactDir,
139
+ deliveryName,
140
+ diagnostics,
141
+ error: routeCatalog.error || 'route catalog emit failed',
142
+ };
143
+ }
132
144
  if (projectHasDocuments(project)) {
133
145
  const docs = await buildIntegratedDocuments({ projectRoot: project, outDir: artifactDir });
134
146
  if (!docs.ok) {
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Compiled route catalog (`_vmz/route-catalog.json`) — 0.1.30 authority for page matching.
3
+ * Hosts load this artifact; they must not re-parse deployment pathPattern into a live catalog.
4
+ */
5
+ import { type DeploymentPageUnit, type PathSeg } from './route-path.js';
6
+ export declare const ROUTE_CATALOG_SCHEMA = "vmz.route.catalog.v0";
7
+ export declare const ROUTE_CATALOG_REL = "_vmz/route-catalog.json";
8
+ export type RouteCatalogPage = {
9
+ chunkId: string;
10
+ routeId: string;
11
+ pathPattern: string;
12
+ pageRel: string;
13
+ segs: PathSeg[];
14
+ };
15
+ export type RouteCatalog = {
16
+ schema: typeof ROUTE_CATALOG_SCHEMA;
17
+ pages: RouteCatalogPage[];
18
+ };
19
+ export declare function buildRouteCatalogFromDeployment(deployment: {
20
+ units?: DeploymentPageUnit[];
21
+ } | null | undefined): RouteCatalog;
22
+ export declare function emitRouteCatalog(distDir: string): {
23
+ ok: boolean;
24
+ written: string[];
25
+ catalog: RouteCatalog | null;
26
+ error?: string;
27
+ };
28
+ export declare function loadRouteCatalog(distDir: string): RouteCatalog | null;
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Compiled route catalog (`_vmz/route-catalog.json`) — 0.1.30 authority for page matching.
3
+ * Hosts load this artifact; they must not re-parse deployment pathPattern into a live catalog.
4
+ */
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { writePrettyJsonFile } from './pretty-json.js';
8
+ import { listPublicPageUnits, parsePathPattern, unitBrowserPathPattern } from './route-path.js';
9
+ export const ROUTE_CATALOG_SCHEMA = 'vmz.route.catalog.v0';
10
+ export const ROUTE_CATALOG_REL = '_vmz/route-catalog.json';
11
+ export function buildRouteCatalogFromDeployment(deployment) {
12
+ const pages = [];
13
+ for (const unit of listPublicPageUnits(deployment)) {
14
+ const chunkId = String(unit.chunkId || '').replace(/\\/g, '/');
15
+ const pathPattern = unitBrowserPathPattern(unit);
16
+ const pageRel = String(unit.clientEntry || `${chunkId}.client.js`).replace(/\\/g, '/');
17
+ const routeId = typeof unit.routeId === 'string' && unit.routeId.trim() ? unit.routeId.trim() : chunkId;
18
+ pages.push({
19
+ chunkId,
20
+ routeId,
21
+ pathPattern,
22
+ pageRel,
23
+ segs: parsePathPattern(pathPattern),
24
+ });
25
+ }
26
+ pages.sort((a, b) => a.chunkId.localeCompare(b.chunkId));
27
+ return { schema: ROUTE_CATALOG_SCHEMA, pages };
28
+ }
29
+ export function emitRouteCatalog(distDir) {
30
+ const deploymentPath = path.join(distDir, 'vmz-deployment.json');
31
+ if (!fs.existsSync(deploymentPath)) {
32
+ return { ok: false, written: [], catalog: null, error: `missing ${deploymentPath}` };
33
+ }
34
+ let deployment;
35
+ try {
36
+ deployment = JSON.parse(fs.readFileSync(deploymentPath, 'utf8'));
37
+ }
38
+ catch (err) {
39
+ return { ok: false, written: [], catalog: null, error: err instanceof Error ? err.message : String(err) };
40
+ }
41
+ const catalog = buildRouteCatalogFromDeployment(deployment);
42
+ if (!catalog.pages.length) {
43
+ return { ok: false, written: [], catalog: null, error: 'no page units with pathPattern' };
44
+ }
45
+ const vmzDir = path.join(distDir, '_vmz');
46
+ fs.mkdirSync(vmzDir, { recursive: true });
47
+ writePrettyJsonFile(path.join(distDir, ...ROUTE_CATALOG_REL.split('/')), catalog);
48
+ return { ok: true, written: [ROUTE_CATALOG_REL], catalog };
49
+ }
50
+ export function loadRouteCatalog(distDir) {
51
+ const p = path.join(distDir, ...ROUTE_CATALOG_REL.split('/'));
52
+ if (!fs.existsSync(p))
53
+ return null;
54
+ try {
55
+ const raw = JSON.parse(fs.readFileSync(p, 'utf8'));
56
+ if (raw?.schema !== ROUTE_CATALOG_SCHEMA || !Array.isArray(raw.pages))
57
+ return null;
58
+ return raw;
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
@@ -11,11 +11,12 @@ import { createRenderHost } from '@vmz/core/render-host';
11
11
  import { resolveRouteLayoutChain } from '@vmz/core/route-layout-chain';
12
12
  import { emitCdnPolicy } from './cdn-policy.js';
13
13
  import { emitContentAddressedAssets, hashedAssetHref } from './content-addressed-assets.js';
14
+ import { LOCALE_LINK_PLAN_REL } from './locale-route-emit.js';
14
15
  import { absoluteUrl, applyLocaleLinkPlan, buildLocaleLinkPlan, buildLocalePageMeta, linkRouteAliasesFromUnits } from './locale-router.js';
15
16
  import { requireNativeAddon } from './native-addon.js';
16
17
  import { writePrettyJsonFile } from './pretty-json.js';
17
18
  import { emitPublicStaticAssets } from './public-static-assets.js';
18
- import { listPublicPageUnits, parsePathPattern, unitBrowserPathPattern } from './route-path.js';
19
+ import { emitRouteCatalog, loadRouteCatalog, ROUTE_CATALOG_SCHEMA } from './route-catalog-emit.js';
19
20
  import { emitSiteFavicon, readSiteFaviconHeadHtml } from './site-favicon.js';
20
21
  export const STATIC_DELIVERY_MANIFEST_SCHEMA = 'vmz.static.delivery_manifest.v0';
21
22
  export const STATIC_EMIT_PLAN_SCHEMA = 'vmz.static.emit_plan.v0';
@@ -42,7 +43,7 @@ export async function emitWebStatic(distDir, opts = {}) {
42
43
  const cssEntry = hashedAssetHref(assets.rewrites, cssLogical) || hashedAssetHref(assets.rewrites, 'vmz.css');
43
44
  const moduleScriptSrc = hashedAssetHref(assets.rewrites, 'entry-client.js') || '/entry-client.js';
44
45
  const localeArt = loadLocaleArtifact(distDir);
45
- const localeLinkPlan = buildLocaleLinkPlan(withLinkRouteAliases(localeArt, distDir, pageCatalog));
46
+ const localeLinkPlan = loadLocaleLinkPlan(distDir) || buildLocaleLinkPlan(withLinkRouteAliases(localeArt, distDir, pageCatalog));
46
47
  for (const page of pageCatalog) {
47
48
  const pattern = page.pathPattern || patternFromSegs(page.segs);
48
49
  const routeId = guessRouteId(distDir, page.chunkId);
@@ -284,26 +285,21 @@ function sortKeys(value) {
284
285
  * @param {string} distDir
285
286
  */
286
287
  function listPageClientFiles(distDir) {
287
- const fromDep = listPagesFromDeployment(distDir);
288
- if (!fromDep.length) {
289
- throw new Error(`emitWebStatic: no page units with pathPattern in ${path.join(distDir, 'vmz-deployment.json')} (plan-only host)`);
290
- }
291
- return fromDep;
292
- }
293
- /**
294
- * @param {string} distDir
295
- */
296
- function listPagesFromDeployment(distDir) {
297
- const deploymentPath = path.join(distDir, 'vmz-deployment.json');
298
- if (!fs.existsSync(deploymentPath)) {
299
- throw new Error(`emitWebStatic: missing ${deploymentPath} (plan-only host)`);
288
+ let catalog = loadRouteCatalog(distDir);
289
+ if (!catalog?.pages?.length) {
290
+ const emitted = emitRouteCatalog(distDir);
291
+ if (!emitted.ok || !emitted.catalog?.pages?.length) {
292
+ throw new Error(`emitWebStatic: missing compiled ${ROUTE_CATALOG_SCHEMA} at _vmz/route-catalog.json (${emitted.error || 'empty'})`);
293
+ }
294
+ catalog = emitted.catalog;
300
295
  }
301
- const deployment = JSON.parse(fs.readFileSync(deploymentPath, 'utf8'));
302
- return listPublicPageUnits(deployment).map((u) => {
303
- const chunkId = String(u.chunkId || '').replace(/\\/g, '/');
304
- const pathPattern = unitBrowserPathPattern(u);
305
- return { chunkId, pathPattern, segs: parsePathPattern(pathPattern) };
306
- });
296
+ return catalog.pages.map((p) => ({
297
+ chunkId: p.chunkId,
298
+ pathPattern: p.pathPattern,
299
+ pageRel: p.pageRel,
300
+ segs: p.segs,
301
+ routeId: p.routeId,
302
+ }));
307
303
  }
308
304
  /**
309
305
  * @param {ReturnType<typeof parsePathPattern>} segs
@@ -381,6 +377,20 @@ function loadLocaleArtifact(distDir) {
381
377
  return null;
382
378
  }
383
379
  }
380
+ function loadLocaleLinkPlan(distDir) {
381
+ const p = path.join(distDir, ...LOCALE_LINK_PLAN_REL.split('/'));
382
+ if (!fs.existsSync(p))
383
+ return null;
384
+ try {
385
+ const raw = JSON.parse(fs.readFileSync(p, 'utf8'));
386
+ if (raw?.schema !== 'vmz.static.locale_link_plan.v0' || !Array.isArray(raw.rows))
387
+ return null;
388
+ return raw;
389
+ }
390
+ catch {
391
+ return null;
392
+ }
393
+ }
384
394
  /** Bridge Link class RouteId ↔ realization chunk routeId for locale href rewrite. */
385
395
  function withLinkRouteAliases(localeArt, distDir, pageCatalog) {
386
396
  if (!localeArt)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vmz/vmz",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
4
4
  "type": "module",
5
5
  "description": "VMZ Node toolchain — N-API workspace session + CLI (publish name @vmz/vmz)",
6
6
  "license": "MIT",
@@ -48,16 +48,16 @@
48
48
  }
49
49
  },
50
50
  "dependencies": {
51
- "@vmz/commander": "0.1.29",
52
- "@vmz/core": "0.1.29",
53
- "@vmz/diagnostic": "0.1.29",
54
- "@vmz/plugin": "0.1.29",
55
- "@vmz/protocol": "0.1.29",
51
+ "@vmz/commander": "0.1.31",
52
+ "@vmz/core": "0.1.31",
53
+ "@vmz/diagnostic": "0.1.31",
54
+ "@vmz/plugin": "0.1.31",
55
+ "@vmz/protocol": "0.1.31",
56
56
  "jiti": "^2.6.1"
57
57
  },
58
58
  "peerDependencies": {
59
- "@vmz/plugin-markdown-it": "0.1.29",
60
- "@vmz/test": "0.1.29",
59
+ "@vmz/plugin-markdown-it": "0.1.31",
60
+ "@vmz/test": "0.1.31",
61
61
  "typescript": "^5.8.3"
62
62
  },
63
63
  "peerDependenciesMeta": {
@@ -92,12 +92,12 @@
92
92
  "cli"
93
93
  ],
94
94
  "optionalDependencies": {
95
- "@vmz/vmz-win32-x64": "0.1.29",
96
- "@vmz/vmz-win32-arm64": "0.1.29",
97
- "@vmz/vmz-darwin-x64": "0.1.29",
98
- "@vmz/vmz-darwin-arm64": "0.1.29",
99
- "@vmz/vmz-linux-x64": "0.1.29",
100
- "@vmz/vmz-linux-arm64": "0.1.29"
95
+ "@vmz/vmz-win32-x64": "0.1.31",
96
+ "@vmz/vmz-win32-arm64": "0.1.31",
97
+ "@vmz/vmz-darwin-x64": "0.1.31",
98
+ "@vmz/vmz-darwin-arm64": "0.1.31",
99
+ "@vmz/vmz-linux-x64": "0.1.31",
100
+ "@vmz/vmz-linux-arm64": "0.1.31"
101
101
  },
102
102
  "publishConfig": {
103
103
  "access": "public"