@vmz/core 0.1.26 → 0.1.27

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.
@@ -3,6 +3,12 @@
3
3
  * Href authority is RouteId × LocaleId realization rows — not path parsing on existing href.
4
4
  */
5
5
  export declare const LOCALE_LINK_PLAN_SCHEMA = "vmz.static.locale_link_plan.v0";
6
+ export type LinkRouteAlias = {
7
+ /** Author Link `to` / `data-vmz-route` (class RouteId, e.g. IndexPage). */
8
+ linkRouteId: string;
9
+ /** Locale realization `routeId` (often chunk path, e.g. pages/index). */
10
+ realizationRouteId: string;
11
+ };
6
12
  export type LocaleHrefArtifact = {
7
13
  locales?: Array<{
8
14
  id: string;
@@ -18,6 +24,11 @@ export type LocaleHrefArtifact = {
18
24
  localeId: string;
19
25
  path: string;
20
26
  }>;
27
+ /**
28
+ * Bridge author Link RouteId ↔ realization routeId.
29
+ * Realization artifacts historically key by chunk path; Links emit class names.
30
+ */
31
+ linkRouteAliases?: LinkRouteAlias[];
21
32
  };
22
33
  export type LocaleLinkPlanRow = {
23
34
  routeId: string;
@@ -28,6 +39,12 @@ export type LocaleLinkPlan = {
28
39
  schema: typeof LOCALE_LINK_PLAN_SCHEMA;
29
40
  rows: LocaleLinkPlanRow[];
30
41
  };
42
+ /** Build Link RouteId aliases from deployment page units (`routeId` + `chunkId`). */
43
+ export declare function linkRouteAliasesFromUnits(units: Array<{
44
+ kind?: string;
45
+ routeId?: string;
46
+ chunkId?: string;
47
+ }> | null | undefined): LinkRouteAlias[];
31
48
  /** Build RouteId × LocaleId → href rows from locale route realization artifact. */
32
49
  export declare function buildLocaleLinkPlan(artifact: LocaleHrefArtifact | null | undefined): LocaleLinkPlan;
33
50
  /** Apply plan rows to `<a data-vmz-route="RouteId">` markers for one LocaleId. */
@@ -3,13 +3,41 @@
3
3
  * Href authority is RouteId × LocaleId realization rows — not path parsing on existing href.
4
4
  */
5
5
  export const LOCALE_LINK_PLAN_SCHEMA = 'vmz.static.locale_link_plan.v0';
6
+ /** Build Link RouteId aliases from deployment page units (`routeId` + `chunkId`). */
7
+ export function linkRouteAliasesFromUnits(units) {
8
+ const out = [];
9
+ const seen = new Set();
10
+ for (const unit of units || []) {
11
+ if (unit?.kind && unit.kind !== 'page')
12
+ continue;
13
+ const linkRouteId = typeof unit?.routeId === 'string' ? unit.routeId.trim() : '';
14
+ const realizationRouteId = typeof unit?.chunkId === 'string' ? unit.chunkId.replace(/\\/g, '/').trim() : '';
15
+ if (!linkRouteId || !realizationRouteId || linkRouteId === realizationRouteId)
16
+ continue;
17
+ const key = `${linkRouteId}\0${realizationRouteId}`;
18
+ if (seen.has(key))
19
+ continue;
20
+ seen.add(key);
21
+ out.push({ linkRouteId, realizationRouteId });
22
+ }
23
+ return out;
24
+ }
6
25
  /** Build RouteId × LocaleId → href rows from locale route realization artifact. */
7
26
  export function buildLocaleLinkPlan(artifact) {
8
27
  const rows = [];
28
+ const aliases = artifact?.linkRouteAliases || [];
9
29
  for (const r of artifact?.realizations || []) {
10
30
  if (!r?.routeId || !r?.localeId || !r?.path)
11
31
  continue;
12
- rows.push({ routeId: String(r.routeId), localeId: String(r.localeId), href: String(r.path) });
32
+ const realizationRouteId = String(r.routeId);
33
+ const localeId = String(r.localeId);
34
+ const href = String(r.path);
35
+ rows.push({ routeId: realizationRouteId, localeId, href });
36
+ for (const alias of aliases) {
37
+ if (alias.realizationRouteId === realizationRouteId && alias.linkRouteId) {
38
+ rows.push({ routeId: String(alias.linkRouteId), localeId, href });
39
+ }
40
+ }
13
41
  }
14
42
  rows.sort((a, b) => (a.routeId === b.routeId ? a.localeId.localeCompare(b.localeId) : a.routeId.localeCompare(b.routeId)));
15
43
  return { schema: LOCALE_LINK_PLAN_SCHEMA, rows };
@@ -32,6 +60,10 @@ export function applyLocaleLinkPlan(html, localeId, plan, escapeAttr = (s) => St
32
60
  const href = byRoute.get(rm[1]);
33
61
  if (!href)
34
62
  return full;
63
+ // Realization rows for dynamic routes keep unresolved patterns (`[id]` / `:id`).
64
+ // Do not clobber compile-time realized hrefs like `/products/sku-1`.
65
+ if (/\[[^\]]+\]/.test(href) || /\/:[^/]+/.test(href))
66
+ return full;
35
67
  const hm = attrs.match(/\bhref\s*=\s*"([^"]*)"/i);
36
68
  if (hm && hm[1] === href)
37
69
  return full;
@@ -22,10 +22,10 @@ import http from 'node:http';
22
22
  import { createRequire, registerHooks } from 'node:module';
23
23
  import path from 'node:path';
24
24
  import { fileURLToPath, pathToFileURL } from 'node:url';
25
- import { localizeBodyLinks } from './localize-body-links.js';
26
- import { createRenderHost } from './render-host.js';
27
25
  import { listClientComponents } from './list-client-components.js';
26
+ import { linkRouteAliasesFromUnits, localizeBodyLinks } from './localize-body-links.js';
28
27
  import { loadNativeAddon } from './native-addon.js';
28
+ import { createRenderHost } from './render-host.js';
29
29
  import { resolveRouteLayoutChain } from './route-layout-chain.js';
30
30
  import { handleNodeRequest, setRoutes, setServerModuleResolver } from './vmz-runtime.js';
31
31
  const require = createRequire(import.meta.url);
@@ -756,6 +756,26 @@ process.on('SIGTERM', () => {
756
756
  process.on('SIGINT', () => {
757
757
  void gracefulShutdown('SIGINT');
758
758
  });
759
+ /**
760
+ * Attach author Link RouteId aliases so localizeBodyLinks can match `data-vmz-route="IndexPage"`
761
+ * against realization rows keyed by chunk path (`pages/index`).
762
+ * @param {any} artifact
763
+ * @param {string} dir
764
+ */
765
+ function attachLinkRouteAliases(artifact, dir) {
766
+ if (!artifact || typeof artifact !== 'object')
767
+ return artifact;
768
+ try {
769
+ const dep = JSON.parse(readFileSync(path.join(dir, 'vmz-deployment.json'), 'utf8'));
770
+ const aliases = linkRouteAliasesFromUnits(Array.isArray(dep.units) ? dep.units : []);
771
+ if (!aliases.length)
772
+ return artifact;
773
+ return { ...artifact, linkRouteAliases: aliases };
774
+ }
775
+ catch {
776
+ return artifact;
777
+ }
778
+ }
759
779
  /**
760
780
  * Re-import routes / pages / components with a new cache-bust token.
761
781
  * Keeps the HTTP server process alive (no Node restart).
@@ -791,6 +811,7 @@ async function softReload(opts = {}) {
791
811
  }
792
812
  try {
793
813
  localeArtifact = JSON.parse(await readFile(path.join(distDir, '_vmz', 'locale-route-realization.json'), 'utf8'));
814
+ localeArtifact = attachLinkRouteAliases(localeArtifact, distDir);
794
815
  }
795
816
  catch {
796
817
  localeArtifact = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vmz/core",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "type": "module",
5
5
  "description": "VMZ production runtime core — DOM / SSR / HTTP / WriteBarrier (no compiler)",
6
6
  "exports": {
@@ -66,12 +66,12 @@
66
66
  "linkedom": "^0.18.13"
67
67
  },
68
68
  "optionalDependencies": {
69
- "@vmz/vmz-win32-x64": "0.1.26",
70
- "@vmz/vmz-win32-arm64": "0.1.26",
71
- "@vmz/vmz-darwin-x64": "0.1.26",
72
- "@vmz/vmz-darwin-arm64": "0.1.26",
73
- "@vmz/vmz-linux-x64": "0.1.26",
74
- "@vmz/vmz-linux-arm64": "0.1.26"
69
+ "@vmz/vmz-win32-x64": "0.1.27",
70
+ "@vmz/vmz-win32-arm64": "0.1.27",
71
+ "@vmz/vmz-darwin-x64": "0.1.27",
72
+ "@vmz/vmz-darwin-arm64": "0.1.27",
73
+ "@vmz/vmz-linux-x64": "0.1.27",
74
+ "@vmz/vmz-linux-arm64": "0.1.27"
75
75
  },
76
76
  "publishConfig": {
77
77
  "access": "public"