@vmz/vmz 0.3.11 → 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 (52) 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/cdn-policy.js +12 -0
  29. package/dist/workspace/content-addressed-assets.d.ts +6 -17
  30. package/dist/workspace/content-addressed-assets.js +10 -95
  31. package/dist/workspace/delivery-runtime-imports.js +3 -0
  32. package/dist/workspace/native-addon.d.ts +4 -0
  33. package/dist/workspace/pack-native.d.ts +139 -0
  34. package/dist/workspace/pack-native.js +273 -0
  35. package/dist/workspace/pack.d.ts +113 -27
  36. package/dist/workspace/pack.js +271 -54
  37. package/dist/workspace/plugin-host.d.ts +4 -4
  38. package/dist/workspace/plugin-host.js +9 -12
  39. package/dist/workspace/production-observability.d.ts +2 -0
  40. package/dist/workspace/production-observability.js +6 -2
  41. package/dist/workspace/project-build.js +26 -4
  42. package/dist/workspace/public-api.d.ts +7 -3
  43. package/dist/workspace/public-api.js +5 -3
  44. package/dist/workspace/static-emit.d.ts +30 -0
  45. package/dist/workspace/static-emit.js +211 -18
  46. package/dist/workspace/user-config.d.ts +112 -0
  47. package/dist/workspace/user-config.js +12 -0
  48. package/host-runtime-files.json +1 -0
  49. package/locales/en-US/cli.json +5 -4
  50. package/package.json +20 -20
  51. package/dist/workspace/pack-client-packages.d.ts +0 -32
  52. package/dist/workspace/pack-client-packages.js +0 -437
@@ -1,437 +0,0 @@
1
- /**
2
- * Browser-safe client package lowering (Pack stage thin slice).
3
- *
4
- * Bare npm/workspace imports are legal on the author surface (01/04).
5
- * Browser ESM cannot resolve them. Pack materializes reachable package
6
- * modules under `dist/vendor/<pkg>/…` and rewrites importers to relative paths
7
- * via a bounded rewrite of generated module syntax. Pack must not re-enter the
8
- * parser pipeline for every emitted JavaScript file.
9
- *
10
- * Not full oxc chunk-split/minify (`oxc-pending` remains for release minify).
11
- */
12
- import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from 'node:fs';
13
- import path from 'node:path';
14
- import { createRequire } from 'node:module';
15
- import { resolvePackageRoot } from './packages.js';
16
- import { requireNativeAddon } from './native-addon.js';
17
- const VENDOR_DIR = 'vendor';
18
- const SKIP_PREFIXES = ['node:', 'nodejs:', 'cloudflare:', 'data:', 'http:', 'https:', 'vmz:', '#'];
19
- export function packClientBareImports(outDir, opts = {}) {
20
- const projectRoot = opts.projectRoot ? path.resolve(opts.projectRoot) : path.dirname(path.resolve(outDir));
21
- /** @type {Map<string, string>} bareSpec → absolute vendored .js path */
22
- const bareToVendor = new Map();
23
- /** @type {Set<string>} absolute source files already materialized */
24
- const materializedSources = new Set();
25
- /** @type {string[]} */
26
- const bareQueue = [];
27
- /** @type {string[]} */
28
- const unresolved = [];
29
- /** @type {string[]} */
30
- const skippedVmz = [];
31
- for (const file of listClientJs(outDir)) {
32
- for (const spec of collectBareSpecs(readFileSync(file, 'utf8'))) {
33
- bareQueue.push({ spec: String(spec), from: file });
34
- }
35
- }
36
- while (bareQueue.length) {
37
- const item = bareQueue.shift();
38
- const { spec } = item;
39
- if (bareToVendor.has(spec))
40
- continue;
41
- const resolved = resolveBareToSource(projectRoot, spec, item.from);
42
- if (!resolved) {
43
- if (!unresolved.includes(spec))
44
- unresolved.push(spec);
45
- continue;
46
- }
47
- if (/\.vmz$/i.test(resolved.sourceFile)) {
48
- if (!skippedVmz.includes(spec))
49
- skippedVmz.push(spec);
50
- continue;
51
- }
52
- const destAbs = materializeSourceTree(outDir, resolved, materializedSources, bareQueue);
53
- if (destAbs)
54
- bareToVendor.set(spec, destAbs);
55
- else if (!unresolved.includes(spec))
56
- unresolved.push(spec);
57
- }
58
- /** @type {string[]} */
59
- const rewritten = [];
60
- for (const file of [...listClientJs(outDir), ...listVendorJs(outDir)]) {
61
- const before = readFileSync(file, 'utf8');
62
- let after = rewriteBareImports(before, file, bareToVendor);
63
- try {
64
- after = rewritePackModuleSpecifiers(after);
65
- }
66
- catch (error) {
67
- throw new Error(`pack module ${file}: ${error instanceof Error ? error.message : String(error)}`);
68
- }
69
- if (after !== before) {
70
- writeFileSync(file, after, 'utf8');
71
- rewritten.push(path.relative(outDir, file).replace(/\\/g, '/'));
72
- }
73
- }
74
- // Any bare that remains in client (non-vendor) JS after rewrite is still browser-broken.
75
- /** @type {string[]} */
76
- const remaining = [];
77
- for (const file of listClientJs(outDir)) {
78
- for (const spec of collectBareSpecs(readFileSync(file, 'utf8'))) {
79
- if (!remaining.includes(spec))
80
- remaining.push(spec);
81
- }
82
- }
83
- return {
84
- rewrittenFiles: rewritten.length,
85
- vendoredModules: [...bareToVendor.values()].map((abs) => path.relative(outDir, abs).replace(/\\/g, '/')),
86
- bareSpecs: [...bareToVendor.keys()],
87
- unresolvedBareSpecs: unresolved,
88
- skippedVmzExports: skippedVmz,
89
- remainingBareSpecs: remaining,
90
- };
91
- }
92
- /**
93
- * Materialize `resolved.sourceFile` and its relative import closure under vendor/.
94
- * @returns {string | null} vendor path for the entry source
95
- */
96
- function materializeSourceTree(outDir, resolved, materializedSources, bareQueue) {
97
- /** @type {string[]} */
98
- const sourceQueue = [resolved.sourceFile];
99
- // Subpath bare specs often land on a file already vendored via a relative
100
- // import from the package root — still map the bare name to that vendor path.
101
- /** @type {string | null} */
102
- let entryDest = vendorPathForSource(outDir, resolved.pkgName, resolved.pkgRoot, resolved.sourceFile);
103
- while (sourceQueue.length) {
104
- const sourceFile = sourceQueue.shift();
105
- if (materializedSources.has(sourceFile))
106
- continue;
107
- materializedSources.add(sourceFile);
108
- const destAbs = vendorPathForSource(outDir, resolved.pkgName, resolved.pkgRoot, sourceFile);
109
- mkdirSync(path.dirname(destAbs), { recursive: true });
110
- const js = materializeModule(sourceFile);
111
- writeFileSync(destAbs, js, 'utf8');
112
- if (sourceFile === resolved.sourceFile)
113
- entryDest = destAbs;
114
- for (const bare of collectBareSpecs(js))
115
- bareQueue.push({ spec: String(bare), from: sourceFile });
116
- for (const rel of collectRelativeSpecs(js)) {
117
- const target = resolveRelativeSource(path.dirname(sourceFile), rel);
118
- if (target && !materializedSources.has(target))
119
- sourceQueue.push(target);
120
- }
121
- // Also follow relative imports as written in the *source* (before transpile),
122
- // so `./catalog.ts` is discovered even if transpile already rewrote to `.js`.
123
- const raw = readFileSync(sourceFile, 'utf8');
124
- for (const rel of collectRelativeSpecs(raw)) {
125
- const target = resolveRelativeSource(path.dirname(sourceFile), rel);
126
- if (target && !materializedSources.has(target))
127
- sourceQueue.push(target);
128
- }
129
- }
130
- return entryDest;
131
- }
132
- function listClientJs(outDir) {
133
- /** @type {string[]} */
134
- const out = [];
135
- walk(outDir, (file) => {
136
- const rel = path.relative(outDir, file).replace(/\\/g, '/');
137
- if (rel.startsWith('_vmz/') || rel.startsWith(`${VENDOR_DIR}/`) || rel.startsWith('#server/') || rel.startsWith('_vmz_server/')) {
138
- return;
139
- }
140
- if (rel.endsWith('.js') || rel.endsWith('.mjs'))
141
- out.push(file);
142
- });
143
- return out;
144
- }
145
- function listVendorJs(outDir) {
146
- const root = path.join(outDir, VENDOR_DIR);
147
- if (!existsSync(root))
148
- return [];
149
- /** @type {string[]} */
150
- const out = [];
151
- walk(root, (file) => {
152
- if (file.endsWith('.js') || file.endsWith('.mjs'))
153
- out.push(file);
154
- });
155
- return out;
156
- }
157
- function walk(dir, visit) {
158
- if (!existsSync(dir))
159
- return;
160
- for (const name of readdirSync(dir)) {
161
- if (name === 'node_modules')
162
- continue;
163
- const full = path.join(dir, name);
164
- let st;
165
- try {
166
- st = statSync(full);
167
- }
168
- catch {
169
- continue;
170
- }
171
- if (st.isDirectory())
172
- walk(full, visit);
173
- else
174
- visit(full);
175
- }
176
- }
177
- /** @param {string} js */
178
- export function collectBareSpecs(js) {
179
- /** @type {Set<string>} */
180
- const specs = new Set();
181
- const add = (spec) => {
182
- if (!spec || isRelativeOrAbsolute(spec) || shouldSkipBare(spec))
183
- return;
184
- specs.add(spec);
185
- };
186
- // `from 'x'` covers import/export … from
187
- let m;
188
- const fromRe = /\bfrom\s*['"]([^'"]+)['"]/g;
189
- while ((m = fromRe.exec(js)))
190
- add(m[1]);
191
- const dynRe = /\bimport\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
192
- while ((m = dynRe.exec(js)))
193
- add(m[1]);
194
- // side-effect: import 'x' (not import( and not import … from)
195
- const sideRe = /\bimport\s*['"]([^'"]+)['"]/g;
196
- while ((m = sideRe.exec(js)))
197
- add(m[1]);
198
- return [...specs];
199
- }
200
- function collectRelativeSpecs(js) {
201
- /** @type {Set<string>} */
202
- const specs = new Set();
203
- const re = /(?:\bfrom\s*|\bimport\s*\(\s*|\bimport\s*)['"](\.[^'"]+)['"]/g;
204
- let m;
205
- while ((m = re.exec(js)))
206
- specs.add(m[1]);
207
- return [...specs];
208
- }
209
- function isRelativeOrAbsolute(spec) {
210
- return spec.startsWith('.') || spec.startsWith('/') || spec.startsWith('\\');
211
- }
212
- function shouldSkipBare(spec) {
213
- return SKIP_PREFIXES.some((p) => spec.startsWith(p));
214
- }
215
- function resolveBareToSource(projectRoot, spec, fromFile) {
216
- const { pkgName, subpath } = splitPackageSpec(spec);
217
- let pkgRoot = null;
218
- if (fromFile && existsSync(fromFile)) {
219
- let cur = path.dirname(realpathSync(fromFile));
220
- for (let i = 0; i < 12; i++) {
221
- const nested = path.join(cur, 'node_modules', ...pkgName.split('/'));
222
- if (existsSync(path.join(nested, 'package.json'))) {
223
- pkgRoot = nested;
224
- break;
225
- }
226
- const parent = path.dirname(cur);
227
- if (parent === cur)
228
- break;
229
- cur = parent;
230
- }
231
- }
232
- if (!pkgRoot)
233
- pkgRoot = resolvePackageRoot(projectRoot, pkgName);
234
- if (!pkgRoot) {
235
- let cur = projectRoot;
236
- for (let i = 0; i < 8; i++) {
237
- pkgRoot = resolvePackageRoot(cur, pkgName);
238
- if (pkgRoot)
239
- break;
240
- const parent = path.dirname(cur);
241
- if (parent === cur)
242
- break;
243
- cur = parent;
244
- }
245
- }
246
- if (!pkgRoot)
247
- return null;
248
- const sourceFile = resolveExportFile(pkgRoot, subpath);
249
- if (!sourceFile)
250
- return null;
251
- return { pkgName, pkgRoot, subpath, sourceFile };
252
- }
253
- function splitPackageSpec(spec) {
254
- if (spec.startsWith('@')) {
255
- const parts = spec.split('/');
256
- if (parts.length < 2)
257
- return { pkgName: spec, subpath: '' };
258
- return { pkgName: `${parts[0]}/${parts[1]}`, subpath: parts.slice(2).join('/') };
259
- }
260
- const i = spec.indexOf('/');
261
- if (i < 0)
262
- return { pkgName: spec, subpath: '' };
263
- return { pkgName: spec.slice(0, i), subpath: spec.slice(i + 1) };
264
- }
265
- function resolveExportFile(pkgRoot, subpath) {
266
- const pkgPath = path.join(pkgRoot, 'package.json');
267
- if (!existsSync(pkgPath))
268
- return null;
269
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
270
- const key = subpath ? `./${subpath}` : '.';
271
- let target = null;
272
- if (pkg.exports && typeof pkg.exports === 'object' && !Array.isArray(pkg.exports)) {
273
- const entry = pkg.exports[key] ?? (!subpath ? pkg.exports['.'] : null);
274
- target = flattenExportTarget(entry);
275
- }
276
- if (!target && !subpath)
277
- target = pkg.module || pkg.main || './index.js';
278
- if (!target && subpath) {
279
- for (const cand of [
280
- path.join(pkgRoot, 'src', `${subpath}.ts`),
281
- path.join(pkgRoot, 'src', `${subpath}.js`),
282
- path.join(pkgRoot, `${subpath}.ts`),
283
- path.join(pkgRoot, `${subpath}.js`),
284
- path.join(pkgRoot, 'src', subpath, 'index.ts'),
285
- path.join(pkgRoot, 'src', subpath, 'index.js'),
286
- ]) {
287
- if (existsSync(cand) && statSync(cand).isFile())
288
- return cand;
289
- }
290
- return null;
291
- }
292
- if (!target || typeof target !== 'string')
293
- return null;
294
- const abs = path.resolve(pkgRoot, target);
295
- if (existsSync(abs) && statSync(abs).isFile())
296
- return abs;
297
- for (const ext of ['.ts', '.tsx', '.js', '.mjs']) {
298
- const c = abs.endsWith(ext) ? abs : abs + ext;
299
- if (existsSync(c) && statSync(c).isFile())
300
- return c;
301
- }
302
- return null;
303
- }
304
- function flattenExportTarget(entry) {
305
- if (typeof entry === 'string')
306
- return entry;
307
- if (!entry || typeof entry !== 'object')
308
- return null;
309
- // Package authors commonly put browser-first TypeScript sources behind a
310
- // conditional export. Resolve conditions before falling back to Node's
311
- // import/default branches so the pack stage can transpile the source into
312
- // the browser-safe vendor tree before static SSR imports it.
313
- const v = entry.browser || entry.import || entry.default || entry.require || entry.module || entry.node || null;
314
- if (typeof v === 'string')
315
- return v;
316
- if (v && typeof v === 'object')
317
- return flattenExportTarget(v);
318
- return null;
319
- }
320
- function vendorPathForSource(outDir, pkgName, pkgRoot, sourceFile) {
321
- const rel = path.relative(pkgRoot, sourceFile).replace(/\\/g, '/');
322
- return path.join(outDir, VENDOR_DIR, packageDirName(pkgName), rewriteTsExt(rel));
323
- }
324
- function packageDirName(pkgName) {
325
- return pkgName.replace(/^@/, '');
326
- }
327
- function materializeModule(sourceFile) {
328
- const ext = path.extname(sourceFile).toLowerCase();
329
- const raw = readFileSync(sourceFile, 'utf8');
330
- if (ext === '.json')
331
- return raw;
332
- if (ext === '.ts' || ext === '.tsx')
333
- return transpileTs(raw, sourceFile);
334
- try {
335
- return rewritePackModuleSpecifiers(raw);
336
- }
337
- catch (error) {
338
- throw new Error(`pack source ${sourceFile}: ${error instanceof Error ? error.message : String(error)}`);
339
- }
340
- }
341
- function transpileTs(source, filename) {
342
- try {
343
- const require = createRequire(import.meta.url);
344
- const ts = require('typescript');
345
- const out = ts.transpileModule(source, {
346
- fileName: filename,
347
- compilerOptions: {
348
- module: ts.ModuleKind.ESNext,
349
- target: ts.ScriptTarget.ES2022,
350
- moduleResolution: ts.ModuleResolutionKind.Bundler,
351
- esModuleInterop: true,
352
- skipLibCheck: true,
353
- },
354
- });
355
- return rewritePackModuleSpecifiers(out.outputText || '');
356
- }
357
- catch (err) {
358
- const msg = err instanceof Error ? err.message : String(err);
359
- return `/* vmz-pack: typescript transpile failed (${msg}) */\n${rewritePackModuleSpecifiers(source)}`;
360
- }
361
- }
362
- function rewriteTsExt(p) {
363
- // Path basename only (output layout) — not ESM source rewrite.
364
- return String(p)
365
- .replace(/\.tsx$/i, '.js')
366
- .replace(/\.ts$/i, '.js');
367
- }
368
- /** oxc AST module specifier rewrite (`.ts`→`.js` + optional exact map). */
369
- export function rewriteRelativeTsSpecs(js, exactMap = null) {
370
- const source = String(js ?? '');
371
- const hasModuleTsSpecifier = /(?:import\s*(?:[^'"()]*?\s*from\s*)?|export\s+[^'"()]*?\s*from\s*|import\s*\()(['"])[^'"\r\n]+\.tsx?\1/i.test(source);
372
- const exactKeys = Object.keys(exactMap ?? {});
373
- const hasExactSpecifier = exactKeys.some((spec) => source.includes(`'${spec}'`) || source.includes(`"${spec}"`));
374
- if (!hasModuleTsSpecifier && !hasExactSpecifier) {
375
- return source;
376
- }
377
- const native = requireNativeAddon();
378
- if (typeof native.rewriteModuleSpecifiers !== 'function') {
379
- throw new Error('native missing rewriteModuleSpecifiers — run `pnpm napi:build`');
380
- }
381
- const rules = {
382
- tsExtToJs: true,
383
- exact: exactMap && typeof exactMap === 'object' ? exactMap : {},
384
- };
385
- return native.rewriteModuleSpecifiers(String(js ?? ''), JSON.stringify(rules));
386
- }
387
- function resolveRelativeSource(fromDir, rel) {
388
- const cleaned = rel.replace(/\?.*$/, '').replace(/#.*$/, '');
389
- const base = path.resolve(fromDir, cleaned);
390
- for (const cand of [
391
- base,
392
- `${base}.ts`,
393
- `${base}.tsx`,
394
- `${base}.js`,
395
- `${base}.mjs`,
396
- path.join(base, 'index.ts'),
397
- path.join(base, 'index.js'),
398
- ]) {
399
- try {
400
- if (existsSync(cand) && statSync(cand).isFile())
401
- return cand;
402
- }
403
- catch {
404
- /* ignore */
405
- }
406
- }
407
- return null;
408
- }
409
- function rewriteBareImports(js, fromFile, bareToVendor) {
410
- /** @type {Record<string, string>} */
411
- const exact = {};
412
- for (const [spec, dest] of bareToVendor.entries()) {
413
- if (isRelativeOrAbsolute(spec) || shouldSkipBare(spec))
414
- continue;
415
- let rel = path.relative(path.dirname(fromFile), dest).replace(/\\/g, '/');
416
- if (!rel.startsWith('.'))
417
- rel = `./${rel}`;
418
- exact[spec] = rel;
419
- }
420
- return rewritePackModuleSpecifiers(js, exact);
421
- }
422
- function rewritePackModuleSpecifiers(source, exactMap = null) {
423
- const rewrite = (spec) => {
424
- const exact = exactMap && exactMap[spec];
425
- if (typeof exact === 'string')
426
- return exact;
427
- return /\.tsx?$/i.test(spec) ? spec.replace(/\.tsx?$/i, '.js') : spec;
428
- };
429
- const replace = (match, quote, spec) => {
430
- const next = rewrite(spec);
431
- return next === spec ? match : match.replace(`${quote}${spec}${quote}`, `${quote}${next}${quote}`);
432
- };
433
- let out = source.replace(/\bimport\s*\(\s*(['"])([^'"]+)\1\s*\)/g, replace);
434
- out = out.replace(/\bimport\s+[^;\n]*?\sfrom\s+(['"])([^'"]+)\1/g, replace);
435
- out = out.replace(/\bimport\s*(['"])([^'"]+)\1/g, replace);
436
- return out.replace(/\bfrom\s*(['"])([^'"]+)\1/g, replace);
437
- }