@vmz/vmz 0.1.9 → 0.1.10
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/cli.js +6 -8
- package/dist/content-addressed-assets.d.ts +7 -1
- package/dist/content-addressed-assets.js +107 -32
- package/dist/index.d.ts +10 -0
- package/dist/index.js +28 -1
- package/dist/static-emit.js +53 -3
- package/package.json +12 -12
package/dist/cli.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Node CLI command implementations .
|
|
4
4
|
*/
|
|
5
5
|
import { spawn } from 'node:child_process';
|
|
6
|
-
import {
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
8
|
-
import { HOST_PROTOCOL, createWorkspace, getProtocolVersions, resolveCoreRuntimeDist, resolveNativePath } from './index.js';
|
|
8
|
+
import { HOST_PROTOCOL, createWorkspace, getProtocolVersions, materializeServeHostRuntime, resolveCoreRuntimeDist, resolveNativePath, } from './index.js';
|
|
9
9
|
import { createDevSession } from './dev-session.js';
|
|
10
10
|
import { gateGlobalProjectCommand, getInvocationContext, isGlobalAllowedCommand } from './invocation.js';
|
|
11
11
|
import { log } from './log.js';
|
|
@@ -501,14 +501,12 @@ async function cmdServe(args) {
|
|
|
501
501
|
});
|
|
502
502
|
const hostJs = path.join(outDir, 'vmz-serve-host.mjs');
|
|
503
503
|
if (!existsSync(hostJs)) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
if (src && existsSync(src)) {
|
|
507
|
-
copyFileSync(src, hostJs);
|
|
504
|
+
try {
|
|
505
|
+
materializeServeHostRuntime(outDir);
|
|
508
506
|
log.info(`materialized ${hostJs} from @vmz/core (release builds omit it)`);
|
|
509
507
|
}
|
|
510
|
-
|
|
511
|
-
log.error(`missing ${hostJs} — run \`vmz build\` (without --release) or ensure @vmz/core is installed`);
|
|
508
|
+
catch (err) {
|
|
509
|
+
log.error(`missing ${hostJs} — run \`vmz build\` (without --release) or ensure @vmz/core is installed (${err instanceof Error ? err.message : err})`);
|
|
512
510
|
return 1;
|
|
513
511
|
}
|
|
514
512
|
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/**
|
|
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
5
|
*/
|
|
6
6
|
export declare const CONTENT_ADDRESSED_ASSETS_SCHEMA = "vmz.content_addressed_assets.v0";
|
|
7
|
+
/**
|
|
8
|
+
* Rewrite relative `@import "./foo.css"` to hashed paths under assets/.
|
|
9
|
+
* @param {string} cssText
|
|
10
|
+
* @param {Record<string, string>} rewrites logical (no leading slash) or `/logical` → `assets/hash.ext`
|
|
11
|
+
*/
|
|
12
|
+
export declare function rewriteCssImports(cssText: any, rewrites: any): any;
|
|
7
13
|
/**
|
|
8
14
|
* Emit `assets/<sha256>.<ext>` copies and rewrite HTML href/src to hashed URLs.
|
|
9
15
|
* @param {string} distDir
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
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
5
|
*/
|
|
6
6
|
// @ts-nocheck
|
|
7
7
|
import crypto from 'node:crypto';
|
|
@@ -16,11 +16,33 @@ const DEFAULT_CANDIDATES = [
|
|
|
16
16
|
'entry-event.js',
|
|
17
17
|
'vmz.css',
|
|
18
18
|
'vmz-designs.css',
|
|
19
|
+
'vmz-style.css',
|
|
19
20
|
'vmz-dom.js',
|
|
20
21
|
'vmz-runtime.js',
|
|
21
22
|
'vmz-http.js',
|
|
22
23
|
'vmz-client-nav.js',
|
|
23
24
|
];
|
|
25
|
+
/** CSS files that may @import other logical CSS; processed after leaf CSS is hashed. */
|
|
26
|
+
const CSS_AGGREGATORS = new Set(['vmz.css']);
|
|
27
|
+
const CSS_IMPORT_RE = /@import\s*(?:url\()?['"]?(\.\/)?([^'")\s;]+)['"]?\)?/gi;
|
|
28
|
+
/**
|
|
29
|
+
* Rewrite relative `@import "./foo.css"` to hashed paths under assets/.
|
|
30
|
+
* @param {string} cssText
|
|
31
|
+
* @param {Record<string, string>} rewrites logical (no leading slash) or `/logical` → `assets/hash.ext`
|
|
32
|
+
*/
|
|
33
|
+
export function rewriteCssImports(cssText, rewrites) {
|
|
34
|
+
return cssText.replace(CSS_IMPORT_RE, (match, _dot, target) => {
|
|
35
|
+
const logical = String(target || '').replace(/^\.\//, '');
|
|
36
|
+
if (!logical)
|
|
37
|
+
return match;
|
|
38
|
+
const hashed = rewrites[logical] || rewrites[`/${logical}`] || rewrites[`assets/${logical}`];
|
|
39
|
+
if (!hashed)
|
|
40
|
+
return match;
|
|
41
|
+
const rel = hashed.startsWith('/') ? hashed.slice(1) : hashed;
|
|
42
|
+
const sibling = rel.startsWith('assets/') ? `./${path.basename(rel)}` : `./${rel}`;
|
|
43
|
+
return `@import"${sibling}"`;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
24
46
|
/**
|
|
25
47
|
* Emit `assets/<sha256>.<ext>` copies and rewrite HTML href/src to hashed URLs.
|
|
26
48
|
* @param {string} distDir
|
|
@@ -38,36 +60,24 @@ export function emitContentAddressedAssets(distDir, opts = {}) {
|
|
|
38
60
|
const objects = [];
|
|
39
61
|
/** @type {Record<string, string>} */
|
|
40
62
|
const rewrites = {};
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
63
|
+
const ordered = orderCandidates(candidates);
|
|
64
|
+
for (const rel of ordered) {
|
|
65
|
+
ingestCandidate(abs, rel, rewrites, objects, { transform: null });
|
|
66
|
+
}
|
|
67
|
+
// Aggregator CSS (vmz.css) must import hashed leaf files — rewrite then hash.
|
|
68
|
+
for (const rel of ordered) {
|
|
69
|
+
if (!CSS_AGGREGATORS.has(rel))
|
|
45
70
|
continue;
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
else {
|
|
56
|
-
// Cross-release reuse: identical digest must not be rewritten.
|
|
57
|
-
const existing = sha256Hex(fs.readFileSync(dest));
|
|
58
|
-
if (existing !== digest) {
|
|
59
|
-
throw new Error(`content-address collision at ${assetRel}`);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
objects.push({
|
|
63
|
-
logicalPath: logical,
|
|
64
|
-
assetPath: assetRel,
|
|
65
|
-
digest,
|
|
66
|
-
bytes: buf.length,
|
|
67
|
-
immutable: true,
|
|
71
|
+
const src = path.join(abs, rel);
|
|
72
|
+
if (!fs.existsSync(src))
|
|
73
|
+
continue;
|
|
74
|
+
const rewritten = rewriteCssImports(fs.readFileSync(src, 'utf8'), rewrites);
|
|
75
|
+
removeLogicalObject(objects, rel);
|
|
76
|
+
delete rewrites[`/${rel}`];
|
|
77
|
+
delete rewrites[rel];
|
|
78
|
+
ingestCandidate(abs, rel, rewrites, objects, {
|
|
79
|
+
transform: () => Buffer.from(rewritten, 'utf8'),
|
|
68
80
|
});
|
|
69
|
-
rewrites[`/${logical}`] = `/${assetRel}`;
|
|
70
|
-
rewrites[logical] = assetRel;
|
|
71
81
|
}
|
|
72
82
|
objects.sort((a, b) => (a.logicalPath < b.logicalPath ? -1 : a.logicalPath > b.logicalPath ? 1 : 0));
|
|
73
83
|
let rewrittenHtml = 0;
|
|
@@ -89,6 +99,74 @@ export function emitContentAddressedAssets(distDir, opts = {}) {
|
|
|
89
99
|
writePrettyJsonFile(outPath, manifest);
|
|
90
100
|
return { manifest, assetsDir, rewrites, manifestPath: outPath };
|
|
91
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* @param {string[]} candidates
|
|
104
|
+
*/
|
|
105
|
+
function orderCandidates(candidates) {
|
|
106
|
+
const set = new Set(candidates.map((c) => String(c).replace(/\\/g, '/').replace(/^\//, '')));
|
|
107
|
+
/** @type {string[]} */
|
|
108
|
+
const out = [];
|
|
109
|
+
for (const name of DEFAULT_CANDIDATES) {
|
|
110
|
+
if (set.has(name) && !CSS_AGGREGATORS.has(name))
|
|
111
|
+
out.push(name);
|
|
112
|
+
}
|
|
113
|
+
for (const name of [...set].sort()) {
|
|
114
|
+
if (!CSS_AGGREGATORS.has(name) && !out.includes(name))
|
|
115
|
+
out.push(name);
|
|
116
|
+
}
|
|
117
|
+
if (set.has('vmz.css'))
|
|
118
|
+
out.push('vmz.css');
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* @param {Array<Record<string, any>>} objects
|
|
123
|
+
* @param {string} logical
|
|
124
|
+
*/
|
|
125
|
+
function removeLogicalObject(objects, logical) {
|
|
126
|
+
const idx = objects.findIndex((o) => o.logicalPath === logical);
|
|
127
|
+
if (idx >= 0)
|
|
128
|
+
objects.splice(idx, 1);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* @param {string} absDist
|
|
132
|
+
* @param {string} rel
|
|
133
|
+
* @param {Record<string, string>} rewrites
|
|
134
|
+
* @param {Array<Record<string, any>>} objects
|
|
135
|
+
* @param {{ transform?: ((buf: Buffer) => Buffer) | null }} opts
|
|
136
|
+
*/
|
|
137
|
+
function ingestCandidate(absDist, rel, rewrites, objects, opts) {
|
|
138
|
+
const logical = String(rel).replace(/\\/g, '/').replace(/^\//, '');
|
|
139
|
+
const src = path.join(absDist, ...logical.split('/'));
|
|
140
|
+
if (!fs.existsSync(src) || !fs.statSync(src).isFile())
|
|
141
|
+
return;
|
|
142
|
+
let buf = fs.readFileSync(src);
|
|
143
|
+
if (typeof opts.transform === 'function') {
|
|
144
|
+
buf = opts.transform(buf);
|
|
145
|
+
}
|
|
146
|
+
const digest = sha256Hex(buf);
|
|
147
|
+
const ext = path.extname(logical) || '';
|
|
148
|
+
const assetRel = `assets/${digest}${ext}`;
|
|
149
|
+
const dest = path.join(absDist, ...assetRel.split('/'));
|
|
150
|
+
if (!fs.existsSync(dest)) {
|
|
151
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
152
|
+
fs.writeFileSync(dest, buf);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
const existing = sha256Hex(fs.readFileSync(dest));
|
|
156
|
+
if (existing !== digest) {
|
|
157
|
+
throw new Error(`content-address collision at ${assetRel}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
objects.push({
|
|
161
|
+
logicalPath: logical,
|
|
162
|
+
assetPath: assetRel,
|
|
163
|
+
digest,
|
|
164
|
+
bytes: buf.length,
|
|
165
|
+
immutable: true,
|
|
166
|
+
});
|
|
167
|
+
rewrites[`/${logical}`] = `/${assetRel}`;
|
|
168
|
+
rewrites[logical] = assetRel;
|
|
169
|
+
}
|
|
92
170
|
/**
|
|
93
171
|
* Resolve an immutable object by digest under dist/assets (cross-source reuse).
|
|
94
172
|
* @param {string} distDir
|
|
@@ -124,7 +202,6 @@ export function assertSharedAssetPath(distDir, a, b, ext = '.js') {
|
|
|
124
202
|
const rel = `assets/${da}${ext}`;
|
|
125
203
|
const dest = path.join(distDir, ...rel.split('/'));
|
|
126
204
|
fs.writeFileSync(dest, typeof a === 'string' ? Buffer.from(a) : a);
|
|
127
|
-
// Second write of identical bytes must be reuse, not fork.
|
|
128
205
|
fs.writeFileSync(dest, typeof b === 'string' ? Buffer.from(b) : b);
|
|
129
206
|
const again = resolveAssetByDigest(distDir, da, ext);
|
|
130
207
|
if (!again || again.assetPath !== rel) {
|
|
@@ -139,7 +216,6 @@ function collectCandidates(distDir) {
|
|
|
139
216
|
if (fs.existsSync(path.join(distDir, name)))
|
|
140
217
|
out.push(name);
|
|
141
218
|
}
|
|
142
|
-
// Include top-level *.client.js and pages/**/*.client.js referenced by resume.
|
|
143
219
|
walk(distDir, distDir, (rel) => {
|
|
144
220
|
if (/\.client\.js$/i.test(rel))
|
|
145
221
|
out.push(rel);
|
|
@@ -173,7 +249,6 @@ function rewriteHtmlReferences(distDir, rewrites) {
|
|
|
173
249
|
let text = fs.readFileSync(file, 'utf8');
|
|
174
250
|
let next = text;
|
|
175
251
|
for (const [from, to] of pairs) {
|
|
176
|
-
// href="/x" src="/x" and unquoted variants in attributes
|
|
177
252
|
next = next.split(from).join(to);
|
|
178
253
|
}
|
|
179
254
|
if (next !== text) {
|
package/dist/index.d.ts
CHANGED
|
@@ -53,6 +53,14 @@ export declare function handshake(host?: {
|
|
|
53
53
|
* @returns {string | null}
|
|
54
54
|
*/
|
|
55
55
|
export declare function resolveCoreRuntimeDist(): string;
|
|
56
|
+
/** Runtime companions required by dist/vmz-serve-host.mjs relative imports. */
|
|
57
|
+
export declare const SERVE_HOST_RUNTIME_FILES: string[][];
|
|
58
|
+
/**
|
|
59
|
+
* Copy serve-host + registry bootstrap modules from `@vmz/core` into app outDir.
|
|
60
|
+
* @param {string} outDir
|
|
61
|
+
* @param {string} [coreDist]
|
|
62
|
+
*/
|
|
63
|
+
export declare function materializeServeHostRuntime(outDir: any, coreDist?: string): void;
|
|
56
64
|
/**
|
|
57
65
|
* @typedef {object} WorkspaceOptions
|
|
58
66
|
* @property {string} root
|
|
@@ -234,6 +242,8 @@ declare const _default: {
|
|
|
234
242
|
expectedProtocol: typeof expectedProtocol;
|
|
235
243
|
resolveNativePath: typeof resolveNativePath;
|
|
236
244
|
resolveCoreRuntimeDist: typeof resolveCoreRuntimeDist;
|
|
245
|
+
materializeServeHostRuntime: typeof materializeServeHostRuntime;
|
|
246
|
+
SERVE_HOST_RUNTIME_FILES: string[][];
|
|
237
247
|
loadNative: typeof loadNative;
|
|
238
248
|
getProtocolVersions: typeof getProtocolVersions;
|
|
239
249
|
handshake: typeof handshake;
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Coarse-grained only — no transform hooks / per-AST callbacks.
|
|
5
5
|
*/
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
7
|
-
import { existsSync } from 'node:fs';
|
|
7
|
+
import { copyFileSync, existsSync } from 'node:fs';
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { fileURLToPath } from 'node:url';
|
|
10
10
|
import { materializeWechatPackaging } from './wechat-packaging.js';
|
|
@@ -144,6 +144,31 @@ export function resolveCoreRuntimeDist() {
|
|
|
144
144
|
return nested;
|
|
145
145
|
return null;
|
|
146
146
|
}
|
|
147
|
+
/** Runtime companions required by dist/vmz-serve-host.mjs relative imports. */
|
|
148
|
+
export const SERVE_HOST_RUNTIME_FILES = [
|
|
149
|
+
['serve-host.mjs', 'vmz-serve-host.mjs'],
|
|
150
|
+
['list-client-components.js', 'list-client-components.js'],
|
|
151
|
+
['deployment-registry.js', 'deployment-registry.js'],
|
|
152
|
+
['render-host.js', 'render-host.js'],
|
|
153
|
+
];
|
|
154
|
+
/**
|
|
155
|
+
* Copy serve-host + registry bootstrap modules from `@vmz/core` into app outDir.
|
|
156
|
+
* @param {string} outDir
|
|
157
|
+
* @param {string} [coreDist]
|
|
158
|
+
*/
|
|
159
|
+
export function materializeServeHostRuntime(outDir, coreDist = resolveCoreRuntimeDist()) {
|
|
160
|
+
if (!coreDist) {
|
|
161
|
+
throw new Error('materializeServeHostRuntime: @vmz/core dist not found');
|
|
162
|
+
}
|
|
163
|
+
for (const [srcName, outName] of SERVE_HOST_RUNTIME_FILES) {
|
|
164
|
+
const src = path.join(coreDist, srcName);
|
|
165
|
+
const dst = path.join(outDir, outName);
|
|
166
|
+
if (!existsSync(src)) {
|
|
167
|
+
throw new Error(`materializeServeHostRuntime: missing ${src}`);
|
|
168
|
+
}
|
|
169
|
+
copyFileSync(src, dst);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
147
172
|
/**
|
|
148
173
|
* @typedef {object} WorkspaceOptions
|
|
149
174
|
* @property {string} root
|
|
@@ -458,6 +483,8 @@ export default {
|
|
|
458
483
|
expectedProtocol,
|
|
459
484
|
resolveNativePath,
|
|
460
485
|
resolveCoreRuntimeDist,
|
|
486
|
+
materializeServeHostRuntime,
|
|
487
|
+
SERVE_HOST_RUNTIME_FILES,
|
|
461
488
|
loadNative,
|
|
462
489
|
getProtocolVersions,
|
|
463
490
|
handshake,
|
package/dist/static-emit.js
CHANGED
|
@@ -7,7 +7,8 @@ import crypto from 'node:crypto';
|
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { pathToFileURL } from 'node:url';
|
|
10
|
-
import {
|
|
10
|
+
import { createRenderHost } from '@vmz/core/render-host';
|
|
11
|
+
import { listClientComponentsSync } from '@vmz/core/component-registry';
|
|
11
12
|
import { emitCdnPolicy } from './cdn-policy.js';
|
|
12
13
|
import { emitContentAddressedAssets } from './content-addressed-assets.js';
|
|
13
14
|
import { absoluteUrl, buildLocalePageMeta, localizeBodyLinks } from './locale-router.js';
|
|
@@ -30,8 +31,8 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
30
31
|
if (!fs.existsSync(domPath)) {
|
|
31
32
|
throw new Error(`emitWebStatic: missing ${domPath} — run vmz build first`);
|
|
32
33
|
}
|
|
33
|
-
const
|
|
34
|
-
|
|
34
|
+
const host = await createRenderHost(distDir, { strictDeployment: true, preload: 'none' });
|
|
35
|
+
const { renderToString, renderToStream } = host;
|
|
35
36
|
const pageCatalog = listPageClientFiles(distDir);
|
|
36
37
|
/** @type {Array<{
|
|
37
38
|
* routeId: string,
|
|
@@ -100,6 +101,7 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
100
101
|
}
|
|
101
102
|
const meta = await resolvePageMeta(Page, { params, props, pathname: pattern, origin });
|
|
102
103
|
const layoutChain = resolveLayoutChain(distDir, page.chunkId);
|
|
104
|
+
await host.ensureComponents([page.chunkId, ...layoutChain]);
|
|
103
105
|
let bodyHtml = '';
|
|
104
106
|
for await (const chunk of renderToStream(Page, props, {})) {
|
|
105
107
|
bodyHtml += chunk;
|
|
@@ -217,6 +219,7 @@ export async function emitWebStatic(distDir, opts = {}) {
|
|
|
217
219
|
const digest = sha256Hex(canonicalJson(manifest));
|
|
218
220
|
manifest.manifestDigest = digest;
|
|
219
221
|
writePrettyJsonFile(path.join(vmzDir, 'static-delivery-manifest.json'), manifest);
|
|
222
|
+
emitStaticClientEntries(distDir, pageCatalog);
|
|
220
223
|
const assets = emitContentAddressedAssets(distDir);
|
|
221
224
|
manifest.contentAddressedAssets = {
|
|
222
225
|
schema: assets.manifest.schema,
|
|
@@ -558,3 +561,50 @@ function buildSitemap(_origin, generations) {
|
|
|
558
561
|
}
|
|
559
562
|
return native.generateSitemapXml(urls);
|
|
560
563
|
}
|
|
564
|
+
/**
|
|
565
|
+
* Static CDN must ship entry-client/event like serve-host (content-addressed + HTML rewrite).
|
|
566
|
+
* @param {string} distDir
|
|
567
|
+
* @param {Array<{ chunkId: string }>} pageCatalog
|
|
568
|
+
*/
|
|
569
|
+
function emitStaticClientEntries(distDir, pageCatalog) {
|
|
570
|
+
const componentEntries = listClientComponentsSync(distDir, { strict: true });
|
|
571
|
+
const indexChunk = pageCatalog.find((p) => p.chunkId === 'pages/index')?.chunkId || pageCatalog[0]?.chunkId || 'pages/index';
|
|
572
|
+
const resumeEntries = loadPageResumeEntriesSync(distDir, indexChunk);
|
|
573
|
+
const lazySet = new Set(resumeEntries
|
|
574
|
+
.filter((e) => isEventResumeStrategy(e.strategy))
|
|
575
|
+
.map((e) => e.component)
|
|
576
|
+
.filter(Boolean));
|
|
577
|
+
const eager = componentEntries.filter((e) => !lazySet.has(e.name));
|
|
578
|
+
const lazy = componentEntries.filter((e) => lazySet.has(e.name));
|
|
579
|
+
const native = requireNativeAddon();
|
|
580
|
+
if (typeof native.generateServeEntryClient !== 'function') {
|
|
581
|
+
throw new Error('vmz native addon missing generateServeEntryClient — rebuild with `pnpm napi:build`');
|
|
582
|
+
}
|
|
583
|
+
fs.writeFileSync(path.join(distDir, 'entry-client.js'), native.generateServeEntryClient(eager, lazy, ''), 'utf8');
|
|
584
|
+
if (typeof native.generateServeEntryEvent === 'function') {
|
|
585
|
+
fs.writeFileSync(path.join(distDir, 'entry-event.js'), native.generateServeEntryEvent(''), 'utf8');
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* @param {string} distDir
|
|
590
|
+
* @param {string} chunkId
|
|
591
|
+
*/
|
|
592
|
+
function loadPageResumeEntriesSync(distDir, chunkId) {
|
|
593
|
+
try {
|
|
594
|
+
const dep = JSON.parse(fs.readFileSync(path.join(distDir, 'vmz-deployment.json'), 'utf8'));
|
|
595
|
+
const units = Array.isArray(dep.units) ? dep.units : [];
|
|
596
|
+
const page = units.find((u) => u.chunkId === chunkId) || units.find((u) => u.chunkId === 'pages/index') || units.find((u) => u.kind === 'page');
|
|
597
|
+
const entries = Array.isArray(page?.resumeEntries) ? page.resumeEntries : [];
|
|
598
|
+
return entries.map((e) => ({
|
|
599
|
+
component: String(e.component || ''),
|
|
600
|
+
strategy: String(e.strategy || ''),
|
|
601
|
+
}));
|
|
602
|
+
}
|
|
603
|
+
catch {
|
|
604
|
+
return [];
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
/** @param {string} strategy */
|
|
608
|
+
function isEventResumeStrategy(strategy) {
|
|
609
|
+
return strategy === 'event' || strategy === 'click' || String(strategy).startsWith('event:');
|
|
610
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vmz/vmz",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
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.10",
|
|
52
|
+
"@vmz/plugin": "0.1.10",
|
|
53
|
+
"@vmz/protocol": "0.1.10",
|
|
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.10",
|
|
59
|
+
"@vmz/test": "0.1.10",
|
|
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.10",
|
|
94
|
+
"@vmz/vmz-win32-arm64": "0.1.10",
|
|
95
|
+
"@vmz/vmz-darwin-x64": "0.1.10",
|
|
96
|
+
"@vmz/vmz-darwin-arm64": "0.1.10",
|
|
97
|
+
"@vmz/vmz-linux-x64": "0.1.10",
|
|
98
|
+
"@vmz/vmz-linux-arm64": "0.1.10"
|
|
99
99
|
},
|
|
100
100
|
"publishConfig": {
|
|
101
101
|
"access": "public"
|