@vmz/vmz 0.1.18 → 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
@@ -2,8 +2,11 @@
2
2
  * `vmz test` command — discovery / build / filter / TestReport orchestration.
3
3
  * Semantics live in `@vmz/test` (optional peer — not installed with bare `@vmz/vmz`).
4
4
  */
5
+ import fs from 'node:fs';
6
+ import os from 'node:os';
5
7
  import path from 'node:path';
6
8
  import { createWorkspace } from './index.js';
9
+ import { buildProjectToOutDirRoot } from './project-build.js';
7
10
  import { log } from './log.js';
8
11
  import { generatePrettyJson } from './pretty-json.js';
9
12
  export function registerTestCommand(cli) {
@@ -37,7 +40,7 @@ export async function cmdTest(args) {
37
40
  log.error(e instanceof Error ? e.message : String(e));
38
41
  return 1;
39
42
  }
40
- const { discoverTestManifests, buildTestReport, parseModes, buildForCompile, runCompileManifest, runLogicManifest, runSsrManifest, runResumeManifest, runBrowserManifest, runDeploymentManifest, } = test;
43
+ const { discoverTestManifests, buildTestReport, parseModes, runCompileManifest, runLogicManifest, runSsrManifest, runResumeManifest, runBrowserManifest, runDeploymentManifest, resolveDeliveryServeRoot, } = test;
41
44
  const project = path.resolve(String(args._[0] || '.'));
42
45
  let modes;
43
46
  try {
@@ -170,16 +173,30 @@ export async function cmdTest(args) {
170
173
  let buildOut = null;
171
174
  let buildDiags = [];
172
175
  let buildError = null;
176
+ let deliveryName = null;
173
177
  if (needsBuild) {
174
- const built = buildForCompile(project, outDirArg ? path.resolve(outDirArg) : undefined, {
175
- createWorkspace,
176
- });
177
- buildOut = built.outDir;
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.
182
+ const outDirRoot = outDirArg ? path.resolve(outDirArg) : fs.mkdtempSync(path.join(os.tmpdir(), 'vmz-test-'));
183
+ fs.mkdirSync(outDirRoot, { recursive: true });
184
+ const built = await buildProjectToOutDirRoot(project, outDirRoot);
178
185
  buildDiags = built.diagnostics || [];
179
- if (!built.ok) {
186
+ if (built.ok === false) {
187
+ deliveryName = built.deliveryName;
180
188
  buildError = built.error || 'build failed';
189
+ buildOut = outDirRoot;
181
190
  log.error(buildError);
182
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
+ }
183
200
  }
184
201
  tests = [];
185
202
  for (const m of selected) {
@@ -256,7 +273,10 @@ export async function cmdTest(args) {
256
273
  base.planId = result.planId ?? base.planId;
257
274
  }
258
275
  if (doBrowser) {
259
- const result = await runBrowserManifest(m, { outDir: buildOut });
276
+ const result = await runBrowserManifest(m, {
277
+ outDir: buildOut,
278
+ deliveryName,
279
+ });
260
280
  statuses.push(result.status);
261
281
  diags.push(...result.diagnostics);
262
282
  base.programId = result.programId ?? base.programId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vmz/vmz",
3
- "version": "0.1.18",
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.18",
52
- "@vmz/core": "0.1.18",
53
- "@vmz/diagnostic": "0.1.18",
54
- "@vmz/plugin": "0.1.18",
55
- "@vmz/protocol": "0.1.18",
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.18",
60
- "@vmz/test": "0.1.18",
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.18",
96
- "@vmz/vmz-win32-arm64": "0.1.18",
97
- "@vmz/vmz-darwin-x64": "0.1.18",
98
- "@vmz/vmz-darwin-arm64": "0.1.18",
99
- "@vmz/vmz-linux-x64": "0.1.18",
100
- "@vmz/vmz-linux-arm64": "0.1.18"
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"