@vmz/vmz 0.1.19 → 0.1.20

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.d.ts CHANGED
@@ -105,6 +105,7 @@ export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSE
105
105
  export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
106
106
  export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
107
107
  export { BUILD_PROOF_SCHEMA, ASSEMBLE_MANIFEST_SCHEMA, assembleDelivery, emitBuildProof, } from './build-assemble.js';
108
+ export { buildProjectToOutDirRoot, type BuildProjectOptions, type BuildProjectResult, } from './project-build.js';
108
109
  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';
109
110
  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';
110
111
  export { buildApplicationContext, buildFormatterContext, checkLocaleRuntime, checkSsrClientParity, createLocaleSession, formatMessageTemplate, formatterContextDigest, negotiateLocale, resolveMessageVariant, validateFormatterContext, } from './locale-runtime.js';
package/dist/index.js CHANGED
@@ -345,6 +345,7 @@ export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSE
345
345
  export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
346
346
  export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
347
347
  export { BUILD_PROOF_SCHEMA, ASSEMBLE_MANIFEST_SCHEMA, assembleDelivery, emitBuildProof, } from './build-assemble.js';
348
+ export { buildProjectToOutDirRoot, } from './project-build.js';
348
349
  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';
349
350
  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';
350
351
  export { buildApplicationContext, buildFormatterContext, checkLocaleRuntime, checkSsrClientParity, createLocaleSession, formatMessageTemplate, formatterContextDigest, negotiateLocale, resolveMessageVariant, validateFormatterContext, } from './locale-runtime.js';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared project delivery build (N-API + pack + assemble).
3
+ * Used by `vmz build` and `vmz test` so Browser Host sees the same
4
+ * `<out-dir>/<profiles.*.name>/` tree (including static HTML).
5
+ */
6
+ export type BuildProjectOptions = {
7
+ /** `--profile` id; empty → delivery default. */
8
+ profile?: string;
9
+ release?: boolean;
10
+ origin?: string;
11
+ /** Skip locale / documents / proof when only need pack+static for tests. */
12
+ quiet?: boolean;
13
+ };
14
+ export type BuildProjectOk = {
15
+ ok: true;
16
+ outDirRoot: string;
17
+ artifactDir: string;
18
+ deliveryName: string;
19
+ profileId: string;
20
+ assembly: string;
21
+ diagnostics: unknown[];
22
+ };
23
+ export type BuildProjectErr = {
24
+ ok: false;
25
+ outDirRoot: string;
26
+ artifactDir: string | null;
27
+ deliveryName: string | null;
28
+ diagnostics: unknown[];
29
+ error: string;
30
+ };
31
+ export type BuildProjectResult = BuildProjectOk | BuildProjectErr;
32
+ /**
33
+ * Build into `--out-dir` **root** the same way as `vmz build . --out-dir <root>`:
34
+ * nest once via `resolveProfileArtifactDir`, then N-API build + pack + assemble
35
+ * (static HTML for `web-static`). Callers resolve the serve root **after** this.
36
+ */
37
+ export declare function buildProjectToOutDirRoot(project: string, outDirRoot: string, opts?: BuildProjectOptions): Promise<BuildProjectResult>;
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Shared project delivery build (N-API + pack + assemble).
3
+ * Used by `vmz build` and `vmz test` so Browser Host sees the same
4
+ * `<out-dir>/<profiles.*.name>/` tree (including static HTML).
5
+ */
6
+ import path from 'node:path';
7
+ import { assembleDelivery, emitBuildProof } from './build-assemble.js';
8
+ import { normalizeDeliveryAuthoring, resolveProfileArtifactDir, selectBuildProfile } from './delivery-profile.js';
9
+ import { buildIntegratedDocuments, projectHasDocuments } from './document-integrate.js';
10
+ import { emitLocaleRuntimeModules, localeHasErrors } from './locale-check.js';
11
+ import { emitLocaleRouteRealization } from './locale-route-emit.js';
12
+ import { packFromDeploymentIr } from './pack.js';
13
+ import { loadVmzConfig } from './plugin-host.js';
14
+ function dedupeDiagnostics(list) {
15
+ const seen = new Set();
16
+ const out = [];
17
+ for (const d of list || []) {
18
+ const key = `${d.code || ''}\0${d.path || ''}\0${d.message || ''}\0${d.severity || ''}`;
19
+ if (seen.has(key))
20
+ continue;
21
+ seen.add(key);
22
+ out.push(d);
23
+ }
24
+ return out;
25
+ }
26
+ async function runWithPlugins(ws, project, outDir, fn) {
27
+ const { applyPlugins } = await import('./plugin-host.js');
28
+ const { plugins, engines } = await loadVmzConfig(project);
29
+ if (plugins.length) {
30
+ await applyPlugins(ws, plugins, { project, outDir, engines });
31
+ }
32
+ return await fn();
33
+ }
34
+ /**
35
+ * Build into `--out-dir` **root** the same way as `vmz build . --out-dir <root>`:
36
+ * nest once via `resolveProfileArtifactDir`, then N-API build + pack + assemble
37
+ * (static HTML for `web-static`). Callers resolve the serve root **after** this.
38
+ */
39
+ export async function buildProjectToOutDirRoot(project, outDirRoot, opts = {}) {
40
+ const root = path.resolve(outDirRoot);
41
+ const diagnostics = [];
42
+ let cfg;
43
+ try {
44
+ cfg = await loadVmzConfig(project);
45
+ }
46
+ catch (e) {
47
+ return {
48
+ ok: false,
49
+ outDirRoot: root,
50
+ artifactDir: null,
51
+ deliveryName: null,
52
+ diagnostics,
53
+ error: `loadVmzConfig failed: ${e instanceof Error ? e.message : String(e)}`,
54
+ };
55
+ }
56
+ const norm = normalizeDeliveryAuthoring(cfg.delivery ?? null);
57
+ if (!norm.ok) {
58
+ return {
59
+ ok: false,
60
+ outDirRoot: root,
61
+ artifactDir: null,
62
+ deliveryName: null,
63
+ diagnostics: norm.diagnostics ?? [],
64
+ error: 'delivery authoring invalid',
65
+ };
66
+ }
67
+ const selected = selectBuildProfile(norm.table, opts.profile || '');
68
+ if (!selected.ok) {
69
+ return {
70
+ ok: false,
71
+ outDirRoot: root,
72
+ artifactDir: null,
73
+ deliveryName: null,
74
+ diagnostics: selected.diagnostics ?? [],
75
+ error: `unknown build --profile ${opts.profile || norm.table.default}`,
76
+ };
77
+ }
78
+ const deliveryName = String(selected.profile.name || selected.selection.profileId || '');
79
+ const artifactDir = resolveProfileArtifactDir(root, selected.profile);
80
+ const assembly = String(selected.selection.assembly || '');
81
+ const profileId = String(selected.selection.profileId || '');
82
+ // Dynamic import avoids init cycle with `./index.js` re-exports.
83
+ const { createWorkspace, resolveCoreRuntimeDist } = await import('./index.js');
84
+ const ws = createWorkspace({ root: project, outDir: artifactDir });
85
+ try {
86
+ const code = await runWithPlugins(ws, project, artifactDir, () => {
87
+ const report = ws.build(Boolean(opts.release));
88
+ const diags = report.diagnostics ?? [];
89
+ diagnostics.push(...diags);
90
+ const errors = diags.filter((d) => d && (d.severity === 'error' || d.level === 'error'));
91
+ return errors.length ? 1 : 0;
92
+ });
93
+ if (code !== 0) {
94
+ return {
95
+ ok: false,
96
+ outDirRoot: root,
97
+ artifactDir,
98
+ deliveryName,
99
+ diagnostics,
100
+ error: 'workspace build reported errors',
101
+ };
102
+ }
103
+ const localeEmit = emitLocaleRuntimeModules(project, artifactDir);
104
+ const localeRoutes = emitLocaleRouteRealization(project, artifactDir, {
105
+ origin: opts.origin,
106
+ });
107
+ const localeDiags = dedupeDiagnostics([
108
+ ...(localeEmit.diagnostics ?? []),
109
+ ...(localeRoutes.diagnostics ?? []),
110
+ ]);
111
+ diagnostics.push(...localeDiags);
112
+ if (!localeEmit.ok || localeHasErrors({ diagnostics: localeEmit.diagnostics })) {
113
+ return {
114
+ ok: false,
115
+ outDirRoot: root,
116
+ artifactDir,
117
+ deliveryName,
118
+ diagnostics,
119
+ error: 'locale runtime emit failed',
120
+ };
121
+ }
122
+ if (!localeRoutes.ok) {
123
+ return {
124
+ ok: false,
125
+ outDirRoot: root,
126
+ artifactDir,
127
+ deliveryName,
128
+ diagnostics,
129
+ error: 'locale route realization emit failed',
130
+ };
131
+ }
132
+ if (projectHasDocuments(project)) {
133
+ const docs = await buildIntegratedDocuments({ projectRoot: project, outDir: artifactDir });
134
+ if (!docs.ok) {
135
+ return {
136
+ ok: false,
137
+ outDirRoot: root,
138
+ artifactDir,
139
+ deliveryName,
140
+ diagnostics,
141
+ error: 'integrated documents build failed',
142
+ };
143
+ }
144
+ }
145
+ let pack;
146
+ try {
147
+ pack = packFromDeploymentIr(artifactDir, {
148
+ release: Boolean(opts.release),
149
+ profileId,
150
+ assembly,
151
+ coreDist: resolveCoreRuntimeDist(),
152
+ projectRoot: project,
153
+ });
154
+ }
155
+ catch (err) {
156
+ return {
157
+ ok: false,
158
+ outDirRoot: root,
159
+ artifactDir,
160
+ deliveryName,
161
+ diagnostics,
162
+ error: `pack failed: ${err instanceof Error ? err.message : String(err)}`,
163
+ };
164
+ }
165
+ try {
166
+ const assemble = await assembleDelivery(artifactDir, {
167
+ selection: selected.selection,
168
+ profile: {
169
+ ...selected.profile,
170
+ sources: selected.profile.sources ||
171
+ (norm.table.sugar ? norm.table.profiles[norm.table.default]?.sources : null),
172
+ },
173
+ siteId: cfg.application?.id || undefined,
174
+ origin: opts.origin,
175
+ pack: pack.manifest,
176
+ projectRoot: project,
177
+ });
178
+ if (!opts.quiet) {
179
+ emitBuildProof(artifactDir, {
180
+ selection: selected.selection,
181
+ pack: pack.manifest,
182
+ assemble: assemble.manifest,
183
+ release: Boolean(opts.release),
184
+ });
185
+ }
186
+ }
187
+ catch (err) {
188
+ return {
189
+ ok: false,
190
+ outDirRoot: root,
191
+ artifactDir,
192
+ deliveryName,
193
+ diagnostics,
194
+ error: `assemble failed: ${err instanceof Error ? err.message : String(err)}`,
195
+ };
196
+ }
197
+ return {
198
+ ok: true,
199
+ outDirRoot: root,
200
+ artifactDir,
201
+ deliveryName,
202
+ profileId,
203
+ assembly,
204
+ diagnostics,
205
+ };
206
+ }
207
+ finally {
208
+ ws.dispose();
209
+ }
210
+ }
package/dist/test-cmd.js CHANGED
@@ -5,7 +5,8 @@
5
5
  import fs from 'node:fs';
6
6
  import os from 'node:os';
7
7
  import path from 'node:path';
8
- import { createWorkspace, loadVmzConfig, normalizeDeliveryAuthoring, resolveProfileArtifactDir, selectBuildProfile } from './index.js';
8
+ import { createWorkspace } from './index.js';
9
+ import { buildProjectToOutDirRoot } from './project-build.js';
9
10
  import { log } from './log.js';
10
11
  import { generatePrettyJson } from './pretty-json.js';
11
12
  export function registerTestCommand(cli) {
@@ -39,7 +40,7 @@ export async function cmdTest(args) {
39
40
  log.error(e instanceof Error ? e.message : String(e));
40
41
  return 1;
41
42
  }
42
- const { discoverTestManifests, buildTestReport, parseModes, buildForCompile, runCompileManifest, runLogicManifest, runSsrManifest, runResumeManifest, runBrowserManifest, runDeploymentManifest, resolveDeliveryServeRoot, } = test;
43
+ const { discoverTestManifests, buildTestReport, parseModes, runCompileManifest, runLogicManifest, runSsrManifest, runResumeManifest, runBrowserManifest, runDeploymentManifest, resolveDeliveryServeRoot, } = test;
43
44
  const project = path.resolve(String(args._[0] || '.'));
44
45
  let modes;
45
46
  try {
@@ -174,35 +175,28 @@ export async function cmdTest(args) {
174
175
  let buildError = null;
175
176
  let deliveryName = null;
176
177
  if (needsBuild) {
177
- // Align with `vmz build` / `vmz serve`: artifacts live under
178
- // `<out-dir>/<profiles.*.name>` (default name = profile id).
178
+ // Same contract as `vmz build . --out-dir <root>`: build into the
179
+ // out-dir **root** (nest + pack + static assemble inside). Do **not**
180
+ // pre-pass `resolveProfileArtifactDir` as createWorkspace outDir —
181
+ // that path skipped assemble and left Browser Host without HTML.
179
182
  const outDirRoot = outDirArg ? path.resolve(outDirArg) : fs.mkdtempSync(path.join(os.tmpdir(), 'vmz-test-'));
180
- let buildTarget = outDirRoot;
181
- try {
182
- const cfg = await loadVmzConfig(project);
183
- const norm = normalizeDeliveryAuthoring(cfg.delivery ?? null);
184
- if (norm.ok) {
185
- const selected = selectBuildProfile(norm.table, '');
186
- if (selected.ok) {
187
- deliveryName = String(selected.profile.name || selected.selection.profileId || '');
188
- buildTarget = resolveProfileArtifactDir(outDirRoot, selected.profile);
189
- }
190
- }
191
- }
192
- catch (e) {
193
- log.warn(`delivery profile resolve skipped: ${e instanceof Error ? e.message : String(e)}`);
194
- }
195
- fs.mkdirSync(buildTarget, { recursive: true });
196
- const built = buildForCompile(project, buildTarget, {
197
- createWorkspace,
198
- deliveryName,
199
- });
200
- buildOut = resolveDeliveryServeRoot(built.outDir, deliveryName);
183
+ fs.mkdirSync(outDirRoot, { recursive: true });
184
+ const built = await buildProjectToOutDirRoot(project, outDirRoot);
201
185
  buildDiags = built.diagnostics || [];
202
- if (!built.ok) {
186
+ if (built.ok === false) {
187
+ deliveryName = built.deliveryName;
203
188
  buildError = built.error || 'build failed';
189
+ buildOut = outDirRoot;
204
190
  log.error(buildError);
205
191
  }
192
+ else {
193
+ deliveryName = built.deliveryName;
194
+ buildOut = resolveDeliveryServeRoot(built.outDirRoot, built.deliveryName);
195
+ if (!fs.existsSync(path.join(buildOut, 'index.html')) && built.assembly === 'web-static') {
196
+ buildError = `web-static assemble missing index.html under ${buildOut}`;
197
+ log.error(buildError);
198
+ }
199
+ }
206
200
  }
207
201
  tests = [];
208
202
  for (const m of selected) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vmz/vmz",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
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.19",
52
- "@vmz/core": "0.1.19",
53
- "@vmz/diagnostic": "0.1.19",
54
- "@vmz/plugin": "0.1.19",
55
- "@vmz/protocol": "0.1.19",
51
+ "@vmz/commander": "0.1.20",
52
+ "@vmz/core": "0.1.20",
53
+ "@vmz/diagnostic": "0.1.20",
54
+ "@vmz/plugin": "0.1.20",
55
+ "@vmz/protocol": "0.1.20",
56
56
  "jiti": "^2.6.1"
57
57
  },
58
58
  "peerDependencies": {
59
- "@vmz/plugin-markdown-it": "0.1.19",
60
- "@vmz/test": "0.1.19",
59
+ "@vmz/plugin-markdown-it": "0.1.20",
60
+ "@vmz/test": "0.1.20",
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.19",
96
- "@vmz/vmz-win32-arm64": "0.1.19",
97
- "@vmz/vmz-darwin-x64": "0.1.19",
98
- "@vmz/vmz-darwin-arm64": "0.1.19",
99
- "@vmz/vmz-linux-x64": "0.1.19",
100
- "@vmz/vmz-linux-arm64": "0.1.19"
95
+ "@vmz/vmz-win32-x64": "0.1.20",
96
+ "@vmz/vmz-win32-arm64": "0.1.20",
97
+ "@vmz/vmz-darwin-x64": "0.1.20",
98
+ "@vmz/vmz-darwin-arm64": "0.1.20",
99
+ "@vmz/vmz-linux-x64": "0.1.20",
100
+ "@vmz/vmz-linux-arm64": "0.1.20"
101
101
  },
102
102
  "publishConfig": {
103
103
  "access": "public"