@vmz/vmz 0.3.12 → 0.3.13

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 (51) hide show
  1. package/delivery-runtime-files.json +1 -0
  2. package/dist/cli/cli.js +46 -23
  3. package/dist/cli/format-cmd.d.ts +9 -17
  4. package/dist/cli/format-cmd.js +37 -49
  5. package/dist/cli/format-config.d.ts +6 -9
  6. package/dist/cli/format-config.js +5 -29
  7. package/dist/delivery/delivery-profile.js +1 -1
  8. package/dist/dev/dev-session.js +16 -5
  9. package/dist/document/document-base-css.d.ts +15 -0
  10. package/dist/document/document-base-css.js +578 -0
  11. package/dist/document/document-build.d.ts +1 -0
  12. package/dist/document/document-build.js +94 -78
  13. package/dist/document/document-client.d.ts +13 -0
  14. package/dist/document/document-client.js +217 -0
  15. package/dist/document/document-cmd.js +3 -1
  16. package/dist/document/document-designs.d.ts +9 -3
  17. package/dist/document/document-designs.js +20 -34
  18. package/dist/document/document-enrich.d.ts +9 -0
  19. package/dist/document/document-enrich.js +55 -0
  20. package/dist/document/document-highlight.d.ts +26 -0
  21. package/dist/document/document-highlight.js +54 -0
  22. package/dist/document/document-integrate.d.ts +5 -0
  23. package/dist/document/document-integrate.js +1 -0
  24. package/dist/document/document-interactive.js +10 -2
  25. package/dist/document/document-layout-render.js +6 -2
  26. package/dist/document/document-schema.d.ts +5 -0
  27. package/dist/workspace/build-assemble.js +18 -6
  28. package/dist/workspace/content-addressed-assets.d.ts +6 -17
  29. package/dist/workspace/content-addressed-assets.js +10 -95
  30. package/dist/workspace/delivery-runtime-imports.js +3 -0
  31. package/dist/workspace/native-addon.d.ts +4 -0
  32. package/dist/workspace/pack-native.d.ts +139 -0
  33. package/dist/workspace/pack-native.js +273 -0
  34. package/dist/workspace/pack.d.ts +112 -32
  35. package/dist/workspace/pack.js +270 -65
  36. package/dist/workspace/plugin-host.d.ts +4 -4
  37. package/dist/workspace/plugin-host.js +6 -6
  38. package/dist/workspace/production-observability.d.ts +2 -0
  39. package/dist/workspace/production-observability.js +6 -2
  40. package/dist/workspace/project-build.js +26 -4
  41. package/dist/workspace/public-api.d.ts +7 -3
  42. package/dist/workspace/public-api.js +5 -3
  43. package/dist/workspace/static-emit.d.ts +30 -0
  44. package/dist/workspace/static-emit.js +211 -18
  45. package/dist/workspace/user-config.d.ts +112 -0
  46. package/dist/workspace/user-config.js +12 -0
  47. package/host-runtime-files.json +1 -0
  48. package/locales/en-US/cli.json +5 -4
  49. package/package.json +20 -20
  50. package/dist/workspace/pack-client-packages.d.ts +0 -34
  51. package/dist/workspace/pack-client-packages.js +0 -550
@@ -0,0 +1,273 @@
1
+ /**
2
+ * TS consumption layer for the Rust `vmz-pack` plan (frozen v0 contract).
3
+ *
4
+ * The N-API binding exports two synchronous functions:
5
+ * packPlan(requestJson: string): string
6
+ * packWrite(requestJson: string, outDir: string): string
7
+ * Both return the same response JSON shape. The interfaces below are a verbatim
8
+ * mirror of that contract: no renames, no guessed defaults, no dual-format
9
+ * tolerance, and diagnostics always propagate explicitly.
10
+ *
11
+ * This slice is the integration layer: `pack.ts` runs the delivery path
12
+ * through `buildPackRequest` / `runPackWrite` against this contract; real-build
13
+ * evidence closes the switch (see the toolchain plan's delivery-path design).
14
+ */
15
+ import path from 'node:path';
16
+ import { requireNativeAddon } from './native-addon.js';
17
+ /** Error carrying the full diagnostic set — never swallowed, never summarized away. */
18
+ export class PackNativeError extends Error {
19
+ code;
20
+ diagnostics;
21
+ constructor(code, message, diagnostics = []) {
22
+ super(`[${code}] ${message}`);
23
+ this.name = 'PackNativeError';
24
+ this.code = code;
25
+ this.diagnostics = diagnostics;
26
+ }
27
+ }
28
+ function isPlainObject(value) {
29
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
30
+ }
31
+ function requestInvalid(message) {
32
+ return new PackNativeError('pack.native.request-invalid', message);
33
+ }
34
+ function responseShape(message) {
35
+ return new PackNativeError('pack.native.response-shape', message);
36
+ }
37
+ function requireString(value, where) {
38
+ if (typeof value !== 'string')
39
+ throw responseShape(`${where} must be a string`);
40
+ return value;
41
+ }
42
+ function requireStringArray(value, where) {
43
+ if (!Array.isArray(value))
44
+ throw responseShape(`${where} must be an array of strings`);
45
+ return value.map((item, i) => requireString(item, `${where}[${i}]`));
46
+ }
47
+ /** Contract mirror: fields outside the frozen shape are rejected, not ignored. */
48
+ function rejectUnknownKeys(obj, allowed, where) {
49
+ const extra = Object.keys(obj).filter((k) => !allowed.includes(k));
50
+ if (extra.length)
51
+ throw responseShape(`${where} has unknown field(s): ${extra.join(', ')}`);
52
+ }
53
+ function parsePackDiagnostic(value, where) {
54
+ if (!isPlainObject(value))
55
+ throw responseShape(`${where} must be an object`);
56
+ rejectUnknownKeys(value, ['code', 'message', 'path', 'span'], where);
57
+ const out = {
58
+ code: requireString(value.code, `${where}.code`),
59
+ message: requireString(value.message, `${where}.message`),
60
+ };
61
+ if (value.path !== undefined)
62
+ out.path = requireString(value.path, `${where}.path`);
63
+ if (value.span !== undefined) {
64
+ if (!Array.isArray(value.span) ||
65
+ value.span.length !== 2 ||
66
+ !value.span.every((n) => typeof n === 'number' && Number.isFinite(n))) {
67
+ throw responseShape(`${where}.span must be [number, number]`);
68
+ }
69
+ out.span = [value.span[0], value.span[1]];
70
+ }
71
+ return out;
72
+ }
73
+ function parseChunkArtifact(value, where) {
74
+ if (!isPlainObject(value))
75
+ throw responseShape(`${where} must be an object`);
76
+ rejectUnknownKeys(value, ['chunkId', 'fileName', 'code', 'modules', 'imports', 'dynamic', 'sourceMapFileName'], where);
77
+ return {
78
+ chunkId: requireString(value.chunkId, `${where}.chunkId`),
79
+ fileName: requireString(value.fileName, `${where}.fileName`),
80
+ code: requireString(value.code, `${where}.code`),
81
+ modules: requireStringArray(value.modules, `${where}.modules`),
82
+ imports: requireStringArray(value.imports, `${where}.imports`),
83
+ dynamic: requireStringArray(value.dynamic, `${where}.dynamic`),
84
+ sourceMapFileName: requireString(value.sourceMapFileName, `${where}.sourceMapFileName`),
85
+ };
86
+ }
87
+ function parseAssetArtifact(value, where) {
88
+ if (!isPlainObject(value))
89
+ throw responseShape(`${where} must be an object`);
90
+ rejectUnknownKeys(value, ['modulePath', 'specifier', 'fileName', 'url', 'sourcePath'], where);
91
+ return {
92
+ modulePath: requireString(value.modulePath, `${where}.modulePath`),
93
+ specifier: requireString(value.specifier, `${where}.specifier`),
94
+ fileName: requireString(value.fileName, `${where}.fileName`),
95
+ url: requireString(value.url, `${where}.url`),
96
+ sourcePath: requireString(value.sourcePath, `${where}.sourcePath`),
97
+ };
98
+ }
99
+ function parseStyleArtifact(value, where) {
100
+ if (!isPlainObject(value))
101
+ throw responseShape(`${where} must be an object`);
102
+ rejectUnknownKeys(value, ['fileName', 'url', 'modules', 'sourcePaths'], where);
103
+ return {
104
+ fileName: requireString(value.fileName, `${where}.fileName`),
105
+ url: requireString(value.url, `${where}.url`),
106
+ modules: requireStringArray(value.modules, `${where}.modules`),
107
+ sourcePaths: requireStringArray(value.sourcePaths, `${where}.sourcePaths`),
108
+ };
109
+ }
110
+ function parseEntryFile(value, where) {
111
+ if (!isPlainObject(value))
112
+ throw responseShape(`${where} must be an object`);
113
+ rejectUnknownKeys(value, ['logical', 'file'], where);
114
+ return { logical: requireString(value.logical, `${where}.logical`), file: requireString(value.file, `${where}.file`) };
115
+ }
116
+ function parseDynamicFile(value, where) {
117
+ if (!isPlainObject(value))
118
+ throw responseShape(`${where} must be an object`);
119
+ rejectUnknownKeys(value, ['from', 'to'], where);
120
+ return { from: requireString(value.from, `${where}.from`), to: requireString(value.to, `${where}.to`) };
121
+ }
122
+ function parsePackPlan(value) {
123
+ if (!isPlainObject(value))
124
+ throw responseShape('response.plan must be an object');
125
+ rejectUnknownKeys(value, ['artifacts', 'styles', 'assets', 'entryFiles', 'dynamicFiles', 'manifestJson'], 'response.plan');
126
+ if (!Array.isArray(value.artifacts))
127
+ throw responseShape('response.plan.artifacts must be an array');
128
+ if (!Array.isArray(value.styles))
129
+ throw responseShape('response.plan.styles must be an array');
130
+ if (!Array.isArray(value.assets))
131
+ throw responseShape('response.plan.assets must be an array');
132
+ if (!Array.isArray(value.entryFiles))
133
+ throw responseShape('response.plan.entryFiles must be an array');
134
+ if (!Array.isArray(value.dynamicFiles))
135
+ throw responseShape('response.plan.dynamicFiles must be an array');
136
+ return {
137
+ artifacts: value.artifacts.map((a, i) => parseChunkArtifact(a, `response.plan.artifacts[${i}]`)),
138
+ styles: value.styles.map((s, i) => parseStyleArtifact(s, `response.plan.styles[${i}]`)),
139
+ assets: value.assets.map((a, i) => parseAssetArtifact(a, `response.plan.assets[${i}]`)),
140
+ entryFiles: value.entryFiles.map((e, i) => parseEntryFile(e, `response.plan.entryFiles[${i}]`)),
141
+ dynamicFiles: value.dynamicFiles.map((d, i) => parseDynamicFile(d, `response.plan.dynamicFiles[${i}]`)),
142
+ manifestJson: requireString(value.manifestJson, 'response.plan.manifestJson'),
143
+ };
144
+ }
145
+ /**
146
+ * Strictly parse one binding response. `ok:false` never returns — it throws a
147
+ * `PackNativeError` carrying every diagnostic from the response.
148
+ */
149
+ function parsePackResponse(raw) {
150
+ let parsed;
151
+ try {
152
+ parsed = JSON.parse(raw);
153
+ }
154
+ catch (error) {
155
+ const msg = error instanceof Error ? error.message : String(error);
156
+ throw new PackNativeError('pack.native.response-json', `binding returned invalid JSON: ${msg}`);
157
+ }
158
+ if (!isPlainObject(parsed))
159
+ throw responseShape('response must be a JSON object');
160
+ rejectUnknownKeys(parsed, ['ok', 'plan', 'diagnostics'], 'response');
161
+ if (typeof parsed.ok !== 'boolean')
162
+ throw responseShape('response.ok must be a boolean');
163
+ if (!Array.isArray(parsed.diagnostics))
164
+ throw responseShape('response.diagnostics must be an array');
165
+ const diagnostics = parsed.diagnostics.map((d, i) => parsePackDiagnostic(d, `response.diagnostics[${i}]`));
166
+ if (parsed.ok === false) {
167
+ if (parsed.plan !== undefined)
168
+ throw responseShape('response.plan must be absent when ok is false');
169
+ const summary = diagnostics.length
170
+ ? diagnostics.map((d) => `${d.code}: ${d.message}`).join(' | ')
171
+ : 'binding reported failure without diagnostics';
172
+ throw new PackNativeError('pack.native.plan-failed', summary, diagnostics);
173
+ }
174
+ if (parsed.plan === undefined)
175
+ throw responseShape('response.plan is required when ok is true');
176
+ return { ok: true, plan: parsePackPlan(parsed.plan), diagnostics };
177
+ }
178
+ /** Assemble the request JSON. Every gap is an explicit error — nothing is guessed. */
179
+ export function buildPackRequest(input) {
180
+ if (!isPlainObject(input))
181
+ throw requestInvalid('input must be an object');
182
+ const logicals = Object.keys(input.entries ?? {});
183
+ if (!logicals.length)
184
+ throw requestInvalid('entries must contain at least one logical entry');
185
+ const entries = logicals.map((logical) => {
186
+ const entryPath = input.entries[logical];
187
+ if (typeof entryPath !== 'string' || !entryPath) {
188
+ throw requestInvalid(`entries["${logical}"] must be a non-empty path string`);
189
+ }
190
+ if (!path.isAbsolute(entryPath)) {
191
+ throw requestInvalid(`entries["${logical}"] must be an absolute path: ${entryPath}`);
192
+ }
193
+ return { logical, path: entryPath };
194
+ });
195
+ if (input.target !== 'browser' && input.target !== 'node') {
196
+ throw new PackNativeError('pack.native.request-target', `target must be "browser" or "node", got ${JSON.stringify(input.target)}`);
197
+ }
198
+ if (typeof input.root !== 'string' || !input.root)
199
+ throw requestInvalid('root must be a non-empty string');
200
+ if (!path.isAbsolute(input.root))
201
+ throw requestInvalid(`root must be an absolute path: ${input.root}`);
202
+ if (typeof input.publicBase !== 'string' || !input.publicBase) {
203
+ throw requestInvalid('publicBase must be a non-empty string');
204
+ }
205
+ if (!Array.isArray(input.uses))
206
+ throw requestInvalid('uses must be an array');
207
+ const useLogicals = new Set();
208
+ const uses = [];
209
+ for (const use of input.uses) {
210
+ if (!use || typeof use !== 'object' || typeof use.logical !== 'string' || !use.logical) {
211
+ throw requestInvalid('uses[] items must be { logical, execution, exports } objects');
212
+ }
213
+ if (use.execution !== 'full' && use.execution !== 'side-effects') {
214
+ throw new PackNativeError('pack.native.request-uses', `uses["${use.logical}"].execution must be "full" or "side-effects", got ${JSON.stringify(use.execution)}`);
215
+ }
216
+ const exports = use.exports;
217
+ if (!exports || typeof exports !== 'object' || typeof exports.kind !== 'string') {
218
+ throw new PackNativeError('pack.native.request-uses', `uses["${use.logical}"].exports must be a tagged object { kind: "all" | "named" | "unconsumed" }`);
219
+ }
220
+ if (exports.kind === 'named') {
221
+ if (!Array.isArray(exports.names) || !exports.names.every((name) => typeof name === 'string' && name)) {
222
+ throw new PackNativeError('pack.native.request-uses', `uses["${use.logical}"].exports.names must be an array of non-empty export names`);
223
+ }
224
+ }
225
+ else if (exports.kind !== 'all' && exports.kind !== 'unconsumed') {
226
+ throw new PackNativeError('pack.native.request-uses', `uses["${use.logical}"].exports.kind must be "all", "named" or "unconsumed"`);
227
+ }
228
+ if (useLogicals.has(use.logical)) {
229
+ throw new PackNativeError('pack.native.request-uses', `uses duplicates logical "${use.logical}"`);
230
+ }
231
+ useLogicals.add(use.logical);
232
+ uses.push({ logical: use.logical, execution: use.execution, exports: use.exports });
233
+ }
234
+ const missing = logicals.filter((logical) => !useLogicals.has(logical));
235
+ if (missing.length) {
236
+ throw new PackNativeError('pack.native.request-uses', `uses must cover every entries[].logical — missing: ${missing.join(', ')}`);
237
+ }
238
+ let origins;
239
+ if (input.origins !== undefined) {
240
+ if (!isPlainObject(input.origins))
241
+ throw requestInvalid('origins must be a record of absolute paths');
242
+ origins = {};
243
+ for (const [emitted, source] of Object.entries(input.origins)) {
244
+ if (!path.isAbsolute(emitted) || typeof source !== 'string' || !path.isAbsolute(source)) {
245
+ throw requestInvalid(`origins must map absolute emitted paths to absolute source paths: ${JSON.stringify(emitted)}`);
246
+ }
247
+ origins[emitted] = source;
248
+ }
249
+ if (!Object.keys(origins).length)
250
+ origins = undefined;
251
+ }
252
+ const request = { entries, target: input.target, root: input.root, uses, publicBase: input.publicBase, ...(origins ? { origins } : {}) };
253
+ return JSON.stringify(request);
254
+ }
255
+ function resolveBinding(opts, fn) {
256
+ const binding = (opts.binding ?? requireNativeAddon());
257
+ if (typeof binding[fn] !== 'function') {
258
+ throw new PackNativeError('pack.native.binding-missing', `native binding missing ${fn} — run \`pnpm napi:build\` with a vmz-pack build`);
259
+ }
260
+ return binding;
261
+ }
262
+ /** Compute the pack plan via the native binding (synchronous, contract v0). */
263
+ export function runPackPlan(requestJson, opts = {}) {
264
+ const binding = resolveBinding(opts, 'packPlan');
265
+ return parsePackResponse(binding.packPlan(requestJson));
266
+ }
267
+ /** Compute the pack plan and write artifacts under `outDir` via the native binding. */
268
+ export function runPackWrite(requestJson, outDir, opts = {}) {
269
+ if (typeof outDir !== 'string' || !outDir)
270
+ throw requestInvalid('outDir must be a non-empty string');
271
+ const binding = resolveBinding(opts, 'packWrite');
272
+ return parsePackResponse(binding.packWrite(requestJson, outDir));
273
+ }
@@ -1,42 +1,67 @@
1
1
  /**
2
- * Pack stage: consume Deployment IR (VPG-owned units), emit pack manifest,
3
- * and lower browser-unreachable bare package imports to `dist/vendor/**`.
2
+ * Pack stage: run the browser delivery graph through the Rust `vmz-pack`
3
+ * binding (N-API `packPlan`/`packWrite`, frozen v0 contract) and record the
4
+ * resulting chunk/asset mapping in `_vmz/pack-manifest.json`.
4
5
  *
5
- * Current status: a thin module-moving slice — reachable module closure
6
- * materialization, specifier rewriting, and TypeScript `transpileModule` type
7
- * erasure. Linking, dead-code elimination, chunk splitting, and minification
8
- * are NOT implemented in this stage; the manifest reports that honestly.
9
- * (Any compaction of compile-emitted modules happens upstream in the compiler,
10
- * not here — pack never rewrites bytes beyond specifier lowering.)
6
+ * Browser graph roots are the bootstrap modules (`entry-client.js` /
7
+ * `entry-event.js`) emitted by the compiler / static delivery path; page and
8
+ * island modules enter the graph through the bootstrap's literal dynamic
9
+ * import tables, never as pack entries. Bootstrap entries declare
10
+ * `execution: 'full'` + `exports: { kind: 'all' }` (script-tag load,
11
+ * whole-module execution).
12
+ *
13
+ * SSR/Node is a separate graph: every deployment unit's `clientEntry` is a
14
+ * Node entry (logical = `chunkId`), packed under `_vmz/pack-node/` and indexed
15
+ * by `_vmz/pack-node-manifest.json`. Node consumers never fall back to the
16
+ * unpacked root `${chunkId}.client.js`; browser bootstrap modules are not Node
17
+ * entries because they bind `dom.browser` / `document`.
18
+ *
19
+ * No vendor materialization, no specifier lowering, and no second hashing
20
+ * pass happen here: `packWrite` emits the final browser JS set under
21
+ * `_vmz/pack/` with content-hashed names, and consumers resolve logical
22
+ * entries through `packEntryHref()` against this manifest.
11
23
  */
24
+ import type { DeploymentIr } from './bundler-adapter.js';
25
+ import type { PackNativeBinding } from './pack-native.js';
12
26
  export declare const PACK_MANIFEST_SCHEMA = "vmz.pack.manifest.v0";
27
+ /** Directory (relative to outDir) where `packWrite` emits the final browser JS set. */
28
+ export declare const PACK_OUTPUT_DIR_REL = "_vmz/pack";
29
+ /** Site root base — VMZ static delivery has no configurable base (see delivery-profile). */
30
+ export declare const PACK_PUBLIC_BASE = "/";
31
+ /**
32
+ * Projection provenance for the pack graph: each deployment unit's emitted
33
+ * client entry maps back to its source `.vmz`. Bare-specifier package discovery
34
+ * then walks up from the source location — dependency components (e.g. a
35
+ * `@vmz/ui` component importing its own peer) keep their source package's
36
+ * node_modules visibility, matching Node realpath semantics. Relative
37
+ * specifiers keep resolving against the emitted tree.
38
+ */
39
+ export declare function deploymentUnitOrigins(absOut: string, ir: DeploymentIr): Record<string, string>;
13
40
  /**
14
41
  * Ensure dom split companions sit next to vmz-dom.js (barrel imports ./dom-core.js).
15
42
  * Always refresh from `@vmz/core` when present so SSR/runtime fixes are not sticky in outDir.
43
+ * Document surfaces (Node-side document layout mount) consume this; browser delivery
44
+ * runtime files reach the pack graph through `@vmz/core` bare imports in the Rust graph.
16
45
  * @param {string} outDir
17
46
  * @param {string | null | undefined} coreDist `@vmz/core` dist root
18
47
  * @returns {string[]} copied relative names
19
48
  */
20
49
  export declare function ensureRuntimeCompanions(outDir: any, coreDist: any): any[];
21
- /**
22
- * @param {string} outDir
23
- * @param {{
24
- * release?: boolean,
25
- * profileId?: string,
26
- * assembly?: string,
27
- * preferredClientFace?: string,
28
- * coreDist?: string | null,
29
- * projectRoot?: string | null,
30
- * }} [opts]
31
- */
32
50
  interface PackFromDeploymentIrOpts {
33
51
  release?: boolean;
34
52
  profileId?: string;
35
53
  assembly?: string;
36
54
  preferredClientFace?: string;
37
- coreDist?: string | null;
38
55
  projectRoot?: string | null;
56
+ /** Test seam: inject a fake binding. Defaults to the loaded N-API addon. */
57
+ binding?: PackNativeBinding;
39
58
  }
59
+ /**
60
+ * Pack the browser delivery graph via the Rust `vmz-pack` binding and write
61
+ * `_vmz/pack-manifest.json` (v0). Entries are the bootstrap modules that
62
+ * already exist in `outDir` — an empty bootstrap set is an explicit request
63
+ * error, never a silently skipped stage.
64
+ */
40
65
  export declare function packFromDeploymentIr(outDir: string, opts?: PackFromDeploymentIrOpts): {
41
66
  manifest: {
42
67
  schema: string;
@@ -45,22 +70,77 @@ export declare function packFromDeploymentIr(outDir: string, opts?: PackFromDepl
45
70
  release: boolean;
46
71
  preferredClientFace: string;
47
72
  deploymentSchema: unknown;
48
- unitCount: number;
49
- units: unknown[];
73
+ target: "browser";
74
+ publicBase: string;
75
+ entries: Array<{
76
+ logical: string;
77
+ file: string;
78
+ }>;
79
+ entryFiles: unknown[];
80
+ dynamicFiles: unknown[];
81
+ styles: unknown[];
82
+ assets: unknown[];
83
+ chunks: unknown[];
84
+ chunkCount: number;
85
+ styleCount: number;
86
+ entryCount: number;
50
87
  minify: string;
51
- treeShakeBasis: string;
52
- bundler: string;
53
- clientPackageLowering: Record<string, unknown>;
88
+ treeShake: string;
89
+ sourceMaps: string;
90
+ nativeManifest: unknown;
54
91
  packDigest?: string;
55
92
  };
56
93
  path: string;
57
- clientPackages: {
58
- rewrittenFiles: number;
59
- vendoredModules: string[];
60
- bareSpecs: any[];
61
- unresolvedBareSpecs: any[];
62
- skippedVmzExports: any[];
63
- remainingBareSpecs: any[];
94
+ };
95
+ export declare const PACK_NODE_MANIFEST_SCHEMA = "vmz.pack.node-manifest.v0";
96
+ /** Directory (relative to outDir) where `packWrite` emits the Node JS set. */
97
+ export declare const PACK_NODE_OUTPUT_DIR_REL = "_vmz/pack-node";
98
+ /** Node pack manifest (relative to outDir); `entryFiles` maps logical → chunk file. */
99
+ export declare const PACK_NODE_MANIFEST_REL = "_vmz/pack-node-manifest.json";
100
+ interface PackSsrFromDeploymentIrOpts {
101
+ projectRoot?: string | null;
102
+ /** Test seam: inject a fake binding. Defaults to the loaded N-API addon. */
103
+ binding?: PackNativeBinding;
104
+ }
105
+ /**
106
+ * Pack the SSR/Node graph via the Rust `vmz-pack` binding and write
107
+ * `_vmz/pack-node-manifest.json` (v0). Entries are the deployment units'
108
+ * compiled client modules (`clientEntry`, empty → mirrors `vmz-artifacts`
109
+ * `component_entries`: `${chunkId}.client.js`). Node consumers only read
110
+ * `default`, but the import itself is evaluated, hence `side-effects` +
111
+ * named default rather than `all` / `full` / `unconsumed`.
112
+ */
113
+ export declare function packSsrFromDeploymentIr(outDir: string, opts?: PackSsrFromDeploymentIrOpts): {
114
+ manifest: {
115
+ schema: string;
116
+ target: "node";
117
+ deploymentSchema: unknown;
118
+ entries: Array<{
119
+ logical: string;
120
+ file: string;
121
+ }>;
122
+ entryFiles: unknown[];
123
+ dynamicFiles: unknown[];
124
+ chunks: unknown[];
125
+ chunkCount: number;
126
+ entryCount: number;
127
+ nativeManifest: unknown;
128
+ packDigest?: string;
64
129
  };
130
+ path: string;
65
131
  };
132
+ /**
133
+ * Resolve a Node logical entry (`chunkId`) to its packed absolute file from
134
+ * `_vmz/pack-node-manifest.json`. Missing manifest, missing logical, or a
135
+ * missing chunk file is an explicit error — never a fallback to the unpacked
136
+ * root `${chunkId}.client.js`.
137
+ */
138
+ export declare function packNodeEntryFile(outDir: string, chunkId: string): string;
139
+ /**
140
+ * Resolve the final browser URL of a packed logical entry from
141
+ * `_vmz/pack-manifest.json` (`entryFiles` is the only logical→physical map).
142
+ * Missing manifest or missing logical entry is an explicit error — no
143
+ * fallback to unpacked root bytes.
144
+ */
145
+ export declare function packEntryHref(outDir: string, logical: string): string;
66
146
  export {};