@vmz/vmz 0.0.3 → 0.1.0

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 (52) hide show
  1. package/README.md +6 -4
  2. package/dist/build-assemble.d.ts +52 -0
  3. package/dist/build-assemble.js +191 -0
  4. package/dist/cdn-policy.d.ts +196 -0
  5. package/dist/cdn-policy.js +443 -0
  6. package/dist/cli.js +152 -11
  7. package/dist/content-addressed-assets.d.ts +69 -0
  8. package/dist/content-addressed-assets.js +206 -0
  9. package/dist/delivery-profile.d.ts +74 -0
  10. package/dist/delivery-profile.js +279 -0
  11. package/dist/dev-session.js +49 -13
  12. package/dist/document-build.js +9 -4
  13. package/dist/document-designs.js +30 -2
  14. package/dist/document-enrich.js +8 -0
  15. package/dist/embedded-packaging.d.ts +22 -0
  16. package/dist/embedded-packaging.js +113 -0
  17. package/dist/index.d.ts +19 -3
  18. package/dist/index.js +35 -15
  19. package/dist/invocation.d.ts +8 -31
  20. package/dist/invocation.js +12 -33
  21. package/dist/locale-check.d.ts +16 -0
  22. package/dist/locale-check.js +131 -3
  23. package/dist/locale-cmd.js +2 -2
  24. package/dist/locale-route-emit.d.ts +34 -0
  25. package/dist/locale-route-emit.js +134 -0
  26. package/dist/locale-router.d.ts +20 -0
  27. package/dist/locale-router.js +68 -0
  28. package/dist/log.d.ts +2 -2
  29. package/dist/log.js +11 -3
  30. package/dist/pack.d.ts +40 -0
  31. package/dist/pack.js +108 -0
  32. package/dist/plugin-host.d.ts +10 -1
  33. package/dist/plugin-host.js +19 -2
  34. package/dist/port.d.ts +10 -0
  35. package/dist/port.js +46 -0
  36. package/dist/production-observability.d.ts +286 -0
  37. package/dist/production-observability.js +469 -0
  38. package/dist/production-test-pack.d.ts +144 -0
  39. package/dist/production-test-pack.js +447 -0
  40. package/dist/release-cmd.d.ts +8 -0
  41. package/dist/release-cmd.js +126 -0
  42. package/dist/release-pack.d.ts +96 -0
  43. package/dist/release-pack.js +346 -0
  44. package/dist/server-artifact.d.ts +140 -0
  45. package/dist/server-artifact.js +205 -0
  46. package/dist/server-language-backend.d.ts +89 -0
  47. package/dist/server-language-backend.js +121 -0
  48. package/dist/site-delivery.d.ts +134 -0
  49. package/dist/site-delivery.js +345 -0
  50. package/dist/static-emit.d.ts +145 -0
  51. package/dist/static-emit.js +577 -0
  52. package/package.json +13 -13
package/dist/index.d.ts CHANGED
@@ -14,8 +14,8 @@ export declare function expectedProtocol(): {
14
14
  pluginProtocol: string;
15
15
  };
16
16
  /**
17
- * Resolve native `.node` via the platform optionalDependency only
18
- * (`@vmz/vmz-<short>` from pnpm workspace or published npm).
17
+ * Resolve native `.node` via the platform optionalDependency
18
+ * (`@vmz/vmz-<short>`; transitional fallback `@vmz/vmz-<short>`).
19
19
  * @returns {string}
20
20
  */
21
21
  export declare function resolveNativePath(): any;
@@ -138,14 +138,30 @@ export declare function checkApplicationHostCompositionJson(hostRoot: any, packa
138
138
  */
139
139
  export declare function checkApplicationDevTestDeployJson(hostRoot: any, packageRoots: any, dirtyPaths?: any[]): any;
140
140
  export { createDevSession, listWatchedFiles, srcFingerprint } from './dev-session.js';
141
+ export { findAvailablePort } from './port.js';
141
142
  export { runCli, parseArgs, printHelp, printGlobalHelp, printProjectHelp } from './cli.js';
142
143
  export { findNearestProjectVmz, getInvocationContext, isGlobalAllowedCommand, isUnderNodeModules, resolveThisPackageRoot, resolveVmzBin, gateGlobalProjectCommand, } from './invocation.js';
143
144
  export { resolveWorkspaceDirs, findPackageJson, readPackageMeta } from './resolve.js';
144
145
  export { resolvePackageRoot, resolveWorkspacePackages } from './packages.js';
145
146
  export { log } from './log.js';
146
147
  export { cmdApplication, runCheck as runApplicationCheck } from './application-cmd.js';
148
+ export { cmdArtifact } from './release-cmd.js';
149
+ export { ARTIFACT_DIFF_SCHEMA, DELIVERY_ARTIFACT_MANIFEST_SCHEMA, RELEASE_ENVELOPE_SCHEMA, ROUTE_REALIZATION_TABLE_SCHEMA, atomicWritePointer, canonicalJson, diffArtifacts, loadReleaseEnvelope, packRelease, publishRelease, readPointer, rollbackRelease, sha256File, sha256Hex, } from './release-pack.js';
150
+ export { STATIC_DELIVERY_MANIFEST_SCHEMA, emitWebStatic, } from './static-emit.js';
151
+ export { CONTENT_ADDRESSED_ASSETS_SCHEMA, emitContentAddressedAssets, resolveAssetByDigest, assertSharedAssetPath, contentAddressedAssetsDigest, } from './content-addressed-assets.js';
152
+ export { CDN_POLICY_MANIFEST_SCHEMA, CDN_ADAPTER_PROJECTION_SCHEMA, CACHE_HTML, CACHE_ASSET_IMMUTABLE, CACHE_META, buildCdnPolicyManifest, emitCdnPolicy, projectCdnAdapter, createLocalStaticHandler, listenLocalStaticHost, matchGlob, } from './cdn-policy.js';
153
+ export { SITE_DELIVERY_CONTRACT_SCHEMA, SITE_DELIVERY_RESOLUTION_SCHEMA, defineSite, normalizeSiteDelivery, normalizeSourceProbe, resolveSiteRelease, probeReleaseDirectory, emitSiteDelivery, } from './site-delivery.js';
154
+ export { EMBEDDED_RESOURCE_INDEX_SCHEMA, emitEmbeddedPackaging, } from './embedded-packaging.js';
155
+ export { SERVER_LANG_IDS, SERVER_LANG_ALIASES, SERVER_LANGUAGE_BACKENDS, resolveServerLanguage, assertLangRuntimePair, } from './server-language-backend.js';
156
+ export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSEMBLIES, SERVER_RUNTIMES, BUILTIN_PROFILES, pickSiteAuthoring, normalizeDeliveryAuthoring, selectBuildProfile, semanticIdsForAssembly, } from './delivery-profile.js';
157
+ export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
158
+ export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
159
+ export { BUILD_PROOF_SCHEMA, ASSEMBLE_MANIFEST_SCHEMA, assembleDelivery, emitBuildProof, } from './build-assemble.js';
160
+ export { PRODUCTION_SCENARIO_PACK_SCHEMA, PRODUCTION_CI_PROFILE_SCHEMA, PRODUCTION_TEST_REPORT_SCHEMA, browserProductionScenarioPack, browserProductionCiProfile, normalizeScenarioPack, normalizeCiProfile, scenarioPackDigest, ciProfileDigest, buildProductionTestReport, productionTestReportDigest, emitProductionTestArtifacts, assertNoForbiddenRunners, } from './production-test-pack.js';
161
+ export { PRODUCTION_OBSERVABILITY_SCHEMA, PRODUCTION_TRACE_SCHEMA, REQUIRED_TRACE_FACETS, browserProductionObservability, normalizeObservability, redactSensitive, validateProductionTrace, buildCoveringProductionTrace, checkProductionBudgets, checkCapabilityClosure, applySecurityHeadersToCdnPolicy, measureDistBudgets, emitProductionObservability, observabilityDigest, } from './production-observability.js';
147
162
  export { buildApplicationContext, buildFormatterContext, checkLocaleRuntime, checkSsrClientParity, createLocaleSession, formatMessageTemplate, formatterContextDigest, negotiateLocale, resolveMessageVariant, validateFormatterContext, } from './locale-runtime.js';
148
- export { absoluteUrl, assertLocaleCacheKey, buildLocalePageMeta, buildLocaleRouteRealizationTable, checkLocaleRouter, commitLocaleRouteMetaTransition, localeAwareCacheKey, parseLocaleFromPath, planLocalePathNavigation, realizeRoutePath, resolveLinkHref, } from './locale-router.js';
163
+ export { absoluteUrl, assertLocaleCacheKey, buildLocalePageMeta, buildLocaleRouteRealizationTable, checkLocaleRouter, commitLocaleRouteMetaTransition, localeAwareCacheKey, localizeBodyLinks, localizeSameAppHref, parseLocaleFromPath, planLocalePathNavigation, realizeRoutePath, resolveLinkHref, } from './locale-router.js';
164
+ export { LOCALE_ROUTE_REALIZATION_ARTIFACT_SCHEMA, emitLocaleRouteRealization, } from './locale-route-emit.js';
149
165
  export { assertHostMessageInvariant, assertServerErrorEnvelope, assertServerFormatContext, buildLocaleDeliveryResolution, checkLocaleDelivery, fallbackDigest, messageCatalogHash, proveMiniPackageMessages, validateNativeLocalePack, } from './locale-delivery.js';
150
166
  export { checkLocaleConformance, diffLocaleCatalogs, explainLocaleMessage, extractHardcodedText, pseudoLocalizeCatalog, } from './locale-tooling.js';
151
167
  export { applyPlugins, contentHash, defineConfig, definePlugin, loadVmzConfig, } from './plugin-host.js';
package/dist/index.js CHANGED
@@ -52,32 +52,34 @@ function platformShort(triple = platformTriple()) {
52
52
  return triple;
53
53
  }
54
54
  /**
55
- * Resolve native `.node` via the platform optionalDependency only
56
- * (`@vmz/vmz-<short>` from pnpm workspace or published npm).
55
+ * Resolve native `.node` via the platform optionalDependency
56
+ * (`@vmz/vmz-<short>`; transitional fallback `@vmz/vmz-<short>`).
57
57
  * @returns {string}
58
58
  */
59
59
  export function resolveNativePath() {
60
60
  const triple = platformTriple();
61
61
  const short = platformShort(triple);
62
- const name = `@vmz/vmz-${short}`;
62
+ const names = [`@vmz/vmz-${short}`, `@vmz/vmz-${short}`];
63
63
  /** @type {string[]} */
64
64
  const candidates = [];
65
- try {
66
- const resolved = require.resolve(`${name}/package.json`);
67
- const dir = path.dirname(resolved);
68
- // Prefer platform-named binary; plain `vmz.node` is legacy-only.
69
- candidates.push(path.join(dir, `vmz.${triple}.node`), path.join(dir, 'vmz.node'));
70
- }
71
- catch {
72
- /* optional dep not installed */
65
+ for (const name of names) {
66
+ try {
67
+ const resolved = require.resolve(`${name}/package.json`);
68
+ const dir = path.dirname(resolved);
69
+ // Prefer platform-named binary; plain `vmz.node` is legacy-only.
70
+ candidates.push(path.join(dir, `vmz.${triple}.node`), path.join(dir, 'vmz.node'));
71
+ }
72
+ catch {
73
+ /* optional dep not installed */
74
+ }
75
+ // pnpm may nest under the @vmz/vmz package's node_modules
76
+ candidates.push(path.join(pkgRoot, 'node_modules', name, `vmz.${triple}.node`), path.join(pkgRoot, 'node_modules', name, 'vmz.node'));
73
77
  }
74
- // pnpm may nest under the vmz package's node_modules
75
- candidates.push(path.join(pkgRoot, 'node_modules', name, `vmz.${triple}.node`), path.join(pkgRoot, 'node_modules', name, 'vmz.node'));
76
78
  for (const p of candidates) {
77
79
  if (existsSync(p))
78
80
  return p;
79
81
  }
80
- throw new Error(`vmz native addon not found for ${name}. Run: pnpm napi:build (writes packages/runtimes/vmz-${short}/)\n` +
82
+ throw new Error(`vmz native addon not found for @vmz/vmz-${short}. Run: pnpm napi:build (writes packages/runtimes/vmz-${short}/)\n` +
81
83
  `Looked in:\n${candidates.map((c) => ` - ${c}`).join('\n')}`);
82
84
  }
83
85
  let _native;
@@ -316,14 +318,32 @@ export function checkApplicationDevTestDeployJson(hostRoot, packageRoots, dirtyP
316
318
  return native.checkApplicationDevTestDeployJson(hostRoot, packageRoots, dirtyPaths);
317
319
  }
318
320
  export { createDevSession, listWatchedFiles, srcFingerprint } from './dev-session.js';
321
+ export { findAvailablePort } from './port.js';
319
322
  export { runCli, parseArgs, printHelp, printGlobalHelp, printProjectHelp } from './cli.js';
320
323
  export { findNearestProjectVmz, getInvocationContext, isGlobalAllowedCommand, isUnderNodeModules, resolveThisPackageRoot, resolveVmzBin, gateGlobalProjectCommand, } from './invocation.js';
321
324
  export { resolveWorkspaceDirs, findPackageJson, readPackageMeta } from './resolve.js';
322
325
  export { resolvePackageRoot, resolveWorkspacePackages } from './packages.js';
323
326
  export { log } from './log.js';
324
327
  export { cmdApplication, runCheck as runApplicationCheck } from './application-cmd.js';
328
+ export { cmdArtifact } from './release-cmd.js';
329
+ export { ARTIFACT_DIFF_SCHEMA, DELIVERY_ARTIFACT_MANIFEST_SCHEMA, RELEASE_ENVELOPE_SCHEMA, ROUTE_REALIZATION_TABLE_SCHEMA, atomicWritePointer, canonicalJson, diffArtifacts, loadReleaseEnvelope, packRelease, publishRelease, readPointer, rollbackRelease, sha256File, sha256Hex, } from './release-pack.js';
330
+ // APPLICATION_ARTIFACT_SCHEMA lives in @vmz/protocol (already re-exported above);
331
+ // release-pack keeps a local constant for envelope writes — do not dual-export the name.
332
+ export { STATIC_DELIVERY_MANIFEST_SCHEMA, emitWebStatic, } from './static-emit.js';
333
+ export { CONTENT_ADDRESSED_ASSETS_SCHEMA, emitContentAddressedAssets, resolveAssetByDigest, assertSharedAssetPath, contentAddressedAssetsDigest, } from './content-addressed-assets.js';
334
+ export { CDN_POLICY_MANIFEST_SCHEMA, CDN_ADAPTER_PROJECTION_SCHEMA, CACHE_HTML, CACHE_ASSET_IMMUTABLE, CACHE_META, buildCdnPolicyManifest, emitCdnPolicy, projectCdnAdapter, createLocalStaticHandler, listenLocalStaticHost, matchGlob, } from './cdn-policy.js';
335
+ export { SITE_DELIVERY_CONTRACT_SCHEMA, SITE_DELIVERY_RESOLUTION_SCHEMA, defineSite, normalizeSiteDelivery, normalizeSourceProbe, resolveSiteRelease, probeReleaseDirectory, emitSiteDelivery, } from './site-delivery.js';
336
+ export { EMBEDDED_RESOURCE_INDEX_SCHEMA, emitEmbeddedPackaging, } from './embedded-packaging.js';
337
+ export { SERVER_LANG_IDS, SERVER_LANG_ALIASES, SERVER_LANGUAGE_BACKENDS, resolveServerLanguage, assertLangRuntimePair, } from './server-language-backend.js';
338
+ export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSEMBLIES, SERVER_RUNTIMES, BUILTIN_PROFILES, pickSiteAuthoring, normalizeDeliveryAuthoring, selectBuildProfile, semanticIdsForAssembly, } from './delivery-profile.js';
339
+ export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
340
+ export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
341
+ export { BUILD_PROOF_SCHEMA, ASSEMBLE_MANIFEST_SCHEMA, assembleDelivery, emitBuildProof, } from './build-assemble.js';
342
+ export { PRODUCTION_SCENARIO_PACK_SCHEMA, PRODUCTION_CI_PROFILE_SCHEMA, PRODUCTION_TEST_REPORT_SCHEMA, browserProductionScenarioPack, browserProductionCiProfile, normalizeScenarioPack, normalizeCiProfile, scenarioPackDigest, ciProfileDigest, buildProductionTestReport, productionTestReportDigest, emitProductionTestArtifacts, assertNoForbiddenRunners, } from './production-test-pack.js';
343
+ export { PRODUCTION_OBSERVABILITY_SCHEMA, PRODUCTION_TRACE_SCHEMA, REQUIRED_TRACE_FACETS, browserProductionObservability, normalizeObservability, redactSensitive, validateProductionTrace, buildCoveringProductionTrace, checkProductionBudgets, checkCapabilityClosure, applySecurityHeadersToCdnPolicy, measureDistBudgets, emitProductionObservability, observabilityDigest, } from './production-observability.js';
325
344
  export { buildApplicationContext, buildFormatterContext, checkLocaleRuntime, checkSsrClientParity, createLocaleSession, formatMessageTemplate, formatterContextDigest, negotiateLocale, resolveMessageVariant, validateFormatterContext, } from './locale-runtime.js';
326
- export { absoluteUrl, assertLocaleCacheKey, buildLocalePageMeta, buildLocaleRouteRealizationTable, checkLocaleRouter, commitLocaleRouteMetaTransition, localeAwareCacheKey, parseLocaleFromPath, planLocalePathNavigation, realizeRoutePath, resolveLinkHref, } from './locale-router.js';
345
+ export { absoluteUrl, assertLocaleCacheKey, buildLocalePageMeta, buildLocaleRouteRealizationTable, checkLocaleRouter, commitLocaleRouteMetaTransition, localeAwareCacheKey, localizeBodyLinks, localizeSameAppHref, parseLocaleFromPath, planLocalePathNavigation, realizeRoutePath, resolveLinkHref, } from './locale-router.js';
346
+ export { LOCALE_ROUTE_REALIZATION_ARTIFACT_SCHEMA, emitLocaleRouteRealization, } from './locale-route-emit.js';
327
347
  export { assertHostMessageInvariant, assertServerErrorEnvelope, assertServerFormatContext, buildLocaleDeliveryResolution, checkLocaleDelivery, fallbackDigest, messageCatalogHash, proveMiniPackageMessages, validateNativeLocalePack, } from './locale-delivery.js';
328
348
  export { checkLocaleConformance, diffLocaleCatalogs, explainLocaleMessage, extractHardcodedText, pseudoLocalizeCatalog, } from './locale-tooling.js';
329
349
  export { applyPlugins, contentHash, defineConfig, definePlugin, loadVmzConfig, } from './plugin-host.js';
@@ -1,58 +1,40 @@
1
1
  /**
2
2
  * `vmz` CLI invocation modes (JS gate only; Rust binary stays full).
3
3
  *
4
+ * Product install face: workspace `vmz` / publish `@vmz/vmz` (bin still `vmz`).
5
+ *
4
6
  * Three modes — do not collapse them:
5
7
  * - **developer**: monorepo source checkout (`packages/runtimes/vmz`, not under node_modules)
6
- * - **project**: app's `node_modules/vmz` or `node_modules/@vmz/vmz` (pnpm/npm/yarn)
8
+ * - **project**: app's nearest `node_modules/vmz` or `node_modules/@vmz/vmz`
7
9
  * - **global**: npm/pnpm global (or any install under node_modules that is not the nearest project one)
8
10
  *
9
11
  */
10
- /** @typedef {'developer' | 'project' | 'global'} InvocationMode */
11
12
  /**
12
- * Package root of the running `vmz` / `@vmz/vmz` install (`…/vmz`, not `…/vmz/dist`).
13
+ * Package root of the running `vmz` / `@vmz/vmz` install.
13
14
  * @param {string} [fromUrl]
14
15
  */
15
16
  export declare function resolveThisPackageRoot(fromUrl?: string): string;
16
17
  /**
17
- * Walk from `startDir` for nearest project `vmz` / `@vmz/vmz` package root.
18
+ * Walk from `startDir` for nearest project CLI package root.
18
19
  * @param {string} startDir
19
- * @returns {string | null} realpath of package root
20
+ * @returns {string | null}
20
21
  */
21
22
  export declare function findNearestProjectVmz(startDir: any): string;
22
23
  /**
23
- * Resolve CLI entry for a `vmz` package root (`bin/vmz.js`).
24
+ * Resolve CLI entry (`bin/vmz.js`).
24
25
  * @param {string} packageRoot
25
26
  * @returns {string | null}
26
27
  */
27
28
  export declare function resolveVmzBin(packageRoot: any): string;
28
29
  /**
29
- * Install lives under a `node_modules` tree (npm -g, pnpm store link, etc.).
30
- * Workspace source checkout (`packages/runtimes/vmz`) does not → developer mode.
31
30
  * @param {string} packageRoot
32
31
  */
33
32
  export declare function isUnderNodeModules(packageRoot: any): boolean;
34
33
  /**
35
- * Classify how this process was launched.
36
- *
37
- * | mode | thisPackageRoot | rule |
38
- * |-------------|-----------------------------------------|-------------------------------------------|
39
- * | developer | monorepo `packages/runtimes/vmz` | not under `node_modules` |
40
- * | project | app `node_modules/(@vmz/)vmz` | under node_modules ∧ equals nearest |
41
- * | global | global / unrelated node_modules install | under node_modules ∧ not nearest project |
42
- *
43
34
  * @param {{
44
35
  * cwd?: string,
45
36
  * thisPackageRoot?: string,
46
37
  * }} [opts]
47
- * @returns {{
48
- * mode: InvocationMode,
49
- * cwd: string,
50
- * thisPackageRoot: string,
51
- * nearestProjectVmz: string | null,
52
- * isDeveloper: boolean,
53
- * isProjectLocal: boolean,
54
- * isGlobalLike: boolean,
55
- * }}
56
38
  */
57
39
  export declare function getInvocationContext(opts?: {}): {
58
40
  mode: any;
@@ -65,21 +47,16 @@ export declare function getInvocationContext(opts?: {}): {
65
47
  isGlobalLike: boolean;
66
48
  };
67
49
  /**
68
- * Commands allowed in **global** mode without re-exec / refusal.
69
- * Developer + project modes allow the full CLI.
70
50
  * @param {string | undefined} cmd
71
51
  */
72
52
  export declare function isGlobalAllowedCommand(cmd: any): boolean;
73
53
  /**
74
54
  * @param {string} bin
75
- * @param {string[]} argv full argv including command (e.g. `['check', '.']`)
55
+ * @param {string[]} argv
76
56
  * @returns {Promise<number>}
77
57
  */
78
58
  export declare function reexecProjectVmz(bin: any, argv: any): Promise<unknown>;
79
59
  /**
80
- * Guard for project-only commands when the current install is **global** mode.
81
- * Developer / project → proceed. Global + local present → re-exec. Global alone → refuse.
82
- *
83
60
  * @returns {Promise<{ action: 'proceed' } | { action: 'exit', code: number }>}
84
61
  */
85
62
  export declare function gateGlobalProjectCommand(opts: any): Promise<{
@@ -2,9 +2,11 @@
2
2
  /**
3
3
  * `vmz` CLI invocation modes (JS gate only; Rust binary stays full).
4
4
  *
5
+ * Product install face: workspace `vmz` / publish `@vmz/vmz` (bin still `vmz`).
6
+ *
5
7
  * Three modes — do not collapse them:
6
8
  * - **developer**: monorepo source checkout (`packages/runtimes/vmz`, not under node_modules)
7
- * - **project**: app's `node_modules/vmz` or `node_modules/@vmz/vmz` (pnpm/npm/yarn)
9
+ * - **project**: app's nearest `node_modules/vmz` or `node_modules/@vmz/vmz`
8
10
  * - **global**: npm/pnpm global (or any install under node_modules that is not the nearest project one)
9
11
  *
10
12
  */
@@ -13,8 +15,9 @@ import { existsSync, realpathSync } from 'node:fs';
13
15
  import path from 'node:path';
14
16
  import { fileURLToPath } from 'node:url';
15
17
  /** @typedef {'developer' | 'project' | 'global'} InvocationMode */
18
+ const PROJECT_PKG_SEGMENTS = [['@vmz', 'vmz'], ['vmz']];
16
19
  /**
17
- * Package root of the running `vmz` / `@vmz/vmz` install (`…/vmz`, not `…/vmz/dist`).
20
+ * Package root of the running `vmz` / `@vmz/vmz` install.
18
21
  * @param {string} [fromUrl]
19
22
  */
20
23
  export function resolveThisPackageRoot(fromUrl = import.meta.url) {
@@ -32,15 +35,15 @@ function tryRealpath(p) {
32
35
  }
33
36
  }
34
37
  /**
35
- * Walk from `startDir` for nearest project `vmz` / `@vmz/vmz` package root.
38
+ * Walk from `startDir` for nearest project CLI package root.
36
39
  * @param {string} startDir
37
- * @returns {string | null} realpath of package root
40
+ * @returns {string | null}
38
41
  */
39
42
  export function findNearestProjectVmz(startDir) {
40
43
  let dir = path.resolve(startDir);
41
44
  for (;;) {
42
- const candidates = [path.join(dir, 'node_modules', 'vmz'), path.join(dir, 'node_modules', '@vmz', 'vmz')];
43
- for (const candidate of candidates) {
45
+ for (const segments of PROJECT_PKG_SEGMENTS) {
46
+ const candidate = path.join(dir, 'node_modules', ...segments);
44
47
  const pkgJson = path.join(candidate, 'package.json');
45
48
  if (existsSync(pkgJson)) {
46
49
  return tryRealpath(candidate);
@@ -53,7 +56,7 @@ export function findNearestProjectVmz(startDir) {
53
56
  }
54
57
  }
55
58
  /**
56
- * Resolve CLI entry for a `vmz` package root (`bin/vmz.js`).
59
+ * Resolve CLI entry (`bin/vmz.js`).
57
60
  * @param {string} packageRoot
58
61
  * @returns {string | null}
59
62
  */
@@ -64,8 +67,6 @@ export function resolveVmzBin(packageRoot) {
64
67
  return null;
65
68
  }
66
69
  /**
67
- * Install lives under a `node_modules` tree (npm -g, pnpm store link, etc.).
68
- * Workspace source checkout (`packages/runtimes/vmz`) does not → developer mode.
69
70
  * @param {string} packageRoot
70
71
  */
71
72
  export function isUnderNodeModules(packageRoot) {
@@ -74,27 +75,10 @@ export function isUnderNodeModules(packageRoot) {
74
75
  return parts.includes('node_modules');
75
76
  }
76
77
  /**
77
- * Classify how this process was launched.
78
- *
79
- * | mode | thisPackageRoot | rule |
80
- * |-------------|-----------------------------------------|-------------------------------------------|
81
- * | developer | monorepo `packages/runtimes/vmz` | not under `node_modules` |
82
- * | project | app `node_modules/(@vmz/)vmz` | under node_modules ∧ equals nearest |
83
- * | global | global / unrelated node_modules install | under node_modules ∧ not nearest project |
84
- *
85
78
  * @param {{
86
79
  * cwd?: string,
87
80
  * thisPackageRoot?: string,
88
81
  * }} [opts]
89
- * @returns {{
90
- * mode: InvocationMode,
91
- * cwd: string,
92
- * thisPackageRoot: string,
93
- * nearestProjectVmz: string | null,
94
- * isDeveloper: boolean,
95
- * isProjectLocal: boolean,
96
- * isGlobalLike: boolean,
97
- * }}
98
82
  */
99
83
  export function getInvocationContext(opts = {}) {
100
84
  const cwd = path.resolve(opts.cwd ?? process.cwd());
@@ -124,8 +108,6 @@ export function getInvocationContext(opts = {}) {
124
108
  };
125
109
  }
126
110
  /**
127
- * Commands allowed in **global** mode without re-exec / refusal.
128
- * Developer + project modes allow the full CLI.
129
111
  * @param {string | undefined} cmd
130
112
  */
131
113
  export function isGlobalAllowedCommand(cmd) {
@@ -142,7 +124,7 @@ export function isGlobalAllowedCommand(cmd) {
142
124
  }
143
125
  /**
144
126
  * @param {string} bin
145
- * @param {string[]} argv full argv including command (e.g. `['check', '.']`)
127
+ * @param {string[]} argv
146
128
  * @returns {Promise<number>}
147
129
  */
148
130
  export function reexecProjectVmz(bin, argv) {
@@ -161,9 +143,6 @@ export function reexecProjectVmz(bin, argv) {
161
143
  });
162
144
  }
163
145
  /**
164
- * Guard for project-only commands when the current install is **global** mode.
165
- * Developer / project → proceed. Global + local present → re-exec. Global alone → refuse.
166
- *
167
146
  * @returns {Promise<{ action: 'proceed' } | { action: 'exit', code: number }>}
168
147
  */
169
148
  export async function gateGlobalProjectCommand(opts) {
@@ -175,7 +154,7 @@ export async function gateGlobalProjectCommand(opts) {
175
154
  if (ctx.nearestProjectVmz && ctx.nearestProjectVmz !== ctx.thisPackageRoot) {
176
155
  const bin = resolveVmzBin(ctx.nearestProjectVmz);
177
156
  if (!bin) {
178
- logError('found project `@vmz/vmz` / `vmz` but bin/vmz.js is missing.');
157
+ logError('found project `vmz` / `@vmz/vmz` but bin/vmz.js is missing.');
179
158
  return { action: 'exit', code: 1 };
180
159
  }
181
160
  const code = await reexec(bin, argv);
@@ -80,6 +80,22 @@ export declare function scanLocaleUsages(projectRoot: any): {
80
80
  * @param {string} outDir
81
81
  */
82
82
  export declare function emitLocaleTypedModules(report: any, outDir: any): any[];
83
+ /**
84
+ * Emit runtime `#locales/<catalog>.js` into application `dist/` and rewrite
85
+ * client imports from `#locales/...` to relative ESM paths.
86
+ *
87
+ * Variant pick reads `html[data-locale]` (else defaultLocale). Thin bridge until
88
+ * host LocaleTransition reloads locale-scoped chunks (I2/I4).
89
+ *
90
+ * @param {string} projectRoot
91
+ * @param {string} distDir
92
+ * @returns {{ ok: boolean, written: string[], diagnostics: any[] }}
93
+ */
94
+ export declare function emitLocaleRuntimeModules(projectRoot: any, distDir: any): {
95
+ ok: boolean;
96
+ written: any[];
97
+ diagnostics: any;
98
+ };
83
99
  /**
84
100
  * MessageId rename plan — WorkspaceEdit-shaped, no parallel rename IR.
85
101
  * @param {ReturnType<typeof checkLocales>} report
@@ -250,10 +250,12 @@ export function checkLocales(opts) {
250
250
  const manifestPathJson = path.join(localesRoot, 'locales.json');
251
251
  const manifestPath = fs.existsSync(manifestPathJson5) ? manifestPathJson5 : fs.existsSync(manifestPathJson) ? manifestPathJson : null;
252
252
  if (!fs.existsSync(localesRoot) || !manifestPath) {
253
+ // Discipline nudge: i18n is first-class — missing policy is never silent.
254
+ // Soft for now (warning); production profiles may elevate to error later.
253
255
  diagnostics.push({
254
256
  code: DIAG_MANIFEST_MISSING,
255
- severity: 'error',
256
- message: 'locales/locales.json5 missing (LocaleId policy truth source)',
257
+ severity: 'warning',
258
+ message: 'locales/locales.json5 missing — declare LocaleId policy under /locales (native i18n, not an afterthought)',
257
259
  path: 'locales/locales.json5',
258
260
  });
259
261
  return emptyReport(projectRoot, diagnostics);
@@ -586,9 +588,10 @@ function paramSignature(params) {
586
588
  .join(',');
587
589
  }
588
590
  function emptyReport(projectRoot, diagnostics) {
591
+ const hasErrors = (diagnostics || []).some((d) => d.severity === 'error');
589
592
  return {
590
593
  schema: LOCALE_CHECK_SCHEMA,
591
- status: 'failed',
594
+ status: hasErrors ? 'failed' : 'ready',
592
595
  root: projectRoot,
593
596
  localesRoot: 'locales',
594
597
  manifest: null,
@@ -694,6 +697,131 @@ export function emitLocaleTypedModules(report, outDir) {
694
697
  fs.writeFileSync(path.join(outDir, 'index.json'), `${JSON.stringify(index, null, 2)}\n`, 'utf8');
695
698
  return written;
696
699
  }
700
+ /**
701
+ * Emit runtime `#locales/<catalog>.js` into application `dist/` and rewrite
702
+ * client imports from `#locales/...` to relative ESM paths.
703
+ *
704
+ * Variant pick reads `html[data-locale]` (else defaultLocale). Thin bridge until
705
+ * host LocaleTransition reloads locale-scoped chunks (I2/I4).
706
+ *
707
+ * @param {string} projectRoot
708
+ * @param {string} distDir
709
+ * @returns {{ ok: boolean, written: string[], diagnostics: any[] }}
710
+ */
711
+ export function emitLocaleRuntimeModules(projectRoot, distDir) {
712
+ const report = checkLocales({ projectRoot, checkUnused: false });
713
+ if (localeHasErrors(report)) {
714
+ return { ok: false, written: [], diagnostics: report.diagnostics || [] };
715
+ }
716
+ // Missing locales.json5 is warning-only for now — surface diagnostics, skip emit.
717
+ if (!report.manifest) {
718
+ return { ok: true, written: [], diagnostics: report.diagnostics || [] };
719
+ }
720
+ const defaultLocale = report.manifest.defaultLocale || 'zh-hans';
721
+ const byId = new Map((report.messageCatalog?.messages || []).map((m) => [m.messageId, m]));
722
+ /** @type {string[]} */
723
+ const written = [];
724
+ const localesOut = path.join(distDir, 'locales');
725
+ fs.mkdirSync(localesOut, { recursive: true });
726
+ for (const mod of report.typedModules || []) {
727
+ const lines = [
728
+ `/** Generated ${mod.module} — runtime LocalizedText (defaultLocale=${defaultLocale}) */`,
729
+ `const __vmzDefaultLocale = ${JSON.stringify(defaultLocale)};`,
730
+ `function __vmzLocaleId() {`,
731
+ ` try {`,
732
+ ` const stored = localStorage.getItem("vmz.locale");`,
733
+ ` if (stored) return stored;`,
734
+ ` } catch {}`,
735
+ ` if (typeof document !== "undefined") {`,
736
+ ` const d = document.documentElement?.getAttribute("data-locale");`,
737
+ ` if (d) return d;`,
738
+ ` const lang = document.documentElement?.lang;`,
739
+ ` if (lang === "en" || lang === "en-US" || lang === "en-us") return "en-us";`,
740
+ ` if (lang === "zh" || lang === "zh-CN" || lang === "zh-Hans" || lang === "zh-hans") return "zh-hans";`,
741
+ ` }`,
742
+ ` return __vmzDefaultLocale;`,
743
+ `}`,
744
+ `function __vmzFormat(template, args) {`,
745
+ ` if (!args) return String(template ?? "");`,
746
+ ` return String(template ?? "").replace(/\\{(\\w+)(?:,\\s*\\w+)?\\}/g, (m, name) =>`,
747
+ ` Object.prototype.hasOwnProperty.call(args, name) ? String(args[name]) : m`,
748
+ ` );`,
749
+ `}`,
750
+ `function __vmzPick(variants, args) {`,
751
+ ` const id = __vmzLocaleId();`,
752
+ ` const template = variants[id] ?? variants[__vmzDefaultLocale] ?? "";`,
753
+ ` return __vmzFormat(template, args);`,
754
+ `}`,
755
+ '',
756
+ ];
757
+ for (const exp of mod.exports || []) {
758
+ const node = byId.get(exp.messageId);
759
+ const variants = {};
760
+ if (node?.variants) {
761
+ for (const [loc, v] of Object.entries(node.variants)) {
762
+ variants[loc] = v.template;
763
+ }
764
+ }
765
+ const lit = JSON.stringify(variants);
766
+ if ((exp.params || []).length) {
767
+ lines.push(`export function ${exp.exportName}(args) { return __vmzPick(${lit}, args); }`);
768
+ }
769
+ else {
770
+ lines.push(`export function ${exp.exportName}() { return __vmzPick(${lit}); }`);
771
+ }
772
+ }
773
+ lines.push('');
774
+ const file = path.join(localesOut, `${mod.catalogId}.js`);
775
+ fs.mkdirSync(path.dirname(file), { recursive: true });
776
+ fs.writeFileSync(file, lines.join('\n'), 'utf8');
777
+ written.push(file);
778
+ }
779
+ rewriteLocaleImportsInDist(distDir);
780
+ return { ok: true, written, diagnostics: report.diagnostics || [] };
781
+ }
782
+ /**
783
+ * @param {string} distDir
784
+ */
785
+ function rewriteLocaleImportsInDist(distDir) {
786
+ /** @type {string[]} */
787
+ const files = [];
788
+ walkDistJs(distDir, (file) => files.push(file));
789
+ for (const file of files) {
790
+ let text = fs.readFileSync(file, 'utf8');
791
+ if (!text.includes('#locales/'))
792
+ continue;
793
+ const fromDir = path.dirname(file);
794
+ // Emit path is dist/locales/*.js — `#` cannot appear in ESM file URLs (fragment).
795
+ const next = text.replace(/from\s*(["'])#locales\/([^"']+)\1/g, (_m, quote, id) => {
796
+ const target = path.join(distDir, 'locales', `${id}.js`);
797
+ let rel = path.relative(fromDir, target).replace(/\\/g, '/');
798
+ if (!rel.startsWith('.'))
799
+ rel = `./${rel}`;
800
+ return `from ${quote}${rel}${quote}`;
801
+ });
802
+ if (next !== text)
803
+ fs.writeFileSync(file, next, 'utf8');
804
+ }
805
+ }
806
+ /**
807
+ * @param {string} dir
808
+ * @param {(file: string) => void} fn
809
+ */
810
+ function walkDistJs(dir, fn) {
811
+ if (!fs.existsSync(dir))
812
+ return;
813
+ for (const ent of fs.readdirSync(dir, { withFileTypes: true })) {
814
+ const full = path.join(dir, ent.name);
815
+ if (ent.isDirectory()) {
816
+ if (ent.name === 'node_modules')
817
+ continue;
818
+ walkDistJs(full, fn);
819
+ }
820
+ else if (ent.name.endsWith('.js') || ent.name.endsWith('.mjs')) {
821
+ fn(full);
822
+ }
823
+ }
824
+ }
697
825
  /**
698
826
  * MessageId rename plan — WorkspaceEdit-shaped, no parallel rename IR.
699
827
  * @param {ReturnType<typeof checkLocales>} report
@@ -117,8 +117,8 @@ function cmdLocaleList(args) {
117
117
  const projectRoot = resolveProject(args);
118
118
  const report = checkLocales({ projectRoot, checkUnused: false });
119
119
  if (!report.manifest) {
120
- log.error('locales.json5 missing');
121
- return 1;
120
+ console.warn('vmz warn vmz::locale::manifest_missing: locales/locales.json5 missing');
121
+ return localeHasErrors(report) ? 1 : 0;
122
122
  }
123
123
  for (const loc of report.manifest.locales) {
124
124
  const mark = loc.id === report.manifest.defaultLocale ? ' (default)' : '';
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Emit RouteId × LocaleId realization (+ PageMeta / hreflang seed) into dist/_vmz.
3
+ * Consumed by serve-host + static-emit; LocaleId stays out of stable RouteId.
4
+ */
5
+ export declare const LOCALE_ROUTE_REALIZATION_ARTIFACT_SCHEMA = "vmz.locale.route_realization.v0";
6
+ /**
7
+ * @param {string} projectRoot
8
+ * @param {string} distDir
9
+ * @param {{ origin?: string }} [opts]
10
+ */
11
+ export declare function emitLocaleRouteRealization(projectRoot: any, distDir: any, opts?: {}): {
12
+ ok: boolean;
13
+ written: any[];
14
+ diagnostics: any;
15
+ artifact: any;
16
+ } | {
17
+ ok: boolean;
18
+ written: string[];
19
+ artifact: {
20
+ schema: string;
21
+ defaultLocale: any;
22
+ locales: any;
23
+ routing: {
24
+ strategy: any;
25
+ defaultPrefix: any;
26
+ defaultLocale: any;
27
+ };
28
+ origin: string;
29
+ routes: any;
30
+ realizations: any[];
31
+ pageMetas: any[];
32
+ };
33
+ diagnostics: any[];
34
+ };