@vmz/vmz 0.1.13 → 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 +18 -7
- package/dist/cdn-policy.js +5 -4
- package/dist/cli.js +106 -38
- package/dist/content-addressed-assets.d.ts +23 -2
- package/dist/content-addressed-assets.js +178 -32
- package/dist/delivery-profile.d.ts +30 -2
- package/dist/delivery-profile.js +139 -5
- package/dist/dev-session.d.ts +1 -0
- package/dist/dev-session.js +269 -65
- package/dist/dev-watch-roots.d.ts +80 -0
- package/dist/dev-watch-roots.js +245 -0
- package/dist/document-build.d.ts +2 -1
- package/dist/document-build.js +104 -82
- package/dist/document-cmd.js +2 -9
- package/dist/document-enrich.d.ts +2 -1
- package/dist/document-enrich.js +15 -4
- package/dist/document-integrate.js +29 -21
- package/dist/document-layout-render.d.ts +20 -0
- package/dist/document-layout-render.js +87 -0
- package/dist/document-routing-config.d.ts +13 -0
- package/dist/document-routing-config.js +40 -0
- package/dist/embedded-packaging.js +2 -1
- package/dist/index.d.ts +18 -2
- package/dist/index.js +63 -4
- package/dist/locale-check.js +28 -61
- package/dist/locale-cmd.js +10 -42
- package/dist/locale-route-emit.d.ts +4 -1
- package/dist/locale-route-emit.js +7 -32
- package/dist/locale-router.js +26 -8
- package/dist/native-addon.d.ts +9 -0
- package/dist/native-addon.js +84 -0
- package/dist/pack.js +3 -2
- package/dist/pretty-json.d.ts +19 -0
- package/dist/pretty-json.js +43 -0
- package/dist/production-observability.js +3 -2
- package/dist/production-test-pack.js +4 -3
- package/dist/public-static-assets.d.ts +24 -0
- package/dist/public-static-assets.js +140 -0
- package/dist/release-pack.js +5 -18
- package/dist/route-path.d.ts +35 -0
- package/dist/route-path.js +77 -0
- package/dist/server-artifact.js +4 -3
- package/dist/site-delivery.js +4 -3
- 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 +134 -97
- package/dist/test-cmd.js +2 -1
- package/dist/wechat-packaging.d.ts +22 -0
- package/dist/wechat-packaging.js +59 -0
- package/package.json +12 -12
package/dist/dev-session.js
CHANGED
|
@@ -14,9 +14,10 @@ import { spawn } from 'node:child_process';
|
|
|
14
14
|
import { existsSync } from 'node:fs';
|
|
15
15
|
import path from 'node:path';
|
|
16
16
|
import { buildIntegratedDocuments, projectHasDocuments } from './document-integrate.js';
|
|
17
|
-
import { createWorkspace } from './index.js';
|
|
17
|
+
import { createWorkspace, resolveNativePath } from './index.js';
|
|
18
18
|
import { emitLocaleRuntimeModules, localeHasErrors } from './locale-check.js';
|
|
19
19
|
import { log } from './log.js';
|
|
20
|
+
import { coalesceRootBurst, collectDevWatchRoots, classifyWatchRoot, isDependencyPath, mergeDirtySets } from './dev-watch-roots.js';
|
|
20
21
|
import { diffFingerprints, fileFingerprintMap } from './watch-diff.js';
|
|
21
22
|
/**
|
|
22
23
|
* @typedef {object} DevSessionOptions
|
|
@@ -25,6 +26,7 @@ import { diffFingerprints, fileFingerprintMap } from './watch-diff.js';
|
|
|
25
26
|
* @property {string} [host]
|
|
26
27
|
* @property {number} [port]
|
|
27
28
|
* @property {number} [pollMs]
|
|
29
|
+
* @property {'browser' | 'mini-program-wechat'} [target]
|
|
28
30
|
* @property {AbortSignal} [signal]
|
|
29
31
|
* @property {typeof createWorkspace} [createWorkspaceFn]
|
|
30
32
|
* @property {(opts: { project: string, outDir: string, host: string, port: number }) => import('node:child_process').ChildProcess} [spawnHostFn]
|
|
@@ -39,6 +41,7 @@ export function createDevSession(options) {
|
|
|
39
41
|
const host = options.host ?? '127.0.0.1';
|
|
40
42
|
const port = options.port ?? 5173;
|
|
41
43
|
const pollMs = Math.max(50, options.pollMs ?? 300);
|
|
44
|
+
const wechatPreview = options.target === 'mini-program-wechat';
|
|
42
45
|
const createWs = options.createWorkspaceFn ?? createWorkspace;
|
|
43
46
|
const spawnHost = options.spawnHostFn ?? defaultSpawnHost;
|
|
44
47
|
const softReload = options.softReloadFn ?? defaultSoftReload;
|
|
@@ -76,6 +79,33 @@ export function createDevSession(options) {
|
|
|
76
79
|
log.info(`${label} ok (${mode}; chunks=[${chunks}]; ${(report.emitted ?? []).length} emitted)`);
|
|
77
80
|
return true;
|
|
78
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Rewrite `dist/wechat` so WeChat DevTools (already open) recompiles WXSS.
|
|
84
|
+
* Preview is vendor compile, not the browser serve-host.
|
|
85
|
+
*/
|
|
86
|
+
function packWechatPreview() {
|
|
87
|
+
if (typeof ws.lowerMiniprogramWechatPackaging !== 'function') {
|
|
88
|
+
log.error('wechat pack: workspace missing lowerMiniprogramWechatPackaging');
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
let report;
|
|
92
|
+
try {
|
|
93
|
+
const raw = ws.lowerMiniprogramWechatPackaging();
|
|
94
|
+
report = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
log.error(`wechat pack failed: ${err}`);
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
log.diagnostics(report.diagnostics ?? []);
|
|
101
|
+
if (report.status !== 'ready') {
|
|
102
|
+
log.error(`wechat pack ${report.status || 'failed'}`);
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
const packRoot = report.packRoot || 'dist/wechat';
|
|
106
|
+
log.info(`wechat pack ok → ${path.join(project, packRoot)} (WeChat DevTools compiles WXSS here)`);
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
79
109
|
async function waitHostReady(timeoutMs = 8000) {
|
|
80
110
|
const start = Date.now();
|
|
81
111
|
while (Date.now() - start < timeoutMs) {
|
|
@@ -143,18 +173,38 @@ export function createDevSession(options) {
|
|
|
143
173
|
throw new Error('vmz dev: integrated document build failed');
|
|
144
174
|
}
|
|
145
175
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
176
|
+
if (wechatPreview) {
|
|
177
|
+
if (!packWechatPreview()) {
|
|
178
|
+
throw new Error('vmz dev: wechat pack failed');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
const hostJs = path.join(outDir, 'vmz-serve-host.mjs');
|
|
183
|
+
if (!existsSync(hostJs)) {
|
|
184
|
+
throw new Error(`vmz dev: missing ${hostJs}`);
|
|
185
|
+
}
|
|
186
|
+
child = spawnHost({ project, outDir, host, port });
|
|
187
|
+
await waitHostReady().catch((err) => {
|
|
188
|
+
log.warn(String(err));
|
|
189
|
+
});
|
|
149
190
|
}
|
|
150
|
-
child = spawnHost({ project, outDir, host, port });
|
|
151
|
-
await waitHostReady().catch((err) => {
|
|
152
|
-
log.warn(String(err));
|
|
153
|
-
});
|
|
154
191
|
const docsRoot = path.join(project, 'documents');
|
|
155
192
|
const localesRoot = path.join(project, 'locales');
|
|
156
|
-
const
|
|
157
|
-
|
|
193
|
+
const designsRoot = path.join(project, 'designs');
|
|
194
|
+
const watched = collectDevWatchRoots({ project, outDir });
|
|
195
|
+
/** @type {string[]} */
|
|
196
|
+
const watchRoots = [...watched.roots];
|
|
197
|
+
/** @type {string[]} */
|
|
198
|
+
let dependencyRoots = [...watched.dependencyRoots];
|
|
199
|
+
if (wechatPreview) {
|
|
200
|
+
log.info(`dev → WeChat DevTools (watching ${watchRoots.join(', ')}; keep dist/wechat open)`);
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
log.info(`dev → http://${host}:${port} (watching ${watchRoots.join(', ')})`);
|
|
204
|
+
}
|
|
205
|
+
if (dependencyRoots.length) {
|
|
206
|
+
log.info(`dev dependency watch roots (${dependencyRoots.length}): ${dependencyRoots.join(', ')}`);
|
|
207
|
+
}
|
|
158
208
|
/** @type {Map<string, Map<string, string>>} */
|
|
159
209
|
const fingerprints = new Map();
|
|
160
210
|
for (const root of watchRoots) {
|
|
@@ -166,18 +216,57 @@ export function createDevSession(options) {
|
|
|
166
216
|
};
|
|
167
217
|
signal?.addEventListener('abort', onAbort, { once: true });
|
|
168
218
|
/**
|
|
169
|
-
*
|
|
219
|
+
* Scan all watch roots into a batch. Does not update fingerprints.
|
|
170
220
|
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
221
|
+
function scanBatch() {
|
|
222
|
+
/** @type {{ srcChanged: string[], srcDeleted: string[], depChanged: string[], depDeleted: string[], designsChanged: string[], designsDeleted: string[], docsDirty: boolean, localesDirty: boolean, designsDirty: boolean }} */
|
|
223
|
+
const batch = {
|
|
224
|
+
srcChanged: [],
|
|
225
|
+
srcDeleted: [],
|
|
226
|
+
depChanged: [],
|
|
227
|
+
depDeleted: [],
|
|
228
|
+
designsChanged: [],
|
|
229
|
+
designsDeleted: [],
|
|
230
|
+
docsDirty: false,
|
|
231
|
+
localesDirty: false,
|
|
232
|
+
designsDirty: false,
|
|
233
|
+
};
|
|
234
|
+
const watchCtx = { src, docsRoot, localesRoot, designsRoot, dependencyRoots };
|
|
235
|
+
for (const root of watchRoots) {
|
|
236
|
+
const prev = fingerprints.get(root) || new Map();
|
|
237
|
+
const next = fileFingerprintMap(root);
|
|
177
238
|
const diff = diffFingerprints(prev, next);
|
|
178
239
|
if (!diff.changed.length && !diff.deleted.length)
|
|
179
|
-
|
|
180
|
-
|
|
240
|
+
continue;
|
|
241
|
+
const kind = classifyWatchRoot(root, watchCtx);
|
|
242
|
+
if (kind === 'src') {
|
|
243
|
+
batch.srcChanged.push(...diff.changed);
|
|
244
|
+
batch.srcDeleted.push(...diff.deleted);
|
|
245
|
+
}
|
|
246
|
+
else if (kind === 'locales') {
|
|
247
|
+
batch.localesDirty = true;
|
|
248
|
+
}
|
|
249
|
+
else if (kind === 'docs') {
|
|
250
|
+
batch.docsDirty = true;
|
|
251
|
+
}
|
|
252
|
+
else if (kind === 'designs') {
|
|
253
|
+
batch.designsDirty = true;
|
|
254
|
+
batch.designsChanged.push(...diff.changed);
|
|
255
|
+
batch.designsDeleted.push(...diff.deleted);
|
|
256
|
+
}
|
|
257
|
+
else if (kind === 'dep') {
|
|
258
|
+
batch.depChanged.push(...diff.changed);
|
|
259
|
+
batch.depDeleted.push(...diff.deleted);
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
262
|
+
batch.docsDirty = true;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return batch;
|
|
266
|
+
}
|
|
267
|
+
function commitFingerprints() {
|
|
268
|
+
for (const root of watchRoots) {
|
|
269
|
+
fingerprints.set(root, fileFingerprintMap(root));
|
|
181
270
|
}
|
|
182
271
|
}
|
|
183
272
|
try {
|
|
@@ -185,65 +274,125 @@ export function createDevSession(options) {
|
|
|
185
274
|
await sleep(pollMs);
|
|
186
275
|
if (stopped || signal?.aborted)
|
|
187
276
|
break;
|
|
188
|
-
if (child && child.exitCode != null) {
|
|
277
|
+
if (!wechatPreview && child && child.exitCode != null) {
|
|
189
278
|
log.warn(`serve-host exited (${child.exitCode}) — respawning…`);
|
|
190
279
|
child = spawnHost({ project, outDir, host, port });
|
|
191
280
|
await waitHostReady().catch(() => { });
|
|
192
281
|
continue;
|
|
193
282
|
}
|
|
194
|
-
|
|
195
|
-
let batch = { srcChanged: [], srcDeleted: [], docsDirty: false, localesDirty: false };
|
|
283
|
+
let batch;
|
|
196
284
|
try {
|
|
197
|
-
|
|
198
|
-
const prev = fingerprints.get(root) || new Map();
|
|
199
|
-
const next = fileFingerprintMap(root);
|
|
200
|
-
const diff = diffFingerprints(prev, next);
|
|
201
|
-
if (root === src) {
|
|
202
|
-
batch.srcChanged = diff.changed;
|
|
203
|
-
batch.srcDeleted = diff.deleted;
|
|
204
|
-
}
|
|
205
|
-
else if (root === localesRoot) {
|
|
206
|
-
if (diff.changed.length || diff.deleted.length)
|
|
207
|
-
batch.localesDirty = true;
|
|
208
|
-
}
|
|
209
|
-
else if (diff.changed.length || diff.deleted.length) {
|
|
210
|
-
batch.docsDirty = true;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
285
|
+
batch = scanBatch();
|
|
213
286
|
}
|
|
214
287
|
catch (err) {
|
|
215
288
|
log.warn('watch error:', err);
|
|
216
289
|
continue;
|
|
217
290
|
}
|
|
218
|
-
|
|
291
|
+
const srcDirty = batch.srcChanged.length + batch.srcDeleted.length;
|
|
292
|
+
const depDirty = batch.depChanged.length + batch.depDeleted.length;
|
|
293
|
+
const designsDirty = batch.designsDirty || batch.designsChanged.length + batch.designsDeleted.length;
|
|
294
|
+
if (!srcDirty && !depDirty && !batch.docsDirty && !batch.localesDirty && !designsDirty)
|
|
219
295
|
continue;
|
|
220
|
-
|
|
221
|
-
|
|
296
|
+
// Coalesce multi-file bursts without dropping the initial dirty set.
|
|
297
|
+
if (srcDirty > 1) {
|
|
298
|
+
const coalesced = await coalesceRootBurst(src, fingerprints, {
|
|
299
|
+
changed: batch.srcChanged,
|
|
300
|
+
deleted: batch.srcDeleted,
|
|
301
|
+
});
|
|
302
|
+
batch.srcChanged = coalesced.changed;
|
|
303
|
+
batch.srcDeleted = coalesced.deleted;
|
|
222
304
|
}
|
|
223
|
-
|
|
305
|
+
if (depDirty > 1) {
|
|
306
|
+
// Coalesce each dirty dependency root independently, then merge.
|
|
307
|
+
/** @type {{ changed: string[], deleted: string[] }} */
|
|
308
|
+
let acc = { changed: [...batch.depChanged], deleted: [...batch.depDeleted] };
|
|
309
|
+
for (const root of dependencyRoots) {
|
|
310
|
+
const prev = fingerprints.get(root) || new Map();
|
|
311
|
+
const next = fileFingerprintMap(root);
|
|
312
|
+
const peek = diffFingerprints(prev, next);
|
|
313
|
+
if (peek.changed.length + peek.deleted.length <= 1 && !acc.changed.some((f) => isDependencyPath(f, [root]))) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
const coalesced = await coalesceRootBurst(root, fingerprints, {
|
|
317
|
+
changed: acc.changed.filter((f) => isDependencyPath(f, [root])),
|
|
318
|
+
deleted: acc.deleted.filter((f) => isDependencyPath(f, [root])),
|
|
319
|
+
});
|
|
320
|
+
const others = {
|
|
321
|
+
changed: acc.changed.filter((f) => !isDependencyPath(f, [root])),
|
|
322
|
+
deleted: acc.deleted.filter((f) => !isDependencyPath(f, [root])),
|
|
323
|
+
};
|
|
324
|
+
acc = mergeDirtySets(others, coalesced);
|
|
325
|
+
}
|
|
326
|
+
batch.depChanged = acc.changed;
|
|
327
|
+
batch.depDeleted = acc.deleted;
|
|
328
|
+
}
|
|
329
|
+
else if (srcDirty === 1 || depDirty === 1) {
|
|
224
330
|
await sleep(200);
|
|
225
331
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
332
|
+
// Refresh residual dirty after settle (without discarding coalesced sets).
|
|
333
|
+
const residual = scanBatch();
|
|
334
|
+
{
|
|
335
|
+
const srcMerged = mergeDirtySets({ changed: batch.srcChanged, deleted: batch.srcDeleted }, { changed: residual.srcChanged, deleted: residual.srcDeleted });
|
|
336
|
+
batch.srcChanged = srcMerged.changed;
|
|
337
|
+
batch.srcDeleted = srcMerged.deleted;
|
|
338
|
+
const depMerged = mergeDirtySets({ changed: batch.depChanged, deleted: batch.depDeleted }, { changed: residual.depChanged, deleted: residual.depDeleted });
|
|
339
|
+
batch.depChanged = depMerged.changed;
|
|
340
|
+
batch.depDeleted = depMerged.deleted;
|
|
341
|
+
batch.docsDirty = batch.docsDirty || residual.docsDirty;
|
|
342
|
+
batch.localesDirty = batch.localesDirty || residual.localesDirty;
|
|
343
|
+
batch.designsDirty = batch.designsDirty || residual.designsDirty;
|
|
344
|
+
const designsMerged = mergeDirtySets({ changed: batch.designsChanged, deleted: batch.designsDeleted }, { changed: residual.designsChanged, deleted: residual.designsDeleted });
|
|
345
|
+
batch.designsChanged = designsMerged.changed;
|
|
346
|
+
batch.designsDeleted = designsMerged.deleted;
|
|
347
|
+
}
|
|
348
|
+
commitFingerprints();
|
|
349
|
+
if (!batch.srcChanged.length &&
|
|
350
|
+
!batch.srcDeleted.length &&
|
|
351
|
+
!batch.depChanged.length &&
|
|
352
|
+
!batch.depDeleted.length &&
|
|
353
|
+
!batch.docsDirty &&
|
|
354
|
+
!batch.localesDirty &&
|
|
355
|
+
!(batch.designsDirty || batch.designsChanged.length || batch.designsDeleted.length)) {
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
// Dependency changes: conservative full rebuild + full reload (v0.1.5).
|
|
359
|
+
if (batch.depChanged.length || batch.depDeleted.length) {
|
|
360
|
+
log.info(`dependency change detected (${batch.depChanged.length} update, ${batch.depDeleted.length} delete) — full rebuild…`);
|
|
361
|
+
const report = rebuild();
|
|
362
|
+
if (!printReport(report, 'rebuild')) {
|
|
363
|
+
log.warn('rebuild failed — keeping previous server');
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
// Refresh watch roots in case the graph gained new packages.
|
|
367
|
+
const refreshed = collectDevWatchRoots({ project, outDir });
|
|
368
|
+
for (const r of refreshed.roots) {
|
|
369
|
+
if (!watchRoots.includes(r)) {
|
|
370
|
+
watchRoots.push(r);
|
|
371
|
+
fingerprints.set(r, fileFingerprintMap(r));
|
|
372
|
+
}
|
|
235
373
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
374
|
+
dependencyRoots = [...refreshed.dependencyRoots];
|
|
375
|
+
if (batch.docsDirty || projectHasDocuments(project)) {
|
|
376
|
+
const docs = await buildIntegratedDocuments({ projectRoot: project, outDir });
|
|
377
|
+
if (!docs.ok)
|
|
378
|
+
log.warn('document mount rebuild failed — keeping previous docs');
|
|
239
379
|
}
|
|
240
|
-
|
|
241
|
-
|
|
380
|
+
if (wechatPreview) {
|
|
381
|
+
if (!packWechatPreview())
|
|
382
|
+
log.warn('wechat pack failed — keeping previous dist/wechat');
|
|
383
|
+
continue;
|
|
242
384
|
}
|
|
243
|
-
|
|
244
|
-
|
|
385
|
+
const kind = await reloadAfterBuild({
|
|
386
|
+
affectedChunks: report.affectedChunks ?? [],
|
|
387
|
+
seedChunks: report.seedChunks ?? [],
|
|
388
|
+
emitted: report.emitted ?? [],
|
|
389
|
+
full: true,
|
|
390
|
+
islandHmr: false,
|
|
391
|
+
});
|
|
392
|
+
log.info(kind === 'respawn' ? 'reload ok (respawned; deps)' : 'soft reload ok (full page; deps)');
|
|
245
393
|
continue;
|
|
246
|
-
|
|
394
|
+
}
|
|
395
|
+
let needFullReload = batch.docsDirty || batch.designsDirty;
|
|
247
396
|
if (batch.srcChanged.length || batch.srcDeleted.length) {
|
|
248
397
|
log.info(`change detected (${batch.srcChanged.length} update, ${batch.srcDeleted.length} delete) — affected rebuild…`);
|
|
249
398
|
const changes = [
|
|
@@ -264,6 +413,12 @@ export function createDevSession(options) {
|
|
|
264
413
|
needFullReload = true;
|
|
265
414
|
}
|
|
266
415
|
}
|
|
416
|
+
if (wechatPreview) {
|
|
417
|
+
if (!packWechatPreview()) {
|
|
418
|
+
log.warn('wechat pack failed — keeping previous dist/wechat');
|
|
419
|
+
}
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
267
422
|
const kind = await reloadAfterBuild({
|
|
268
423
|
affectedChunks: report.affectedChunks ?? [],
|
|
269
424
|
seedChunks: report.seedChunks ?? [],
|
|
@@ -280,16 +435,56 @@ export function createDevSession(options) {
|
|
|
280
435
|
: 'soft reload ok');
|
|
281
436
|
continue;
|
|
282
437
|
}
|
|
438
|
+
if (batch.designsChanged.length || batch.designsDeleted.length || batch.designsDirty) {
|
|
439
|
+
log.info(`designs change detected (${batch.designsChanged.length} update, ${batch.designsDeleted.length} delete) — rebuilding styles…`);
|
|
440
|
+
const changes = [
|
|
441
|
+
...batch.designsChanged.map((p) => ({ path: p, kind: /** @type {'update'} */ ('update') })),
|
|
442
|
+
...batch.designsDeleted.map((p) => ({ path: p, kind: /** @type {'delete'} */ ('delete') })),
|
|
443
|
+
];
|
|
444
|
+
const report = rebuild(changes.length ? changes : undefined);
|
|
445
|
+
if (!printReport(report, 'rebuild')) {
|
|
446
|
+
log.warn('designs rebuild failed — keeping previous styles');
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
if (batch.docsDirty || projectHasDocuments(project)) {
|
|
450
|
+
const docs = await buildIntegratedDocuments({ projectRoot: project, outDir });
|
|
451
|
+
if (!docs.ok)
|
|
452
|
+
log.warn('document mount rebuild failed — keeping previous docs');
|
|
453
|
+
}
|
|
454
|
+
if (wechatPreview) {
|
|
455
|
+
if (!packWechatPreview())
|
|
456
|
+
log.warn('wechat pack failed — keeping previous dist/wechat');
|
|
457
|
+
continue;
|
|
458
|
+
}
|
|
459
|
+
const kind = await reloadAfterBuild({
|
|
460
|
+
affectedChunks: report.affectedChunks ?? [],
|
|
461
|
+
seedChunks: report.seedChunks ?? [],
|
|
462
|
+
emitted: report.emitted ?? [],
|
|
463
|
+
full: true,
|
|
464
|
+
islandHmr: false,
|
|
465
|
+
});
|
|
466
|
+
log.info(kind === 'respawn' ? 'reload ok (respawned; designs)' : 'soft reload ok (full page; designs)');
|
|
467
|
+
continue;
|
|
468
|
+
}
|
|
283
469
|
if (batch.localesDirty) {
|
|
284
470
|
log.info('locales change detected — re-emitting #locales runtime…');
|
|
285
471
|
if (!emitLocales()) {
|
|
286
472
|
log.warn('locale runtime emit failed — keeping previous modules');
|
|
287
473
|
continue;
|
|
288
474
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
475
|
+
if (wechatPreview) {
|
|
476
|
+
if (!packWechatPreview()) {
|
|
477
|
+
log.warn('wechat pack failed — keeping previous dist/wechat');
|
|
478
|
+
}
|
|
479
|
+
if (!batch.docsDirty)
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
483
|
+
const kind = await reloadAfterBuild({ full: true, islandHmr: false, emitted: [] });
|
|
484
|
+
log.info(kind === 'respawn' ? 'reload ok (respawned; locales)' : 'soft reload ok (full page; locales)');
|
|
485
|
+
if (!batch.docsDirty)
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
293
488
|
}
|
|
294
489
|
if (batch.docsDirty) {
|
|
295
490
|
log.info('documents change detected — rebuilding document mount…');
|
|
@@ -298,8 +493,15 @@ export function createDevSession(options) {
|
|
|
298
493
|
log.warn('document mount rebuild failed — keeping previous docs');
|
|
299
494
|
continue;
|
|
300
495
|
}
|
|
301
|
-
|
|
302
|
-
|
|
496
|
+
if (wechatPreview) {
|
|
497
|
+
if (!packWechatPreview()) {
|
|
498
|
+
log.warn('wechat pack failed — keeping previous dist/wechat');
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
const kind = await reloadAfterBuild({ full: true, islandHmr: false, emitted: [] });
|
|
503
|
+
log.info(kind === 'respawn' ? 'reload ok (respawned; docs)' : 'soft reload ok (full page; docs)');
|
|
504
|
+
}
|
|
303
505
|
}
|
|
304
506
|
}
|
|
305
507
|
}
|
|
@@ -350,6 +552,8 @@ function defaultSpawnHost(opts) {
|
|
|
350
552
|
VMZ_PORT: String(opts.port),
|
|
351
553
|
VMZ_HOST: opts.host,
|
|
352
554
|
VMZ_DEV: '1',
|
|
555
|
+
VMZ_PROJECT_ROOT: opts.project,
|
|
556
|
+
VMZ_NATIVE_NODE: resolveNativePath(),
|
|
353
557
|
},
|
|
354
558
|
stdio: ['ignore', 'inherit', 'inherit'],
|
|
355
559
|
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev watch helpers: coalesce multi-file bursts without dropping dirty set,
|
|
3
|
+
* and derive extra watch roots from the compile graph (deployment unit sources).
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {{ changed: string[], deleted: string[] }} DirtySet
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Merge dirty sets: later change cancels delete and vice versa.
|
|
10
|
+
* @param {DirtySet} a
|
|
11
|
+
* @param {DirtySet} b
|
|
12
|
+
* @returns {DirtySet}
|
|
13
|
+
*/
|
|
14
|
+
export declare function mergeDirtySets(a: any, b: any): {
|
|
15
|
+
changed: unknown[];
|
|
16
|
+
deleted: unknown[];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Wait until `root` stops changing; return the **accumulated** dirty set since `initial`.
|
|
20
|
+
* Updates `fingerprints` for `root` as it polls. Does **not** discard `initial`.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} root
|
|
23
|
+
* @param {Map<string, Map<string, string>>} fingerprints
|
|
24
|
+
* @param {DirtySet} initial
|
|
25
|
+
* @param {{ sleep?: (ms: number) => Promise<void>, maxRounds?: number, settleMs?: number }} [opts]
|
|
26
|
+
* @returns {Promise<DirtySet>}
|
|
27
|
+
*/
|
|
28
|
+
export declare function coalesceRootBurst(root: any, fingerprints: any, initial: any, opts?: {}): Promise<{
|
|
29
|
+
changed: any[];
|
|
30
|
+
deleted: any[];
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Walk up from a file to find a package.json directory.
|
|
34
|
+
* @param {string} file
|
|
35
|
+
* @returns {string | null}
|
|
36
|
+
*/
|
|
37
|
+
export declare function findPackageRoot(file: any): string;
|
|
38
|
+
/**
|
|
39
|
+
* Prefer package/src when present; otherwise the directory containing the source file.
|
|
40
|
+
* @param {string} sourceFile
|
|
41
|
+
* @returns {string | null}
|
|
42
|
+
*/
|
|
43
|
+
export declare function watchRootForSourceFile(sourceFile: any): string;
|
|
44
|
+
/**
|
|
45
|
+
* Absolute roots for workspace / file / link deps that have a src tree.
|
|
46
|
+
* @param {string} project
|
|
47
|
+
* @returns {string[]}
|
|
48
|
+
*/
|
|
49
|
+
export declare function localLinkDependencyRoots(project: any): any[];
|
|
50
|
+
/**
|
|
51
|
+
* Collect watch roots: project src/locales/documents + compile-graph external sources
|
|
52
|
+
* + local link/workspace package roots. Never adds a bare registry node_modules tree.
|
|
53
|
+
*
|
|
54
|
+
* @param {{ project: string, outDir: string }} opts
|
|
55
|
+
* @returns {{ roots: string[], dependencyRoots: string[], applicationRoots: string[] }}
|
|
56
|
+
*/
|
|
57
|
+
export declare function collectDevWatchRoots(opts: any): {
|
|
58
|
+
roots: any[];
|
|
59
|
+
dependencyRoots: unknown[];
|
|
60
|
+
applicationRoots: any[];
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Classify which watch bucket a root belongs to.
|
|
64
|
+
* @param {string} root
|
|
65
|
+
* @param {{
|
|
66
|
+
* src: string,
|
|
67
|
+
* docsRoot: string,
|
|
68
|
+
* localesRoot: string,
|
|
69
|
+
* designsRoot: string,
|
|
70
|
+
* dependencyRoots: string[],
|
|
71
|
+
* }} ctx
|
|
72
|
+
* @returns {'src' | 'locales' | 'docs' | 'designs' | 'dep' | 'other'}
|
|
73
|
+
*/
|
|
74
|
+
export declare function classifyWatchRoot(root: any, ctx: any): "src" | "locales" | "docs" | "designs" | "dep" | "other";
|
|
75
|
+
/**
|
|
76
|
+
* Classify whether a changed file lives under a dependency watch root (not app src).
|
|
77
|
+
* @param {string} file
|
|
78
|
+
* @param {string[]} dependencyRoots
|
|
79
|
+
*/
|
|
80
|
+
export declare function isDependencyPath(file: any, dependencyRoots: any): any;
|