@vmz/vmz 0.1.12 → 0.1.14
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/build-assemble.js +14 -4
- package/dist/cli.js +57 -24
- package/dist/content-addressed-assets.d.ts +15 -0
- package/dist/content-addressed-assets.js +71 -2
- package/dist/delivery-profile.d.ts +19 -1
- package/dist/delivery-profile.js +70 -5
- package/dist/dev-session.js +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +5 -2
- package/dist/public-static-assets.d.ts +24 -0
- package/dist/public-static-assets.js +140 -0
- package/dist/site-favicon.d.ts +31 -0
- package/dist/site-favicon.js +140 -0
- package/dist/static-emit.d.ts +21 -0
- package/dist/static-emit.js +16 -0
- package/package.json +12 -12
package/dist/build-assemble.js
CHANGED
|
@@ -8,6 +8,8 @@ import { semanticIdsForAssembly, sha256Hex, canonicalJson } from './delivery-pro
|
|
|
8
8
|
import { emitServerArtifact } from './server-artifact.js';
|
|
9
9
|
import { emitEmbeddedPackaging } from './embedded-packaging.js';
|
|
10
10
|
import { emitSiteDelivery } from './site-delivery.js';
|
|
11
|
+
import { emitSiteFavicon } from './site-favicon.js';
|
|
12
|
+
import { emitPublicStaticAssets } from './public-static-assets.js';
|
|
11
13
|
import { emitWebStatic } from './static-emit.js';
|
|
12
14
|
import { writePrettyJsonFile } from './pretty-json.js';
|
|
13
15
|
export const BUILD_PROOF_SCHEMA = 'vmz.build.proof.v0';
|
|
@@ -26,10 +28,13 @@ export async function assembleDelivery(outDir, ctx) {
|
|
|
26
28
|
serverRuntime: selection.serverRuntime || null,
|
|
27
29
|
steps: [],
|
|
28
30
|
};
|
|
29
|
-
if (assembly === 'static
|
|
30
|
-
const staticResult = await emitWebStatic(outDir, {
|
|
31
|
+
if (assembly === 'web-static' || assembly === 'cdn+server') {
|
|
32
|
+
const staticResult = await emitWebStatic(outDir, {
|
|
33
|
+
origin: ctx.origin,
|
|
34
|
+
projectRoot: ctx.projectRoot,
|
|
35
|
+
});
|
|
31
36
|
result.steps.push({
|
|
32
|
-
kind: 'static
|
|
37
|
+
kind: 'web-static',
|
|
33
38
|
digest: staticResult.digest,
|
|
34
39
|
htmlFiles: staticResult.htmlFiles?.length ?? 0,
|
|
35
40
|
skipped: staticResult.skipped?.length ?? 0,
|
|
@@ -40,6 +45,11 @@ export async function assembleDelivery(outDir, ctx) {
|
|
|
40
45
|
skipped: staticResult.skipped,
|
|
41
46
|
};
|
|
42
47
|
}
|
|
48
|
+
else if (assembly === 'server-host' || assembly === 'local-static') {
|
|
49
|
+
// SSR / local packs: favicon + opaque public/ for serve-host.
|
|
50
|
+
emitSiteFavicon(outDir, { projectRoot: ctx.projectRoot });
|
|
51
|
+
emitPublicStaticAssets(outDir, { projectRoot: ctx.projectRoot });
|
|
52
|
+
}
|
|
43
53
|
if (assembly === 'local-static') {
|
|
44
54
|
result.steps.push({
|
|
45
55
|
kind: 'local-static',
|
|
@@ -124,7 +134,7 @@ export function emitBuildProof(outDir, ctx) {
|
|
|
124
134
|
};
|
|
125
135
|
for (const id of semanticIds) {
|
|
126
136
|
if (id === 'static-delivery') {
|
|
127
|
-
const step = (ctx.assemble?.steps || []).find((s) => s.kind === 'static
|
|
137
|
+
const step = (ctx.assemble?.steps || []).find((s) => s.kind === 'web-static');
|
|
128
138
|
slots[id] = step
|
|
129
139
|
? { status: 'emitted', detail: `digest=${String(step.digest).slice(0, 12)}` }
|
|
130
140
|
: { status: 'pending', detail: 'assembly requires static emit' };
|
package/dist/cli.js
CHANGED
|
@@ -23,7 +23,7 @@ import { cmdRefactor } from './refactor-cmd.js';
|
|
|
23
23
|
import { cmdExplain } from './explain-cmd.js';
|
|
24
24
|
import { resolveNativeVmzCli } from './resolve-native-cli.js';
|
|
25
25
|
import { loadVmzConfig } from './plugin-host.js';
|
|
26
|
-
import { normalizeDeliveryAuthoring, selectBuildProfile } from './delivery-profile.js';
|
|
26
|
+
import { normalizeDeliveryAuthoring, resolveProfileArtifactDir, selectBuildProfile } from './delivery-profile.js';
|
|
27
27
|
import { packFromDeploymentIr } from './pack.js';
|
|
28
28
|
import { assembleDelivery, emitBuildProof } from './build-assemble.js';
|
|
29
29
|
/**
|
|
@@ -121,11 +121,11 @@ Usage:
|
|
|
121
121
|
vmz help Show this help
|
|
122
122
|
|
|
123
123
|
Options:
|
|
124
|
-
--out-dir, -o <dir>
|
|
124
|
+
--out-dir, -o <dir> Workspace output root (default: dist). Profile artifacts land in <out-dir>/<name> (name defaults to profile id; CDN: name:'cdn' → dist/cdn)
|
|
125
125
|
--release Release build (omit serve-host; pack minify slot; proof)
|
|
126
126
|
--profile <name> Delivery profile (default from config; builtins: web-ssr|static|web-client|web-hybrid)
|
|
127
127
|
--target <id> browser (default) | mini-program-wechat (pack dist/wechat for WeChat DevTools; build+dev)
|
|
128
|
-
--origin <url> Site origin for static
|
|
128
|
+
--origin <url> Site origin for web-static canonical/sitemap
|
|
129
129
|
--host <host> Listen host (default: 127.0.0.1)
|
|
130
130
|
--port <port> Listen port (dev: omit = auto from 5173; set = lock)
|
|
131
131
|
--poll-ms <ms> Dev watch poll interval (default: 300)
|
|
@@ -339,28 +339,29 @@ async function cmdBuild(args) {
|
|
|
339
339
|
return 1;
|
|
340
340
|
}
|
|
341
341
|
const wechatPack = targetRaw === 'mini-program-wechat';
|
|
342
|
-
const { project, outDir } = resolveWorkspaceDirs({
|
|
342
|
+
const { project, outDir: outDirRoot } = resolveWorkspaceDirs({
|
|
343
343
|
path: pathArg,
|
|
344
344
|
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
345
345
|
});
|
|
346
|
-
|
|
346
|
+
const cfg = await loadVmzConfig(project);
|
|
347
|
+
const cliProfile = typeof args.profile === 'string' ? args.profile : '';
|
|
348
|
+
const norm = normalizeDeliveryAuthoring(cfg.delivery ?? null);
|
|
349
|
+
if (!norm.ok) {
|
|
350
|
+
log.diagnostics(norm.diagnostics ?? []);
|
|
351
|
+
log.error('delivery authoring invalid');
|
|
352
|
+
return 1;
|
|
353
|
+
}
|
|
354
|
+
const selected = selectBuildProfile(norm.table, cliProfile);
|
|
355
|
+
if (!selected.ok) {
|
|
356
|
+
log.diagnostics(selected.diagnostics ?? []);
|
|
357
|
+
log.error(`unknown build --profile ${cliProfile || norm.table.default}`);
|
|
358
|
+
return 1;
|
|
359
|
+
}
|
|
360
|
+
const outDir = resolveProfileArtifactDir(outDirRoot, selected.profile);
|
|
361
|
+
log.info(`build ${project} → ${outDir}${wechatPack ? ' (target=mini-program-wechat)' : ''} (out-dir=${outDirRoot}, name=${selected.profile.name})`);
|
|
347
362
|
const ws = createWorkspace({ root: project, outDir });
|
|
348
363
|
try {
|
|
349
|
-
|
|
350
|
-
const cliProfile = typeof args.profile === 'string' ? args.profile : '';
|
|
351
|
-
const norm = normalizeDeliveryAuthoring(cfg.delivery ?? null);
|
|
352
|
-
if (!norm.ok) {
|
|
353
|
-
log.diagnostics(norm.diagnostics ?? []);
|
|
354
|
-
log.error('delivery authoring invalid');
|
|
355
|
-
return 1;
|
|
356
|
-
}
|
|
357
|
-
const selected = selectBuildProfile(norm.table, cliProfile);
|
|
358
|
-
if (!selected.ok) {
|
|
359
|
-
log.diagnostics(selected.diagnostics ?? []);
|
|
360
|
-
log.error(`unknown build --profile ${cliProfile || norm.table.default}`);
|
|
361
|
-
return 1;
|
|
362
|
-
}
|
|
363
|
-
log.info(`delivery profile ${selected.selection.profileId} (assembly=${selected.selection.assembly})`);
|
|
364
|
+
log.info(`delivery profile ${selected.selection.profileId} (assembly=${selected.selection.assembly}, name=${selected.profile.name})`);
|
|
364
365
|
const code = await runWithPlugins(ws, project, outDir, () => {
|
|
365
366
|
const report = ws.build(Boolean(args.release));
|
|
366
367
|
const errors = log.diagnostics(report.diagnostics ?? []);
|
|
@@ -449,7 +450,7 @@ async function cmdBuild(args) {
|
|
|
449
450
|
const origin = typeof args.origin === 'string' ? args.origin : undefined;
|
|
450
451
|
let assemble = null;
|
|
451
452
|
try {
|
|
452
|
-
if (selected.selection.assembly === 'static
|
|
453
|
+
if (selected.selection.assembly === 'web-static') {
|
|
453
454
|
log.info(`static emit ${outDir}`);
|
|
454
455
|
}
|
|
455
456
|
assemble = await assembleDelivery(outDir, {
|
|
@@ -461,9 +462,10 @@ async function cmdBuild(args) {
|
|
|
461
462
|
siteId: cfg.application?.id || undefined,
|
|
462
463
|
origin,
|
|
463
464
|
pack: pack.manifest,
|
|
465
|
+
projectRoot: project,
|
|
464
466
|
});
|
|
465
467
|
for (const step of assemble.manifest.steps || []) {
|
|
466
|
-
if (step.kind === 'static
|
|
468
|
+
if (step.kind === 'web-static') {
|
|
467
469
|
log.info(`static ok (${step.htmlFiles} html, ${step.skipped} skipped, digest=${String(step.digest).slice(0, 12)}…)`);
|
|
468
470
|
}
|
|
469
471
|
else if (step.kind === 'site-delivery' && step.digest) {
|
|
@@ -495,10 +497,25 @@ async function cmdServe(args) {
|
|
|
495
497
|
if (code !== 0)
|
|
496
498
|
return code;
|
|
497
499
|
}
|
|
498
|
-
const { project, outDir } = resolveWorkspaceDirs({
|
|
500
|
+
const { project, outDir: outDirRoot } = resolveWorkspaceDirs({
|
|
499
501
|
path: pathArg,
|
|
500
502
|
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
501
503
|
});
|
|
504
|
+
const cfg = await loadVmzConfig(project);
|
|
505
|
+
const cliProfile = typeof args.profile === 'string' ? args.profile : '';
|
|
506
|
+
const norm = normalizeDeliveryAuthoring(cfg.delivery ?? null);
|
|
507
|
+
if (!norm.ok) {
|
|
508
|
+
log.diagnostics(norm.diagnostics ?? []);
|
|
509
|
+
log.error('delivery authoring invalid');
|
|
510
|
+
return 1;
|
|
511
|
+
}
|
|
512
|
+
const selected = selectBuildProfile(norm.table, cliProfile);
|
|
513
|
+
if (!selected.ok) {
|
|
514
|
+
log.diagnostics(selected.diagnostics ?? []);
|
|
515
|
+
log.error(`unknown build --profile ${cliProfile || norm.table.default}`);
|
|
516
|
+
return 1;
|
|
517
|
+
}
|
|
518
|
+
const outDir = resolveProfileArtifactDir(outDirRoot, selected.profile);
|
|
502
519
|
const hostJs = path.join(outDir, 'vmz-serve-host.mjs');
|
|
503
520
|
if (!existsSync(hostJs)) {
|
|
504
521
|
try {
|
|
@@ -521,6 +538,7 @@ async function cmdServe(args) {
|
|
|
521
538
|
VMZ_DIST: outDir,
|
|
522
539
|
VMZ_PORT: String(port),
|
|
523
540
|
VMZ_HOST: host,
|
|
541
|
+
VMZ_PROJECT_ROOT: project,
|
|
524
542
|
VMZ_NATIVE_NODE: resolveNativePath(),
|
|
525
543
|
},
|
|
526
544
|
stdio: 'inherit',
|
|
@@ -546,10 +564,25 @@ async function cmdServe(args) {
|
|
|
546
564
|
*/
|
|
547
565
|
async function cmdDev(args) {
|
|
548
566
|
const pathArg = args._[0] ?? '.';
|
|
549
|
-
const { project, outDir } = resolveWorkspaceDirs({
|
|
567
|
+
const { project, outDir: outDirRoot } = resolveWorkspaceDirs({
|
|
550
568
|
path: pathArg,
|
|
551
569
|
outDir: typeof args['out-dir'] === 'string' ? args['out-dir'] : undefined,
|
|
552
570
|
});
|
|
571
|
+
const cfg = await loadVmzConfig(project);
|
|
572
|
+
const cliProfile = typeof args.profile === 'string' ? args.profile : '';
|
|
573
|
+
const norm = normalizeDeliveryAuthoring(cfg.delivery ?? null);
|
|
574
|
+
if (!norm.ok) {
|
|
575
|
+
log.diagnostics(norm.diagnostics ?? []);
|
|
576
|
+
log.error('delivery authoring invalid');
|
|
577
|
+
return 1;
|
|
578
|
+
}
|
|
579
|
+
const selected = selectBuildProfile(norm.table, cliProfile);
|
|
580
|
+
if (!selected.ok) {
|
|
581
|
+
log.diagnostics(selected.diagnostics ?? []);
|
|
582
|
+
log.error(`unknown build --profile ${cliProfile || norm.table.default}`);
|
|
583
|
+
return 1;
|
|
584
|
+
}
|
|
585
|
+
const outDir = resolveProfileArtifactDir(outDirRoot, selected.profile);
|
|
553
586
|
const host = typeof args.host === 'string' ? args.host : '127.0.0.1';
|
|
554
587
|
const portLocked = Object.prototype.hasOwnProperty.call(args, 'port');
|
|
555
588
|
let port;
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* A3: content-addressed assets/<hash> layout for immutable CDN objects.
|
|
3
3
|
* Logical paths stay available for serve/dev; static HTML rewrites to hashed URLs.
|
|
4
4
|
* CSS aggregators (vmz.css) rewrite `@import` to hashed sibling paths under assets/.
|
|
5
|
+
* JS under assets/ always rewrites ESM `./` → `../` so barrels (vmz-dom → dom-core)
|
|
6
|
+
* resolve at dist root — never prefer hashed siblings for JS (second-hop 404).
|
|
5
7
|
*/
|
|
6
8
|
export declare const CONTENT_ADDRESSED_ASSETS_SCHEMA = "vmz.content_addressed_assets.v0";
|
|
7
9
|
/**
|
|
@@ -10,6 +12,19 @@ export declare const CONTENT_ADDRESSED_ASSETS_SCHEMA = "vmz.content_addressed_as
|
|
|
10
12
|
* @param {Record<string, string>} rewrites logical (no leading slash) or `/logical` → `assets/hash.ext`
|
|
11
13
|
*/
|
|
12
14
|
export declare function rewriteCssImports(cssText: any, rewrites: any): any;
|
|
15
|
+
/**
|
|
16
|
+
* Rewrite relative ESM so a file served from `/assets/<hash>.js` resolves against
|
|
17
|
+
* dist root (static `from "./x"` / `export * from "./x"` + dynamic `import("./"+…)`).
|
|
18
|
+
*
|
|
19
|
+
* Always use `../…` (Fix A). Do **not** prefer hashed siblings under `assets/`:
|
|
20
|
+
* barrels like `vmz-dom.js` (`export * from './dom-core.js'`) would then resolve
|
|
21
|
+
* as `/assets/dom-core.js` and 404. `rewrites` is accepted for API parity with CSS
|
|
22
|
+
* but intentionally ignored for JS path choice.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} jsText
|
|
25
|
+
* @param {Record<string, string>} [_rewrites]
|
|
26
|
+
*/
|
|
27
|
+
export declare function rewriteJsEntryRelativeImports(jsText: any, _rewrites?: {}): string;
|
|
13
28
|
/**
|
|
14
29
|
* Emit `assets/<sha256>.<ext>` copies and rewrite HTML href/src to hashed URLs.
|
|
15
30
|
* @param {string} distDir
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* A3: content-addressed assets/<hash> layout for immutable CDN objects.
|
|
3
3
|
* Logical paths stay available for serve/dev; static HTML rewrites to hashed URLs.
|
|
4
4
|
* CSS aggregators (vmz.css) rewrite `@import` to hashed sibling paths under assets/.
|
|
5
|
+
* JS under assets/ always rewrites ESM `./` → `../` so barrels (vmz-dom → dom-core)
|
|
6
|
+
* resolve at dist root — never prefer hashed siblings for JS (second-hop 404).
|
|
5
7
|
*/
|
|
6
8
|
// @ts-nocheck
|
|
7
9
|
import crypto from 'node:crypto';
|
|
@@ -24,6 +26,8 @@ const DEFAULT_CANDIDATES = [
|
|
|
24
26
|
];
|
|
25
27
|
/** CSS files that may @import other logical CSS; processed after leaf CSS is hashed. */
|
|
26
28
|
const CSS_AGGREGATORS = new Set(['vmz.css']);
|
|
29
|
+
/** JS entry shells hashed under assets/; relative ESM must be rewritten first. */
|
|
30
|
+
const JS_ENTRY_AGGREGATORS = new Set(['entry-client.js', 'entry-event.js']);
|
|
27
31
|
const CSS_IMPORT_RE = /@import\s*(?:url\()?['"]?(\.\/)?([^'")\s;]+)['"]?\)?/gi;
|
|
28
32
|
/**
|
|
29
33
|
* Rewrite relative `@import "./foo.css"` to hashed paths under assets/.
|
|
@@ -43,6 +47,35 @@ export function rewriteCssImports(cssText, rewrites) {
|
|
|
43
47
|
return `@import"${sibling}"`;
|
|
44
48
|
});
|
|
45
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Rewrite relative ESM so a file served from `/assets/<hash>.js` resolves against
|
|
52
|
+
* dist root (static `from "./x"` / `export * from "./x"` + dynamic `import("./"+…)`).
|
|
53
|
+
*
|
|
54
|
+
* Always use `../…` (Fix A). Do **not** prefer hashed siblings under `assets/`:
|
|
55
|
+
* barrels like `vmz-dom.js` (`export * from './dom-core.js'`) would then resolve
|
|
56
|
+
* as `/assets/dom-core.js` and 404. `rewrites` is accepted for API parity with CSS
|
|
57
|
+
* but intentionally ignored for JS path choice.
|
|
58
|
+
*
|
|
59
|
+
* @param {string} jsText
|
|
60
|
+
* @param {Record<string, string>} [_rewrites]
|
|
61
|
+
*/
|
|
62
|
+
export function rewriteJsEntryRelativeImports(jsText, _rewrites = {}) {
|
|
63
|
+
let out = String(jsText || '');
|
|
64
|
+
// Dynamic: import("./" + id) → import("../" + id)
|
|
65
|
+
out = out.replace(/import\(\s*"\.\/"\s*\+/g, 'import("../"+');
|
|
66
|
+
out = out.replace(/import\(\s*'\.\/'\s*\+/g, "import('../'+");
|
|
67
|
+
const rewriteSpec = (spec) => {
|
|
68
|
+
const logical = String(spec || '').replace(/^\.\//, '');
|
|
69
|
+
if (!logical || logical.startsWith('../') || logical.startsWith('/'))
|
|
70
|
+
return spec;
|
|
71
|
+
return `../${logical}`;
|
|
72
|
+
};
|
|
73
|
+
// import/export … from "./x" | import("./x")
|
|
74
|
+
out = out.replace(/\b((?:import|export)\s+[^'"\n]*?\s+from\s+|import\s*\(\s*)(['"])(\.\/[^'"]+)\2/g, (match, prefix, quote, spec) => `${prefix}${quote}${rewriteSpec(spec)}${quote}`);
|
|
75
|
+
// side-effect: import "./x.js"
|
|
76
|
+
out = out.replace(/(^|[;\s])(import\s*)(['"])(\.\/[^'"]+)\3/gm, (match, lead, kw, quote, spec) => `${lead}${kw}${quote}${rewriteSpec(spec)}${quote}`);
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
46
79
|
/**
|
|
47
80
|
* Emit `assets/<sha256>.<ext>` copies and rewrite HTML href/src to hashed URLs.
|
|
48
81
|
* @param {string} distDir
|
|
@@ -62,6 +95,22 @@ export function emitContentAddressedAssets(distDir, opts = {}) {
|
|
|
62
95
|
const rewrites = {};
|
|
63
96
|
const ordered = orderCandidates(candidates);
|
|
64
97
|
for (const rel of ordered) {
|
|
98
|
+
// Aggregators are replaced in later passes; leaf JS must rewrite ./ → ../ so a
|
|
99
|
+
// hashed barrel under assets/ never 404s on second-hop relative re-exports.
|
|
100
|
+
if (CSS_AGGREGATORS.has(rel) || JS_ENTRY_AGGREGATORS.has(rel)) {
|
|
101
|
+
ingestCandidate(abs, rel, rewrites, objects, { transform: null });
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (/\.m?js$/i.test(rel)) {
|
|
105
|
+
const src = path.join(abs, rel);
|
|
106
|
+
if (!fs.existsSync(src))
|
|
107
|
+
continue;
|
|
108
|
+
const rewritten = rewriteJsEntryRelativeImports(fs.readFileSync(src, 'utf8'), {});
|
|
109
|
+
ingestCandidate(abs, rel, rewrites, objects, {
|
|
110
|
+
transform: () => Buffer.from(rewritten, 'utf8'),
|
|
111
|
+
});
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
65
114
|
ingestCandidate(abs, rel, rewrites, objects, { transform: null });
|
|
66
115
|
}
|
|
67
116
|
// Aggregator CSS (vmz.css) must import hashed leaf files — rewrite then hash.
|
|
@@ -79,6 +128,21 @@ export function emitContentAddressedAssets(distDir, opts = {}) {
|
|
|
79
128
|
transform: () => Buffer.from(rewritten, 'utf8'),
|
|
80
129
|
});
|
|
81
130
|
}
|
|
131
|
+
// JS entry shells: rewrite relative ESM (static + dynamic) then re-hash.
|
|
132
|
+
for (const rel of ordered) {
|
|
133
|
+
if (!JS_ENTRY_AGGREGATORS.has(rel))
|
|
134
|
+
continue;
|
|
135
|
+
const src = path.join(abs, rel);
|
|
136
|
+
if (!fs.existsSync(src))
|
|
137
|
+
continue;
|
|
138
|
+
const rewritten = rewriteJsEntryRelativeImports(fs.readFileSync(src, 'utf8'), rewrites);
|
|
139
|
+
removeLogicalObject(objects, rel);
|
|
140
|
+
delete rewrites[`/${rel}`];
|
|
141
|
+
delete rewrites[rel];
|
|
142
|
+
ingestCandidate(abs, rel, rewrites, objects, {
|
|
143
|
+
transform: () => Buffer.from(rewritten, 'utf8'),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
82
146
|
objects.sort((a, b) => (a.logicalPath < b.logicalPath ? -1 : a.logicalPath > b.logicalPath ? 1 : 0));
|
|
83
147
|
let rewrittenHtml = 0;
|
|
84
148
|
if (opts.rewriteHtml !== false) {
|
|
@@ -107,15 +171,20 @@ function orderCandidates(candidates) {
|
|
|
107
171
|
/** @type {string[]} */
|
|
108
172
|
const out = [];
|
|
109
173
|
for (const name of DEFAULT_CANDIDATES) {
|
|
110
|
-
if (set.has(name) && !CSS_AGGREGATORS.has(name))
|
|
174
|
+
if (set.has(name) && !CSS_AGGREGATORS.has(name) && !JS_ENTRY_AGGREGATORS.has(name))
|
|
111
175
|
out.push(name);
|
|
112
176
|
}
|
|
113
177
|
for (const name of [...set].sort()) {
|
|
114
|
-
if (!CSS_AGGREGATORS.has(name) && !out.includes(name))
|
|
178
|
+
if (!CSS_AGGREGATORS.has(name) && !JS_ENTRY_AGGREGATORS.has(name) && !out.includes(name)) {
|
|
115
179
|
out.push(name);
|
|
180
|
+
}
|
|
116
181
|
}
|
|
117
182
|
if (set.has('vmz.css'))
|
|
118
183
|
out.push('vmz.css');
|
|
184
|
+
for (const name of ['entry-client.js', 'entry-event.js']) {
|
|
185
|
+
if (set.has(name))
|
|
186
|
+
out.push(name);
|
|
187
|
+
}
|
|
119
188
|
return out;
|
|
120
189
|
}
|
|
121
190
|
/**
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare const DELIVERY_PROFILE_AUTHORING_SCHEMA = "vmz.delivery.authoring.v0";
|
|
6
6
|
export declare const BUILD_PROFILE_SELECTION_SCHEMA = "vmz.build.profile_selection.v0";
|
|
7
|
-
/** Browser-era assembly kinds (04 B5). */
|
|
7
|
+
/** Browser-era assembly kinds (04 B5). `static-cdn` was renamed to `web-static`. */
|
|
8
8
|
export declare const ASSEMBLIES: readonly string[];
|
|
9
9
|
export declare const SERVER_RUNTIMES: readonly string[];
|
|
10
10
|
/** Official built-in aliases when not overridden in config. */
|
|
@@ -28,6 +28,22 @@ export declare const BUILTIN_PROFILES: Readonly<{
|
|
|
28
28
|
serverRuntime: string;
|
|
29
29
|
};
|
|
30
30
|
}>;
|
|
31
|
+
/**
|
|
32
|
+
* Profile artifact directory name under CLI `--out-dir` (default = profile id).
|
|
33
|
+
* @param {string} id
|
|
34
|
+
* @param {unknown} rawName
|
|
35
|
+
* @param {Array<{ code: string, message: string }>} diagnostics
|
|
36
|
+
* @returns {string | null}
|
|
37
|
+
*/
|
|
38
|
+
export declare function normalizeProfileArtifactName(id: any, rawName: any, diagnostics: any): string;
|
|
39
|
+
/**
|
|
40
|
+
* Workspace `--out-dir` + profile `name` → artifact root.
|
|
41
|
+
* Always nests: `path.join(outDir, name)` where `name` defaults to profile id
|
|
42
|
+
* (`name: 'cdn'` → `dist/cdn`; omit → `dist/static` for profile `static`).
|
|
43
|
+
* @param {string} outDir
|
|
44
|
+
* @param {{ name?: string, id?: string } | null | undefined} profile
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveProfileArtifactDir(outDir: any, profile: any): any;
|
|
31
47
|
export declare function pickSiteAuthoring(raw: any): {
|
|
32
48
|
artifact: string;
|
|
33
49
|
sources: any;
|
|
@@ -69,6 +85,8 @@ export declare function selectBuildProfile(table: any, cliProfile?: string): {
|
|
|
69
85
|
selection: {
|
|
70
86
|
schema: string;
|
|
71
87
|
profileId: any;
|
|
88
|
+
name: any;
|
|
89
|
+
nameExplicit: boolean;
|
|
72
90
|
host: any;
|
|
73
91
|
assembly: any;
|
|
74
92
|
serverRuntime: any;
|
package/dist/delivery-profile.js
CHANGED
|
@@ -4,18 +4,67 @@
|
|
|
4
4
|
*/
|
|
5
5
|
// @ts-nocheck
|
|
6
6
|
import crypto from 'node:crypto';
|
|
7
|
+
import path from 'node:path';
|
|
7
8
|
export const DELIVERY_PROFILE_AUTHORING_SCHEMA = 'vmz.delivery.authoring.v0';
|
|
8
9
|
export const BUILD_PROFILE_SELECTION_SCHEMA = 'vmz.build.profile_selection.v0';
|
|
9
|
-
/** Browser-era assembly kinds (04 B5). */
|
|
10
|
-
export const ASSEMBLIES = Object.freeze(['local-static', 'static
|
|
10
|
+
/** Browser-era assembly kinds (04 B5). `static-cdn` was renamed to `web-static`. */
|
|
11
|
+
export const ASSEMBLIES = Object.freeze(['local-static', 'web-static', 'server-host', 'cdn+server', 'rust-embedded']);
|
|
11
12
|
export const SERVER_RUNTIMES = Object.freeze(['node', 'worker', 'deno', 'bun', 'rust-host']);
|
|
12
13
|
/** Official built-in aliases when not overridden in config. */
|
|
13
14
|
export const BUILTIN_PROFILES = Object.freeze({
|
|
14
15
|
'web-client': { host: 'browser', assembly: 'local-static' },
|
|
15
|
-
static: { host: 'browser', assembly: 'static
|
|
16
|
+
static: { host: 'browser', assembly: 'web-static' },
|
|
16
17
|
'web-ssr': { host: 'browser', assembly: 'server-host', serverRuntime: 'node' },
|
|
17
18
|
'web-hybrid': { host: 'browser', assembly: 'cdn+server', serverRuntime: 'node' },
|
|
18
19
|
});
|
|
20
|
+
/**
|
|
21
|
+
* Profile artifact directory name under CLI `--out-dir` (default = profile id).
|
|
22
|
+
* @param {string} id
|
|
23
|
+
* @param {unknown} rawName
|
|
24
|
+
* @param {Array<{ code: string, message: string }>} diagnostics
|
|
25
|
+
* @returns {string | null}
|
|
26
|
+
*/
|
|
27
|
+
export function normalizeProfileArtifactName(id, rawName, diagnostics) {
|
|
28
|
+
const fallback = String(id || '').trim();
|
|
29
|
+
if (rawName == null || rawName === '')
|
|
30
|
+
return fallback || null;
|
|
31
|
+
if (typeof rawName !== 'string') {
|
|
32
|
+
diagnostics.push({
|
|
33
|
+
code: 'delivery.profile.name',
|
|
34
|
+
message: `profiles.${id}.name must be a string (got ${typeof rawName})`,
|
|
35
|
+
});
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const name = rawName.trim();
|
|
39
|
+
if (!name) {
|
|
40
|
+
diagnostics.push({
|
|
41
|
+
code: 'delivery.profile.name',
|
|
42
|
+
message: `profiles.${id}.name must be a non-empty string`,
|
|
43
|
+
});
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
if (name === '.' || name === '..' || name.includes('/') || name.includes('\\') || name.includes('\0')) {
|
|
47
|
+
diagnostics.push({
|
|
48
|
+
code: 'delivery.profile.name',
|
|
49
|
+
message: `profiles.${id}.name must be a single path segment under --out-dir (got '${name}')`,
|
|
50
|
+
});
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return name;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Workspace `--out-dir` + profile `name` → artifact root.
|
|
57
|
+
* Always nests: `path.join(outDir, name)` where `name` defaults to profile id
|
|
58
|
+
* (`name: 'cdn'` → `dist/cdn`; omit → `dist/static` for profile `static`).
|
|
59
|
+
* @param {string} outDir
|
|
60
|
+
* @param {{ name?: string, id?: string } | null | undefined} profile
|
|
61
|
+
*/
|
|
62
|
+
export function resolveProfileArtifactDir(outDir, profile) {
|
|
63
|
+
const name = String(profile?.name || profile?.id || '').trim();
|
|
64
|
+
if (!name)
|
|
65
|
+
return outDir;
|
|
66
|
+
return path.join(outDir, name);
|
|
67
|
+
}
|
|
19
68
|
function isPlainObject(v) {
|
|
20
69
|
return v != null && typeof v === 'object' && !Array.isArray(v);
|
|
21
70
|
}
|
|
@@ -122,7 +171,14 @@ function normalizeProfileEntry(entry, id, diagnostics) {
|
|
|
122
171
|
message: `profiles.${id}.host: only 'browser' is supported before Browser Production (got ${host})`,
|
|
123
172
|
});
|
|
124
173
|
}
|
|
125
|
-
|
|
174
|
+
let assembly = String(entry.assembly || '').trim();
|
|
175
|
+
if (assembly === 'static-cdn') {
|
|
176
|
+
diagnostics.push({
|
|
177
|
+
code: 'delivery.profile.assembly.renamed',
|
|
178
|
+
message: `profiles.${id}.assembly 'static-cdn' was renamed to 'web-static'`,
|
|
179
|
+
});
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
126
182
|
if (!ASSEMBLIES.includes(assembly)) {
|
|
127
183
|
diagnostics.push({
|
|
128
184
|
code: 'delivery.profile.assembly',
|
|
@@ -130,6 +186,10 @@ function normalizeProfileEntry(entry, id, diagnostics) {
|
|
|
130
186
|
});
|
|
131
187
|
return null;
|
|
132
188
|
}
|
|
189
|
+
const nameExplicit = entry.name != null && String(entry.name).trim() !== '';
|
|
190
|
+
const name = normalizeProfileArtifactName(id, nameExplicit ? entry.name : id, diagnostics);
|
|
191
|
+
if (!name)
|
|
192
|
+
return null;
|
|
133
193
|
let serverRuntime = null;
|
|
134
194
|
if (assembly === 'server-host' || assembly === 'cdn+server') {
|
|
135
195
|
serverRuntime = String(entry.serverRuntime || 'node');
|
|
@@ -171,6 +231,9 @@ function normalizeProfileEntry(entry, id, diagnostics) {
|
|
|
171
231
|
}
|
|
172
232
|
return {
|
|
173
233
|
id,
|
|
234
|
+
name,
|
|
235
|
+
/** True when author set `profiles.<id>.name`; false → `name` defaulted to profile id. */
|
|
236
|
+
nameExplicit,
|
|
174
237
|
host: 'browser',
|
|
175
238
|
assembly,
|
|
176
239
|
serverRuntime,
|
|
@@ -303,6 +366,8 @@ export function selectBuildProfile(table, cliProfile = '') {
|
|
|
303
366
|
const selection = {
|
|
304
367
|
schema: BUILD_PROFILE_SELECTION_SCHEMA,
|
|
305
368
|
profileId: id,
|
|
369
|
+
name: profile.name,
|
|
370
|
+
nameExplicit: Boolean(profile.nameExplicit),
|
|
306
371
|
host: profile.host,
|
|
307
372
|
assembly: profile.assembly,
|
|
308
373
|
serverRuntime: profile.serverRuntime,
|
|
@@ -315,7 +380,7 @@ export function selectBuildProfile(table, cliProfile = '') {
|
|
|
315
380
|
}
|
|
316
381
|
export function semanticIdsForAssembly(assembly) {
|
|
317
382
|
switch (assembly) {
|
|
318
|
-
case 'static
|
|
383
|
+
case 'web-static':
|
|
319
384
|
return ['static-delivery', 'asset-graph'];
|
|
320
385
|
case 'server-host':
|
|
321
386
|
return ['server-host', 'asset-graph'];
|
package/dist/dev-session.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -166,13 +166,15 @@ export { cmdApplication, runCheck as runApplicationCheck } from './application-c
|
|
|
166
166
|
export { cmdArtifact } from './release-cmd.js';
|
|
167
167
|
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';
|
|
168
168
|
export { STATIC_DELIVERY_MANIFEST_SCHEMA, emitWebStatic, } from './static-emit.js';
|
|
169
|
-
export { CONTENT_ADDRESSED_ASSETS_SCHEMA, emitContentAddressedAssets, resolveAssetByDigest, assertSharedAssetPath, contentAddressedAssetsDigest, } from './content-addressed-assets.js';
|
|
169
|
+
export { CONTENT_ADDRESSED_ASSETS_SCHEMA, emitContentAddressedAssets, resolveAssetByDigest, assertSharedAssetPath, contentAddressedAssetsDigest, rewriteCssImports, rewriteJsEntryRelativeImports, } from './content-addressed-assets.js';
|
|
170
|
+
export { SITE_FAVICON_SCHEMA, emitSiteFavicon, readSiteFaviconHeadHtml, packPngsIntoIco, } from './site-favicon.js';
|
|
171
|
+
export { PUBLIC_STATIC_ASSETS_SCHEMA, emitPublicStaticAssets, } from './public-static-assets.js';
|
|
170
172
|
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';
|
|
171
173
|
export { SITE_DELIVERY_CONTRACT_SCHEMA, SITE_DELIVERY_RESOLUTION_SCHEMA, defineSite, normalizeSiteDelivery, normalizeSourceProbe, resolveSiteRelease, probeReleaseDirectory, emitSiteDelivery, } from './site-delivery.js';
|
|
172
174
|
export { EMBEDDED_RESOURCE_INDEX_SCHEMA, emitEmbeddedPackaging, } from './embedded-packaging.js';
|
|
173
175
|
export { SERVER_LANG_IDS, SERVER_LANG_ALIASES, SERVER_LANGUAGE_BACKENDS, resolveServerLanguage, assertLangRuntimePair, } from './server-language-backend.js';
|
|
174
176
|
export { WECHAT_PACKAGING_SCHEMA, WECHAT_PACKAGING_REL, wechatPackagingFromDelivery, materializeWechatPackaging, } from './wechat-packaging.js';
|
|
175
|
-
export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSEMBLIES, SERVER_RUNTIMES, BUILTIN_PROFILES, pickSiteAuthoring, pickDeliveryPackaging, normalizeDeliveryAuthoring, selectBuildProfile, semanticIdsForAssembly, } from './delivery-profile.js';
|
|
177
|
+
export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSEMBLIES, SERVER_RUNTIMES, BUILTIN_PROFILES, pickSiteAuthoring, pickDeliveryPackaging, normalizeProfileArtifactName, resolveProfileArtifactDir, normalizeDeliveryAuthoring, selectBuildProfile, semanticIdsForAssembly, } from './delivery-profile.js';
|
|
176
178
|
export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
|
|
177
179
|
export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
|
|
178
180
|
export { BUILD_PROOF_SCHEMA, ASSEMBLE_MANIFEST_SCHEMA, assembleDelivery, emitBuildProof, } from './build-assemble.js';
|
package/dist/index.js
CHANGED
|
@@ -147,6 +147,7 @@ export function resolveCoreRuntimeDist() {
|
|
|
147
147
|
/** Runtime companions required by dist/vmz-serve-host.mjs relative imports. */
|
|
148
148
|
export const SERVE_HOST_RUNTIME_FILES = [
|
|
149
149
|
['serve-host.mjs', 'vmz-serve-host.mjs'],
|
|
150
|
+
['native-addon.js', 'native-addon.js'],
|
|
150
151
|
['list-client-components.js', 'list-client-components.js'],
|
|
151
152
|
['deployment-registry.js', 'deployment-registry.js'],
|
|
152
153
|
['render-host.js', 'render-host.js'],
|
|
@@ -408,13 +409,15 @@ export { ARTIFACT_DIFF_SCHEMA, DELIVERY_ARTIFACT_MANIFEST_SCHEMA, RELEASE_ENVELO
|
|
|
408
409
|
// APPLICATION_ARTIFACT_SCHEMA lives in @vmz/protocol (already re-exported above);
|
|
409
410
|
// release-pack keeps a local constant for envelope writes — do not dual-export the name.
|
|
410
411
|
export { STATIC_DELIVERY_MANIFEST_SCHEMA, emitWebStatic, } from './static-emit.js';
|
|
411
|
-
export { CONTENT_ADDRESSED_ASSETS_SCHEMA, emitContentAddressedAssets, resolveAssetByDigest, assertSharedAssetPath, contentAddressedAssetsDigest, } from './content-addressed-assets.js';
|
|
412
|
+
export { CONTENT_ADDRESSED_ASSETS_SCHEMA, emitContentAddressedAssets, resolveAssetByDigest, assertSharedAssetPath, contentAddressedAssetsDigest, rewriteCssImports, rewriteJsEntryRelativeImports, } from './content-addressed-assets.js';
|
|
413
|
+
export { SITE_FAVICON_SCHEMA, emitSiteFavicon, readSiteFaviconHeadHtml, packPngsIntoIco, } from './site-favicon.js';
|
|
414
|
+
export { PUBLIC_STATIC_ASSETS_SCHEMA, emitPublicStaticAssets, } from './public-static-assets.js';
|
|
412
415
|
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';
|
|
413
416
|
export { SITE_DELIVERY_CONTRACT_SCHEMA, SITE_DELIVERY_RESOLUTION_SCHEMA, defineSite, normalizeSiteDelivery, normalizeSourceProbe, resolveSiteRelease, probeReleaseDirectory, emitSiteDelivery, } from './site-delivery.js';
|
|
414
417
|
export { EMBEDDED_RESOURCE_INDEX_SCHEMA, emitEmbeddedPackaging, } from './embedded-packaging.js';
|
|
415
418
|
export { SERVER_LANG_IDS, SERVER_LANG_ALIASES, SERVER_LANGUAGE_BACKENDS, resolveServerLanguage, assertLangRuntimePair, } from './server-language-backend.js';
|
|
416
419
|
export { WECHAT_PACKAGING_SCHEMA, WECHAT_PACKAGING_REL, wechatPackagingFromDelivery, materializeWechatPackaging, } from './wechat-packaging.js';
|
|
417
|
-
export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSEMBLIES, SERVER_RUNTIMES, BUILTIN_PROFILES, pickSiteAuthoring, pickDeliveryPackaging, normalizeDeliveryAuthoring, selectBuildProfile, semanticIdsForAssembly, } from './delivery-profile.js';
|
|
420
|
+
export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSEMBLIES, SERVER_RUNTIMES, BUILTIN_PROFILES, pickSiteAuthoring, pickDeliveryPackaging, normalizeProfileArtifactName, resolveProfileArtifactDir, normalizeDeliveryAuthoring, selectBuildProfile, semanticIdsForAssembly, } from './delivery-profile.js';
|
|
418
421
|
export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
|
|
419
422
|
export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
|
|
420
423
|
export { BUILD_PROOF_SCHEMA, ASSEMBLE_MANIFEST_SCHEMA, assembleDelivery, emitBuildProof, } from './build-assemble.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opaque site-root static files: project `public/**` → deploy root (static / web-static).
|
|
3
|
+
* Not dependency packaging (no node_modules / @dxo/* scanning).
|
|
4
|
+
*/
|
|
5
|
+
export declare const PUBLIC_STATIC_ASSETS_SCHEMA = "vmz.public_static_assets.v0";
|
|
6
|
+
/**
|
|
7
|
+
* @param {string} distDir
|
|
8
|
+
* @param {{ projectRoot?: string, publicDir?: string }} [opts]
|
|
9
|
+
*/
|
|
10
|
+
export declare function emitPublicStaticAssets(distDir: any, opts?: {}): {
|
|
11
|
+
schema: string;
|
|
12
|
+
status: string;
|
|
13
|
+
reason: string;
|
|
14
|
+
fileCount: number;
|
|
15
|
+
files: any[];
|
|
16
|
+
skippedConflicts: any[];
|
|
17
|
+
} | {
|
|
18
|
+
schema: string;
|
|
19
|
+
status: string;
|
|
20
|
+
source: string;
|
|
21
|
+
fileCount: number;
|
|
22
|
+
files: any[];
|
|
23
|
+
skippedConflicts: any[];
|
|
24
|
+
};
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opaque site-root static files: project `public/**` → deploy root (static / web-static).
|
|
3
|
+
* Not dependency packaging (no node_modules / @dxo/* scanning).
|
|
4
|
+
*/
|
|
5
|
+
// @ts-nocheck
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { writePrettyJsonFile } from './pretty-json.js';
|
|
9
|
+
export const PUBLIC_STATIC_ASSETS_SCHEMA = 'vmz.public_static_assets.v0';
|
|
10
|
+
/** Relative paths under dist that VMZ owns; public/ must not clobber. */
|
|
11
|
+
const RESERVED_EXACT = new Set([
|
|
12
|
+
'entry-client.js',
|
|
13
|
+
'entry-event.js',
|
|
14
|
+
'vmz-dom.js',
|
|
15
|
+
'vmz-runtime.js',
|
|
16
|
+
'vmz-http.js',
|
|
17
|
+
'vmz-client-nav.js',
|
|
18
|
+
'vmz.css',
|
|
19
|
+
'vmz-designs.css',
|
|
20
|
+
'vmz-style.css',
|
|
21
|
+
'vmz-deployment.json',
|
|
22
|
+
'vmz-routes.json',
|
|
23
|
+
'vmz-plugin-targets.json',
|
|
24
|
+
'sitemap.xml',
|
|
25
|
+
'robots.txt',
|
|
26
|
+
'404.html',
|
|
27
|
+
]);
|
|
28
|
+
/**
|
|
29
|
+
* @param {string} distDir
|
|
30
|
+
* @param {{ projectRoot?: string, publicDir?: string }} [opts]
|
|
31
|
+
*/
|
|
32
|
+
export function emitPublicStaticAssets(distDir, opts = {}) {
|
|
33
|
+
const absDist = path.resolve(distDir);
|
|
34
|
+
const projectRoot = opts.projectRoot ? path.resolve(opts.projectRoot) : null;
|
|
35
|
+
const publicDir = opts.publicDir ? path.resolve(opts.publicDir) : projectRoot ? path.join(projectRoot, 'public') : null;
|
|
36
|
+
if (!publicDir || !fs.existsSync(publicDir) || !fs.statSync(publicDir).isDirectory()) {
|
|
37
|
+
const skipped = {
|
|
38
|
+
schema: PUBLIC_STATIC_ASSETS_SCHEMA,
|
|
39
|
+
status: 'skipped',
|
|
40
|
+
reason: publicDir ? 'public/ missing' : 'no projectRoot',
|
|
41
|
+
fileCount: 0,
|
|
42
|
+
files: [],
|
|
43
|
+
skippedConflicts: [],
|
|
44
|
+
};
|
|
45
|
+
writeArtifact(absDist, skipped);
|
|
46
|
+
return skipped;
|
|
47
|
+
}
|
|
48
|
+
/** @type {Array<{ path: string, bytes: number }>} */
|
|
49
|
+
const files = [];
|
|
50
|
+
/** @type {Array<{ path: string, reason: string }>} */
|
|
51
|
+
const skippedConflicts = [];
|
|
52
|
+
walkFiles(publicDir, (absFile) => {
|
|
53
|
+
const rel = path.relative(publicDir, absFile).replace(/\\/g, '/');
|
|
54
|
+
if (!rel || rel.startsWith('..'))
|
|
55
|
+
return;
|
|
56
|
+
if (shouldSkipReserved(rel)) {
|
|
57
|
+
skippedConflicts.push({ path: rel, reason: 'reserved-vmz-path' });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
const dest = path.join(absDist, ...rel.split('/'));
|
|
61
|
+
if (fs.existsSync(dest) && isReservedExisting(rel, dest, absDist)) {
|
|
62
|
+
skippedConflicts.push({ path: rel, reason: 'would-clobber-generated' });
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
66
|
+
fs.copyFileSync(absFile, dest);
|
|
67
|
+
files.push({ path: rel, bytes: fs.statSync(dest).size });
|
|
68
|
+
});
|
|
69
|
+
files.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0));
|
|
70
|
+
const artifact = {
|
|
71
|
+
schema: PUBLIC_STATIC_ASSETS_SCHEMA,
|
|
72
|
+
status: 'ready',
|
|
73
|
+
source: 'public/',
|
|
74
|
+
fileCount: files.length,
|
|
75
|
+
files,
|
|
76
|
+
skippedConflicts,
|
|
77
|
+
};
|
|
78
|
+
writeArtifact(absDist, artifact);
|
|
79
|
+
return artifact;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* @param {string} rel
|
|
83
|
+
*/
|
|
84
|
+
function shouldSkipReserved(rel) {
|
|
85
|
+
if (rel === '_vmz' || rel.startsWith('_vmz/'))
|
|
86
|
+
return true;
|
|
87
|
+
if (RESERVED_EXACT.has(rel))
|
|
88
|
+
return true;
|
|
89
|
+
if (rel.startsWith('pages/') || rel.startsWith('components/'))
|
|
90
|
+
return true;
|
|
91
|
+
if (/\.client\.js$/i.test(rel))
|
|
92
|
+
return true;
|
|
93
|
+
if (rel.startsWith('assets/') && /^assets\/[a-f0-9]{64}\./i.test(rel))
|
|
94
|
+
return true;
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* After compile, many generated files already exist; do not let public overwrite them.
|
|
99
|
+
* Allow overwrite of non-reserved paths (e.g. re-copy same wasm).
|
|
100
|
+
* @param {string} rel
|
|
101
|
+
* @param {string} dest
|
|
102
|
+
* @param {string} absDist
|
|
103
|
+
*/
|
|
104
|
+
function isReservedExisting(rel, dest, absDist) {
|
|
105
|
+
if (shouldSkipReserved(rel))
|
|
106
|
+
return true;
|
|
107
|
+
// Never overwrite generated HTML shells that static-emit will (or did) write.
|
|
108
|
+
if (/\.html$/i.test(rel) && fs.existsSync(dest)) {
|
|
109
|
+
const text = fs.readFileSync(dest, 'utf8');
|
|
110
|
+
if (text.includes('data-vmz-page') || text.includes('entry-client'))
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
void absDist;
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* @param {string} dir
|
|
118
|
+
* @param {(absFile: string) => void} onFile
|
|
119
|
+
*/
|
|
120
|
+
function walkFiles(dir, onFile) {
|
|
121
|
+
for (const name of fs.readdirSync(dir)) {
|
|
122
|
+
if (name === '.' || name === '..')
|
|
123
|
+
continue;
|
|
124
|
+
const full = path.join(dir, name);
|
|
125
|
+
const st = fs.statSync(full);
|
|
126
|
+
if (st.isDirectory())
|
|
127
|
+
walkFiles(full, onFile);
|
|
128
|
+
else if (st.isFile())
|
|
129
|
+
onFile(full);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* @param {string} absDist
|
|
134
|
+
* @param {Record<string, unknown>} artifact
|
|
135
|
+
*/
|
|
136
|
+
function writeArtifact(absDist, artifact) {
|
|
137
|
+
const vmzDir = path.join(absDist, '_vmz');
|
|
138
|
+
fs.mkdirSync(vmzDir, { recursive: true });
|
|
139
|
+
writePrettyJsonFile(path.join(vmzDir, 'public-static-assets.json'), artifact);
|
|
140
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Site favicon: author SVG → PNG + ICO + `_vmz/site-favicon.json` head links.
|
|
3
|
+
* Convention: `assets/favicon.svg` (or `favicon.svg`) under project / already in dist.
|
|
4
|
+
*/
|
|
5
|
+
export declare const SITE_FAVICON_SCHEMA = "vmz.site_favicon.v0";
|
|
6
|
+
/**
|
|
7
|
+
* @param {string} distDir
|
|
8
|
+
* @param {{ projectRoot?: string, skipNative?: boolean }} [opts]
|
|
9
|
+
*/
|
|
10
|
+
export declare function emitSiteFavicon(distDir: any, opts?: {}): {
|
|
11
|
+
schema: string;
|
|
12
|
+
status: string;
|
|
13
|
+
source: string;
|
|
14
|
+
svg: string;
|
|
15
|
+
ico: string;
|
|
16
|
+
png: string[];
|
|
17
|
+
headHtml: string;
|
|
18
|
+
} | {
|
|
19
|
+
status: string;
|
|
20
|
+
reason: string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Read ready head HTML for static/SSR shells (empty when missing).
|
|
24
|
+
* @param {string} distDir
|
|
25
|
+
*/
|
|
26
|
+
export declare function readSiteFaviconHeadHtml(distDir: any): any;
|
|
27
|
+
/**
|
|
28
|
+
* PNG-in-ICO (Vista+); widely accepted by modern browsers.
|
|
29
|
+
* @param {Array<{ png: Buffer, size: number }>} images
|
|
30
|
+
*/
|
|
31
|
+
export declare function packPngsIntoIco(images: any): Buffer<ArrayBuffer>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Site favicon: author SVG → PNG + ICO + `_vmz/site-favicon.json` head links.
|
|
3
|
+
* Convention: `assets/favicon.svg` (or `favicon.svg`) under project / already in dist.
|
|
4
|
+
*/
|
|
5
|
+
// @ts-nocheck
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { requireNativeAddon } from './native-addon.js';
|
|
9
|
+
import { writePrettyJsonFile } from './pretty-json.js';
|
|
10
|
+
export const SITE_FAVICON_SCHEMA = 'vmz.site_favicon.v0';
|
|
11
|
+
const ICO_SIZES = [16, 32, 48];
|
|
12
|
+
/**
|
|
13
|
+
* @param {string} distDir
|
|
14
|
+
* @param {{ projectRoot?: string, skipNative?: boolean }} [opts]
|
|
15
|
+
*/
|
|
16
|
+
export function emitSiteFavicon(distDir, opts = {}) {
|
|
17
|
+
const absDist = path.resolve(distDir);
|
|
18
|
+
const projectRoot = opts.projectRoot ? path.resolve(opts.projectRoot) : null;
|
|
19
|
+
const src = discoverFaviconSvg(absDist, projectRoot);
|
|
20
|
+
if (!src) {
|
|
21
|
+
return { status: 'skipped', reason: 'no assets/favicon.svg' };
|
|
22
|
+
}
|
|
23
|
+
const svgText = fs.readFileSync(src.path, 'utf8');
|
|
24
|
+
const assetsDir = path.join(absDist, 'assets');
|
|
25
|
+
fs.mkdirSync(assetsDir, { recursive: true });
|
|
26
|
+
const svgDest = path.join(assetsDir, 'favicon.svg');
|
|
27
|
+
if (path.resolve(src.path) !== path.resolve(svgDest)) {
|
|
28
|
+
fs.copyFileSync(src.path, svgDest);
|
|
29
|
+
}
|
|
30
|
+
/** @type {Buffer[]} */
|
|
31
|
+
const pngs = [];
|
|
32
|
+
if (!opts.skipNative) {
|
|
33
|
+
const native = requireNativeAddon();
|
|
34
|
+
if (typeof native.rasterizeSvgPng !== 'function') {
|
|
35
|
+
throw new Error('vmz native addon missing rasterizeSvgPng — rebuild with `pnpm napi:build`');
|
|
36
|
+
}
|
|
37
|
+
for (const px of ICO_SIZES) {
|
|
38
|
+
const buf = Buffer.from(native.rasterizeSvgPng(svgText, px));
|
|
39
|
+
pngs.push(buf);
|
|
40
|
+
fs.writeFileSync(path.join(assetsDir, `favicon-${px}.png`), buf);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
let icoPath = null;
|
|
44
|
+
if (pngs.length) {
|
|
45
|
+
const ico = packPngsIntoIco(pngs.map((png, i) => ({ png, size: ICO_SIZES[i] })));
|
|
46
|
+
icoPath = path.join(absDist, 'favicon.ico');
|
|
47
|
+
fs.writeFileSync(icoPath, ico);
|
|
48
|
+
}
|
|
49
|
+
const headParts = [];
|
|
50
|
+
if (icoPath) {
|
|
51
|
+
headParts.push('<link rel="icon" href="/favicon.ico" sizes="any">');
|
|
52
|
+
}
|
|
53
|
+
headParts.push('<link rel="icon" href="/assets/favicon.svg" type="image/svg+xml">');
|
|
54
|
+
for (const px of ICO_SIZES) {
|
|
55
|
+
if (fs.existsSync(path.join(assetsDir, `favicon-${px}.png`))) {
|
|
56
|
+
headParts.push(`<link rel="icon" type="image/png" sizes="${px}x${px}" href="/assets/favicon-${px}.png">`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const headHtml = `${headParts.join('\n')}\n`;
|
|
60
|
+
const artifact = {
|
|
61
|
+
schema: SITE_FAVICON_SCHEMA,
|
|
62
|
+
status: 'ready',
|
|
63
|
+
source: src.rel,
|
|
64
|
+
svg: 'assets/favicon.svg',
|
|
65
|
+
ico: icoPath ? 'favicon.ico' : null,
|
|
66
|
+
png: ICO_SIZES.filter((px) => fs.existsSync(path.join(assetsDir, `favicon-${px}.png`))).map((px) => `assets/favicon-${px}.png`),
|
|
67
|
+
headHtml,
|
|
68
|
+
};
|
|
69
|
+
const vmzDir = path.join(absDist, '_vmz');
|
|
70
|
+
fs.mkdirSync(vmzDir, { recursive: true });
|
|
71
|
+
writePrettyJsonFile(path.join(vmzDir, 'site-favicon.json'), artifact);
|
|
72
|
+
return artifact;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Read ready head HTML for static/SSR shells (empty when missing).
|
|
76
|
+
* @param {string} distDir
|
|
77
|
+
*/
|
|
78
|
+
export function readSiteFaviconHeadHtml(distDir) {
|
|
79
|
+
try {
|
|
80
|
+
const p = path.join(distDir, '_vmz', 'site-favicon.json');
|
|
81
|
+
if (!fs.existsSync(p))
|
|
82
|
+
return '';
|
|
83
|
+
const j = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
84
|
+
if (j?.status !== 'ready' || typeof j.headHtml !== 'string')
|
|
85
|
+
return '';
|
|
86
|
+
return j.headHtml;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return '';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* @param {string} distDir
|
|
94
|
+
* @param {string|null} projectRoot
|
|
95
|
+
*/
|
|
96
|
+
function discoverFaviconSvg(distDir, projectRoot) {
|
|
97
|
+
const candidates = [path.join(distDir, 'assets', 'favicon.svg'), path.join(distDir, 'favicon.svg')];
|
|
98
|
+
if (projectRoot) {
|
|
99
|
+
candidates.push(path.join(projectRoot, 'assets', 'favicon.svg'), path.join(projectRoot, 'favicon.svg'), path.join(projectRoot, 'public', 'assets', 'favicon.svg'), path.join(projectRoot, 'public', 'favicon.svg'));
|
|
100
|
+
}
|
|
101
|
+
for (const abs of candidates) {
|
|
102
|
+
if (fs.existsSync(abs) && fs.statSync(abs).isFile()) {
|
|
103
|
+
return {
|
|
104
|
+
path: abs,
|
|
105
|
+
rel: path.relative(projectRoot || distDir, abs).replace(/\\/g, '/') || 'assets/favicon.svg',
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* PNG-in-ICO (Vista+); widely accepted by modern browsers.
|
|
113
|
+
* @param {Array<{ png: Buffer, size: number }>} images
|
|
114
|
+
*/
|
|
115
|
+
export function packPngsIntoIco(images) {
|
|
116
|
+
const count = images.length;
|
|
117
|
+
const header = Buffer.alloc(6);
|
|
118
|
+
header.writeUInt16LE(0, 0);
|
|
119
|
+
header.writeUInt16LE(1, 2);
|
|
120
|
+
header.writeUInt16LE(count, 4);
|
|
121
|
+
const entries = Buffer.alloc(16 * count);
|
|
122
|
+
/** @type {Buffer[]} */
|
|
123
|
+
const blobs = [];
|
|
124
|
+
let offset = 6 + 16 * count;
|
|
125
|
+
for (let i = 0; i < count; i += 1) {
|
|
126
|
+
const { png, size } = images[i];
|
|
127
|
+
const o = i * 16;
|
|
128
|
+
entries.writeUInt8(size >= 256 ? 0 : size, o);
|
|
129
|
+
entries.writeUInt8(size >= 256 ? 0 : size, o + 1);
|
|
130
|
+
entries.writeUInt8(0, o + 2);
|
|
131
|
+
entries.writeUInt8(0, o + 3);
|
|
132
|
+
entries.writeUInt16LE(1, o + 4);
|
|
133
|
+
entries.writeUInt16LE(32, o + 6);
|
|
134
|
+
entries.writeUInt32LE(png.length, o + 8);
|
|
135
|
+
entries.writeUInt32LE(offset, o + 12);
|
|
136
|
+
blobs.push(png);
|
|
137
|
+
offset += png.length;
|
|
138
|
+
}
|
|
139
|
+
return Buffer.concat([header, entries, ...blobs]);
|
|
140
|
+
}
|
package/dist/static-emit.d.ts
CHANGED
|
@@ -43,6 +43,12 @@ export declare function emitWebStatic(distDir: any, opts?: {}): Promise<{
|
|
|
43
43
|
sitemap: string;
|
|
44
44
|
robots: string;
|
|
45
45
|
};
|
|
46
|
+
publicAssets: {
|
|
47
|
+
schema: string;
|
|
48
|
+
status: string;
|
|
49
|
+
fileCount: number;
|
|
50
|
+
source: any;
|
|
51
|
+
};
|
|
46
52
|
};
|
|
47
53
|
htmlFiles: any[];
|
|
48
54
|
skipped: any[];
|
|
@@ -55,6 +61,21 @@ export declare function emitWebStatic(distDir: any, opts?: {}): Promise<{
|
|
|
55
61
|
objects: any[];
|
|
56
62
|
rewrittenHtml: number;
|
|
57
63
|
};
|
|
64
|
+
publicAssets: {
|
|
65
|
+
schema: string;
|
|
66
|
+
status: string;
|
|
67
|
+
reason: string;
|
|
68
|
+
fileCount: number;
|
|
69
|
+
files: any[];
|
|
70
|
+
skippedConflicts: any[];
|
|
71
|
+
} | {
|
|
72
|
+
schema: string;
|
|
73
|
+
status: string;
|
|
74
|
+
source: string;
|
|
75
|
+
fileCount: number;
|
|
76
|
+
files: any[];
|
|
77
|
+
skippedConflicts: any[];
|
|
78
|
+
};
|
|
58
79
|
cdnPolicy: {
|
|
59
80
|
schema: string;
|
|
60
81
|
applicationId: any;
|
package/dist/static-emit.js
CHANGED
|
@@ -15,7 +15,9 @@ import { emitContentAddressedAssets } from './content-addressed-assets.js';
|
|
|
15
15
|
import { absoluteUrl, buildLocalePageMeta, localizeBodyLinks } from './locale-router.js';
|
|
16
16
|
import { requireNativeAddon } from './native-addon.js';
|
|
17
17
|
import { writePrettyJsonFile } from './pretty-json.js';
|
|
18
|
+
import { emitPublicStaticAssets } from './public-static-assets.js';
|
|
18
19
|
import { filePathPatternFromChunk, isRouteBoundaryStem, listPublicPageUnits, parsePathPattern, unitBrowserPathPattern } from './route-path.js';
|
|
20
|
+
import { emitSiteFavicon, readSiteFaviconHeadHtml } from './site-favicon.js';
|
|
19
21
|
export const STATIC_DELIVERY_MANIFEST_SCHEMA = 'vmz.static.delivery_manifest.v0';
|
|
20
22
|
/**
|
|
21
23
|
* @param {string} distDir
|
|
@@ -32,6 +34,9 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
32
34
|
if (!fs.existsSync(domPath)) {
|
|
33
35
|
throw new Error(`emitWebStatic: missing ${domPath} — run vmz build first`);
|
|
34
36
|
}
|
|
37
|
+
emitSiteFavicon(distDir, { projectRoot: opts.projectRoot });
|
|
38
|
+
const faviconHead = readSiteFaviconHeadHtml(distDir);
|
|
39
|
+
const publicAssets = emitPublicStaticAssets(distDir, { projectRoot: opts.projectRoot });
|
|
35
40
|
const host = await createRenderHost(distDir, { strictDeployment: true, preload: 'none' });
|
|
36
41
|
const { renderToString, renderToStream } = host;
|
|
37
42
|
const pageCatalog = listPageClientFiles(distDir);
|
|
@@ -135,6 +140,7 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
135
140
|
props,
|
|
136
141
|
meta: gen.meta,
|
|
137
142
|
cssEntry: readCssEntry(distDir),
|
|
143
|
+
headExtraHtml: faviconHead,
|
|
138
144
|
});
|
|
139
145
|
fs.writeFileSync(absHtml, html, 'utf8');
|
|
140
146
|
generations.push({
|
|
@@ -166,6 +172,7 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
166
172
|
},
|
|
167
173
|
cssEntry: readCssEntry(distDir),
|
|
168
174
|
isErrorDocument: true,
|
|
175
|
+
headExtraHtml: faviconHead,
|
|
169
176
|
});
|
|
170
177
|
fs.writeFileSync(path.join(distDir, '404.html'), notFoundHtml, 'utf8');
|
|
171
178
|
const sitemap = buildSitemap(origin, generations);
|
|
@@ -216,6 +223,12 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
216
223
|
sitemap: 'sitemap.xml',
|
|
217
224
|
robots: 'robots.txt',
|
|
218
225
|
},
|
|
226
|
+
publicAssets: {
|
|
227
|
+
schema: publicAssets.schema,
|
|
228
|
+
status: publicAssets.status,
|
|
229
|
+
fileCount: publicAssets.fileCount ?? 0,
|
|
230
|
+
source: publicAssets.source || null,
|
|
231
|
+
},
|
|
219
232
|
};
|
|
220
233
|
const digest = sha256Hex(canonicalJson(manifest));
|
|
221
234
|
manifest.manifestDigest = digest;
|
|
@@ -239,6 +252,7 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
239
252
|
skipped,
|
|
240
253
|
digest: manifest.manifestDigest,
|
|
241
254
|
assets: assets.manifest,
|
|
255
|
+
publicAssets,
|
|
242
256
|
cdnPolicy: cdn.policy,
|
|
243
257
|
cdnAdapters: cdn.adapters,
|
|
244
258
|
};
|
|
@@ -503,6 +517,7 @@ function readCssEntry(distDir) {
|
|
|
503
517
|
* meta: { title: string, description: string, canonical: string, robots: string, lang: string, dir?: string, alternates?: Array<{ hreflang: string, href: string }> },
|
|
504
518
|
* cssEntry: string | null,
|
|
505
519
|
* isErrorDocument?: boolean,
|
|
520
|
+
* headExtraHtml?: string,
|
|
506
521
|
* }} input
|
|
507
522
|
*/
|
|
508
523
|
function wrapDocument(input) {
|
|
@@ -530,6 +545,7 @@ function wrapDocument(input) {
|
|
|
530
545
|
// napi Option<String>: omit/undefined = None; null is rejected as String
|
|
531
546
|
...(input.cssEntry ? { cssEntry: String(input.cssEntry) } : {}),
|
|
532
547
|
isErrorDocument: !!input.isErrorDocument,
|
|
548
|
+
...(input.headExtraHtml ? { headExtraHtml: String(input.headExtraHtml) } : {}),
|
|
533
549
|
});
|
|
534
550
|
}
|
|
535
551
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vmz/vmz",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "VMZ Node toolchain — N-API workspace session + CLI (publish name @vmz/vmz)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -48,15 +48,15 @@
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@vmz/core": "0.1.
|
|
52
|
-
"@vmz/plugin": "0.1.
|
|
53
|
-
"@vmz/protocol": "0.1.
|
|
51
|
+
"@vmz/core": "0.1.14",
|
|
52
|
+
"@vmz/plugin": "0.1.14",
|
|
53
|
+
"@vmz/protocol": "0.1.14",
|
|
54
54
|
"jiti": "^2.6.1",
|
|
55
55
|
"json5": "^2.2.3"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@vmz/plugin-markdown-it": "0.1.
|
|
59
|
-
"@vmz/test": "0.1.
|
|
58
|
+
"@vmz/plugin-markdown-it": "0.1.14",
|
|
59
|
+
"@vmz/test": "0.1.14",
|
|
60
60
|
"typescript": "^5.8.3"
|
|
61
61
|
},
|
|
62
62
|
"peerDependenciesMeta": {
|
|
@@ -90,12 +90,12 @@
|
|
|
90
90
|
"cli"
|
|
91
91
|
],
|
|
92
92
|
"optionalDependencies": {
|
|
93
|
-
"@vmz/vmz-win32-x64": "0.1.
|
|
94
|
-
"@vmz/vmz-win32-arm64": "0.1.
|
|
95
|
-
"@vmz/vmz-darwin-x64": "0.1.
|
|
96
|
-
"@vmz/vmz-darwin-arm64": "0.1.
|
|
97
|
-
"@vmz/vmz-linux-x64": "0.1.
|
|
98
|
-
"@vmz/vmz-linux-arm64": "0.1.
|
|
93
|
+
"@vmz/vmz-win32-x64": "0.1.14",
|
|
94
|
+
"@vmz/vmz-win32-arm64": "0.1.14",
|
|
95
|
+
"@vmz/vmz-darwin-x64": "0.1.14",
|
|
96
|
+
"@vmz/vmz-darwin-arm64": "0.1.14",
|
|
97
|
+
"@vmz/vmz-linux-x64": "0.1.14",
|
|
98
|
+
"@vmz/vmz-linux-arm64": "0.1.14"
|
|
99
99
|
},
|
|
100
100
|
"publishConfig": {
|
|
101
101
|
"access": "public"
|