@dimina-kit/devtools 0.4.0-dev.20260707110006 → 0.4.0-dev.20260711062001
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/main/index.bundle.js +48 -14
- package/dist/main/ipc/project-fs.d.ts +32 -3
- package/dist/main/ipc/project-fs.js +33 -5
- package/dist/main/services/render-inspect/index.d.ts +1 -1
- package/dist/main/services/settings/index.d.ts +7 -1
- package/dist/main/services/settings/index.js +22 -2
- package/dist/main/services/workbench-coi-server.js +9 -2
- package/dist/main/services/workspace/workspace-service.js +7 -7
- package/dist/preload/instrumentation/wxml.js +1 -1
- package/dist/preload/runtime/bridge.d.ts +3 -3
- package/dist/preload/runtime/bridge.js +2 -2
- package/dist/preload/windows/host-toolbar-runtime.cjs.map +2 -2
- package/dist/preload/windows/main.cjs +27 -2
- package/dist/preload/windows/main.cjs.map +2 -2
- package/dist/preload/windows/simulator.cjs +12 -4
- package/dist/preload/windows/simulator.cjs.map +3 -3
- package/dist/preload/windows/simulator.js +12 -4
- package/dist/render-host/render-inspect.js +189 -88
- package/dist/renderer/assets/index-WbvXdhWQ.js +49 -0
- package/dist/renderer/assets/{input-CTb_le7F.js → input-COtRON-n.js} +2 -2
- package/dist/renderer/assets/{ipc-transport-BPWIV5hA.css → ipc-transport-CNvORIEX.css} +1 -1
- package/dist/renderer/assets/{ipc-transport-Ck5Xa8Tu.js → ipc-transport-SuI2rOB_.js} +1 -1
- package/dist/renderer/assets/{popover-B1Zu2UQu.js → popover-B73T3z-m.js} +2 -2
- package/dist/renderer/assets/{select-ozSk5Pt6.js → select-Bwb8O0Mf.js} +2 -2
- package/dist/renderer/assets/{settings-CNwGOI22.js → settings-BispnvJU.js} +2 -2
- package/dist/renderer/assets/{settings-api-DMbMp1Eq.js → settings-api-HIBz8BFz.js} +2 -2
- package/dist/renderer/assets/workbenchSettings-CtRBr7gS.js +8 -0
- package/dist/renderer/entries/main/index.html +6 -6
- package/dist/renderer/entries/popover/index.html +5 -5
- package/dist/renderer/entries/settings/index.html +5 -5
- package/dist/renderer/entries/workbench-settings/index.html +4 -4
- package/dist/shared/ipc-channels.d.ts +2 -44
- package/dist/shared/ipc-schemas.d.ts +4 -1
- package/dist/shared/ipc-schemas.js +4 -1
- package/dist/simulator/assets/simulator-A1vGZVBM.js +10 -0
- package/dist/simulator/simulator.html +1 -1
- package/dist/vscode-workbench/assets/__vite-browser-external-B1y6A_ue.js +1 -0
- package/dist/vscode-workbench/assets/{dist-OuMzPA6f.js → dist-UYlh9rWP.js} +3 -3
- package/dist/vscode-workbench/assets/fs-core-worker-urls-BGhWkdqX.js +1 -0
- package/dist/vscode-workbench/assets/fs-core.worker-Bs1XABE2.js +1 -0
- package/dist/vscode-workbench/assets/fs-query.worker-cZ-7Fjch.js +2 -0
- package/dist/vscode-workbench/assets/{iconv-lite-umd-a5yQx8hi.js → iconv-lite-umd-P85lbjJb.js} +1 -1
- package/dist/vscode-workbench/assets/{index-CVEUw5jw.js → index-nrKFi46w.js} +445 -445
- package/dist/vscode-workbench/assets/{jschardet-BYkY0M2Q.js → jschardet-CLQONAKz.js} +1 -1
- package/dist/vscode-workbench/index.html +1 -1
- package/package.json +5 -4
- package/dist/preload/instrumentation/wxml-extract.d.ts +0 -11
- package/dist/preload/instrumentation/wxml-extract.js +0 -382
- package/dist/preload/shared/sid-registry.d.ts +0 -11
- package/dist/preload/shared/sid-registry.js +0 -38
- package/dist/renderer/assets/index-BjCKGJDg.js +0 -49
- package/dist/renderer/assets/workbenchSettings-Cr4EHo5w.js +0 -8
- package/dist/simulator/assets/simulator-DU3-fS3v.js +0 -10
- package/dist/vscode-workbench/assets/__vite-browser-external-D6-QnwSb.js +0 -1
- package/dist/vscode-workbench/assets/fs-core-worker-urls-CLvv1Q_0.js +0 -1
- package/dist/vscode-workbench/assets/fs-core.worker-VoMLk-PY.js +0 -1
- package/dist/vscode-workbench/assets/fs-query.worker-fXLkQK9l.js +0 -2
|
@@ -27,7 +27,10 @@ var DEFAULTS = {
|
|
|
27
27
|
port: 7789
|
|
28
28
|
},
|
|
29
29
|
compile: {
|
|
30
|
-
|
|
30
|
+
autoBuild: true
|
|
31
|
+
},
|
|
32
|
+
preview: {
|
|
33
|
+
autoReload: true
|
|
31
34
|
},
|
|
32
35
|
theme: "system",
|
|
33
36
|
lastCreateBaseDir: null
|
|
@@ -35,6 +38,9 @@ var DEFAULTS = {
|
|
|
35
38
|
function getSettingsFile() {
|
|
36
39
|
return path.join(app.getPath("userData"), "dimina-workbench-settings.json");
|
|
37
40
|
}
|
|
41
|
+
function pickBool(value, fallback) {
|
|
42
|
+
return typeof value === "boolean" ? value : fallback;
|
|
43
|
+
}
|
|
38
44
|
function loadWorkbenchSettings() {
|
|
39
45
|
try {
|
|
40
46
|
const data = JSON.parse(fs.readFileSync(getSettingsFile(), "utf-8"));
|
|
@@ -49,7 +55,16 @@ function loadWorkbenchSettings() {
|
|
|
49
55
|
port: data.mcp?.port ?? DEFAULTS.mcp.port
|
|
50
56
|
},
|
|
51
57
|
compile: {
|
|
52
|
-
|
|
58
|
+
// Legacy files persisted a single `compile.watch`; the new schema
|
|
59
|
+
// splits it into `compile.autoBuild` (recompile on save) and
|
|
60
|
+
// `preview.autoReload` (reload the simulator afterwards). Prefer the new
|
|
61
|
+
// key, fall back to the legacy one so an old settings file keeps its
|
|
62
|
+
// "auto-compile" choice; `preview.autoReload` defaults to true (the old
|
|
63
|
+
// always-reload behavior) when the file predates the split.
|
|
64
|
+
autoBuild: pickBool(data.compile?.autoBuild, pickBool(data.compile?.watch, DEFAULTS.compile.autoBuild))
|
|
65
|
+
},
|
|
66
|
+
preview: {
|
|
67
|
+
autoReload: pickBool(data.preview?.autoReload, DEFAULTS.preview.autoReload)
|
|
53
68
|
},
|
|
54
69
|
theme,
|
|
55
70
|
lastCreateBaseDir: typeof data.lastCreateBaseDir === "string" ? data.lastCreateBaseDir : DEFAULTS.lastCreateBaseDir
|
|
@@ -59,7 +74,8 @@ function loadWorkbenchSettings() {
|
|
|
59
74
|
...DEFAULTS,
|
|
60
75
|
cdp: { ...DEFAULTS.cdp },
|
|
61
76
|
mcp: { ...DEFAULTS.mcp },
|
|
62
|
-
compile: { ...DEFAULTS.compile }
|
|
77
|
+
compile: { ...DEFAULTS.compile },
|
|
78
|
+
preview: { ...DEFAULTS.preview }
|
|
63
79
|
};
|
|
64
80
|
}
|
|
65
81
|
}
|
|
@@ -502,12 +518,10 @@ var UpdateChannel = {
|
|
|
502
518
|
};
|
|
503
519
|
|
|
504
520
|
// src/main/ipc/project-fs.ts
|
|
521
|
+
import { WATCH_IGNORE_DIRS } from "@dimina-kit/devkit/watch-ignore";
|
|
505
522
|
var LIST_FILE_LIMIT = 5e3;
|
|
506
523
|
var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
507
|
-
|
|
508
|
-
".git",
|
|
509
|
-
".svn",
|
|
510
|
-
".hg",
|
|
524
|
+
...WATCH_IGNORE_DIRS,
|
|
511
525
|
"dist",
|
|
512
526
|
"build",
|
|
513
527
|
".next",
|
|
@@ -665,7 +679,18 @@ async function statWithin(root, rel) {
|
|
|
665
679
|
}
|
|
666
680
|
async function readdirWithin(root, rel) {
|
|
667
681
|
const safe = await resolveWithinProjectRoot(joinRel(root, rel), root);
|
|
668
|
-
|
|
682
|
+
const dirents = await fs2.readdir(safe, { withFileTypes: true });
|
|
683
|
+
return Promise.all(
|
|
684
|
+
dirents.map(async (d) => {
|
|
685
|
+
if (d.isDirectory()) return { name: d.name, isDirectory: true };
|
|
686
|
+
try {
|
|
687
|
+
const st = await fs2.stat(path2.join(safe, d.name));
|
|
688
|
+
return { name: d.name, isDirectory: false, size: st.size, mtimeMs: st.mtimeMs };
|
|
689
|
+
} catch {
|
|
690
|
+
return { name: d.name, isDirectory: false };
|
|
691
|
+
}
|
|
692
|
+
})
|
|
693
|
+
);
|
|
669
694
|
}
|
|
670
695
|
async function readFileBufferWithin(root, rel) {
|
|
671
696
|
return readFileBuffer(root, joinRel(root, rel));
|
|
@@ -4095,16 +4120,18 @@ function createWorkspaceService(ctx) {
|
|
|
4095
4120
|
}
|
|
4096
4121
|
}
|
|
4097
4122
|
async function runCompile(projectPath, sessionGeneration) {
|
|
4098
|
-
const { compile } = loadWorkbenchSettings();
|
|
4123
|
+
const { compile, preview } = loadWorkbenchSettings();
|
|
4099
4124
|
try {
|
|
4100
4125
|
const session5 = await ctx.adapter.openProject({
|
|
4101
4126
|
projectPath,
|
|
4102
4127
|
sourcemap: true,
|
|
4103
4128
|
fileTypes: ctx.fileTypes,
|
|
4104
|
-
|
|
4129
|
+
// Two independent gates: autoBuild = recompile on save; autoReload = refresh the simulator afterwards (off ⇒ page/form state survives; hotReload below stays false so the native simulator, which has no SSE reload, isn't refreshed).
|
|
4130
|
+
watch: compile.autoBuild,
|
|
4131
|
+
autoReload: preview.autoReload,
|
|
4105
4132
|
onRebuild: () => {
|
|
4106
4133
|
const { pages } = getProjectPages(projectPath);
|
|
4107
|
-
sendStatus("ready", "\u7F16\u8BD1\u5B8C\u6210\uFF0C\u5DF2\u91CD\u542F",
|
|
4134
|
+
sendStatus("ready", preview.autoReload ? "\u7F16\u8BD1\u5B8C\u6210\uFF0C\u5DF2\u91CD\u542F" : "\u7F16\u8BD1\u5B8C\u6210", preview.autoReload, pages.length ? pages : void 0);
|
|
4108
4135
|
},
|
|
4109
4136
|
onBuildError: (err2) => sendStatus("error", String(err2)),
|
|
4110
4137
|
// Watcher died mid-session (EMFILE, permission loss, …): non-fatal, so 'ready' stays but `watcher: 'dead'` flags that saves no longer auto-rebuild.
|
|
@@ -4631,7 +4658,10 @@ var WorkbenchSettingsSaveSchema = z3.tuple([
|
|
|
4631
4658
|
port: z3.number().int().min(0).max(65535)
|
|
4632
4659
|
}),
|
|
4633
4660
|
compile: z3.looseObject({
|
|
4634
|
-
|
|
4661
|
+
autoBuild: z3.boolean()
|
|
4662
|
+
}),
|
|
4663
|
+
preview: z3.looseObject({
|
|
4664
|
+
autoReload: z3.boolean()
|
|
4635
4665
|
}),
|
|
4636
4666
|
theme: z3.enum(["system", "light", "dark"]),
|
|
4637
4667
|
lastCreateBaseDir: z3.union([z3.string(), z3.null()])
|
|
@@ -11044,8 +11074,12 @@ async function fsStat(ctx) {
|
|
|
11044
11074
|
}
|
|
11045
11075
|
async function fsReaddir(ctx) {
|
|
11046
11076
|
const entries = await readdirWithin(ctx.projectRoot, ctx.rel);
|
|
11047
|
-
const visible = entries.filter((e) => !(e.isDirectory
|
|
11048
|
-
jsonRes(
|
|
11077
|
+
const visible = entries.filter((e) => !(e.isDirectory && SKIP_DIRS.has(e.name)));
|
|
11078
|
+
jsonRes(
|
|
11079
|
+
ctx.res,
|
|
11080
|
+
200,
|
|
11081
|
+
visible.map((e) => e.isDirectory ? [e.name, 2] : [e.name, 1, e.size, e.mtimeMs])
|
|
11082
|
+
);
|
|
11049
11083
|
}
|
|
11050
11084
|
async function fsRead(ctx) {
|
|
11051
11085
|
const buf = await readFileBufferWithin(ctx.projectRoot, ctx.rel);
|
|
@@ -2,7 +2,13 @@ import type { WorkbenchContext } from '../services/workbench-context.js';
|
|
|
2
2
|
import type { Disposable } from '@dimina-kit/electron-deck/main';
|
|
3
3
|
/** Dependency/VCS/build directories invisible to every project-tree consumer:
|
|
4
4
|
* IPC `listFiles`, the `/__fs/readdir` bridge (so the workbench mirror and the
|
|
5
|
-
* WAL ledger seed never walk into them), and the `/__fs/watch` change stream.
|
|
5
|
+
* WAL ledger seed never walk into them), and the `/__fs/watch` change stream.
|
|
6
|
+
* Derived from devkit's `WATCH_IGNORE_DIRS` (the shared never-source core:
|
|
7
|
+
* node_modules + VCS) so the `node_modules` omission that once wedged
|
|
8
|
+
* `watcher.close()` can never drift back on this side, PLUS the editor mirror's
|
|
9
|
+
* own build-output names (`dist`/`build`/tool caches) — which the devkit
|
|
10
|
+
* recompile watcher deliberately does NOT ignore, since app.json may declare
|
|
11
|
+
* pages under such paths. */
|
|
6
12
|
export declare const SKIP_DIRS: ReadonlySet<string>;
|
|
7
13
|
/**
|
|
8
14
|
* Synchronous, string-level guard: reject empty root (ENOACTIVE), NUL bytes
|
|
@@ -79,8 +85,31 @@ export declare function writeFile(root: string, p: string, content: string | Buf
|
|
|
79
85
|
* out-of-sandbox metadata. `rel` is a project-root-relative bridge path.
|
|
80
86
|
*/
|
|
81
87
|
export declare function statWithin(root: string, rel: string): Promise<import('node:fs').Stats>;
|
|
82
|
-
/**
|
|
83
|
-
|
|
88
|
+
/**
|
|
89
|
+
* One `readdirWithin` result entry. Directories carry no stat (the caller —
|
|
90
|
+
* the `/__fs/readdir` bridge handler — never needs it: a directory recurses
|
|
91
|
+
* instead of being compared). `size`/`mtimeMs` are omitted (not `null`) when
|
|
92
|
+
* the entry raced a concurrent delete between `readdir` and `stat` — the
|
|
93
|
+
* bridge wire format then drops them too, which the sync engine's watch
|
|
94
|
+
* expansion (dimina-kit workbench's wal-audit-watch-expand.ts) treats as
|
|
95
|
+
* "always changed" rather than risking a false stat match.
|
|
96
|
+
*/
|
|
97
|
+
export interface ReaddirStatEntry {
|
|
98
|
+
name: string;
|
|
99
|
+
isDirectory: boolean;
|
|
100
|
+
size?: number;
|
|
101
|
+
mtimeMs?: number;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Realpath-contained `fs.readdir` twin (see {@link statWithin}) that also
|
|
105
|
+
* `fs.stat`s every FILE entry (size + mtimeMs) — the disk-side half of the
|
|
106
|
+
* sync engine's stat-diffing (see wal-audit-watch-expand.ts's module doc):
|
|
107
|
+
* a watch-reported directory is only worth a full content re-read when a
|
|
108
|
+
* file's stat inside it actually moved, and the `/__fs/readdir` bridge is
|
|
109
|
+
* the one HTTP round trip cheap enough to do that check on every watch
|
|
110
|
+
* event without itself re-reading file bytes.
|
|
111
|
+
*/
|
|
112
|
+
export declare function readdirWithin(root: string, rel: string): Promise<ReaddirStatEntry[]>;
|
|
84
113
|
/**
|
|
85
114
|
* Raw-byte read twin of {@link readFileBuffer} taking a project-root-relative
|
|
86
115
|
* bridge path (the COI `/__fs/read` bridge), with the same realpath +
|
|
@@ -47,14 +47,21 @@ import { z } from 'zod';
|
|
|
47
47
|
import { IpcRegistry } from '../utils/ipc-registry.js';
|
|
48
48
|
import { validate } from '../utils/ipc-schema.js';
|
|
49
49
|
import { ProjectFsChannel } from '../../shared/ipc-channels.js';
|
|
50
|
+
import { WATCH_IGNORE_DIRS } from '@dimina-kit/devkit/watch-ignore';
|
|
50
51
|
/** Cap for `listFiles` — huge monorepos would otherwise stall the renderer. */
|
|
51
52
|
const LIST_FILE_LIMIT = 5000;
|
|
52
53
|
/** Dependency/VCS/build directories invisible to every project-tree consumer:
|
|
53
54
|
* IPC `listFiles`, the `/__fs/readdir` bridge (so the workbench mirror and the
|
|
54
|
-
* WAL ledger seed never walk into them), and the `/__fs/watch` change stream.
|
|
55
|
+
* WAL ledger seed never walk into them), and the `/__fs/watch` change stream.
|
|
56
|
+
* Derived from devkit's `WATCH_IGNORE_DIRS` (the shared never-source core:
|
|
57
|
+
* node_modules + VCS) so the `node_modules` omission that once wedged
|
|
58
|
+
* `watcher.close()` can never drift back on this side, PLUS the editor mirror's
|
|
59
|
+
* own build-output names (`dist`/`build`/tool caches) — which the devkit
|
|
60
|
+
* recompile watcher deliberately does NOT ignore, since app.json may declare
|
|
61
|
+
* pages under such paths. */
|
|
55
62
|
export const SKIP_DIRS = new Set([
|
|
56
|
-
|
|
57
|
-
'.next', '.cache', '.turbo', '.parcel-cache', '.nuxt', '.output', '.vite',
|
|
63
|
+
...WATCH_IGNORE_DIRS,
|
|
64
|
+
'dist', 'build', '.next', '.cache', '.turbo', '.parcel-cache', '.nuxt', '.output', '.vite',
|
|
58
65
|
]);
|
|
59
66
|
const PathArg = z.string().min(1);
|
|
60
67
|
const ReadFileSchema = z.tuple([PathArg]);
|
|
@@ -319,10 +326,31 @@ export async function statWithin(root, rel) {
|
|
|
319
326
|
const safe = await resolveWithinProjectRoot(joinRel(root, rel), root);
|
|
320
327
|
return fs.stat(safe);
|
|
321
328
|
}
|
|
322
|
-
/**
|
|
329
|
+
/**
|
|
330
|
+
* Realpath-contained `fs.readdir` twin (see {@link statWithin}) that also
|
|
331
|
+
* `fs.stat`s every FILE entry (size + mtimeMs) — the disk-side half of the
|
|
332
|
+
* sync engine's stat-diffing (see wal-audit-watch-expand.ts's module doc):
|
|
333
|
+
* a watch-reported directory is only worth a full content re-read when a
|
|
334
|
+
* file's stat inside it actually moved, and the `/__fs/readdir` bridge is
|
|
335
|
+
* the one HTTP round trip cheap enough to do that check on every watch
|
|
336
|
+
* event without itself re-reading file bytes.
|
|
337
|
+
*/
|
|
323
338
|
export async function readdirWithin(root, rel) {
|
|
324
339
|
const safe = await resolveWithinProjectRoot(joinRel(root, rel), root);
|
|
325
|
-
|
|
340
|
+
const dirents = await fs.readdir(safe, { withFileTypes: true });
|
|
341
|
+
return Promise.all(dirents.map(async (d) => {
|
|
342
|
+
if (d.isDirectory())
|
|
343
|
+
return { name: d.name, isDirectory: true };
|
|
344
|
+
try {
|
|
345
|
+
const st = await fs.stat(path.join(safe, d.name));
|
|
346
|
+
return { name: d.name, isDirectory: false, size: st.size, mtimeMs: st.mtimeMs };
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
// Entry vanished (or became unreadable) between readdir and stat —
|
|
350
|
+
// report it stat-less; see this function's doc for why that is safe.
|
|
351
|
+
return { name: d.name, isDirectory: false };
|
|
352
|
+
}
|
|
353
|
+
}));
|
|
326
354
|
}
|
|
327
355
|
/**
|
|
328
356
|
* Raw-byte read twin of {@link readFileBuffer} taking a project-root-relative
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
import type { WebContents } from 'electron';
|
|
17
17
|
import type { ConnectionRegistry } from '@dimina-kit/electron-deck/main';
|
|
18
18
|
import type { ElementInspection } from '../../../shared/ipc-channels.js';
|
|
19
|
-
import type { WxmlNode } from '
|
|
19
|
+
import type { WxmlNode } from '@dimina-kit/inspect';
|
|
20
20
|
export interface RenderInspector {
|
|
21
21
|
/** Inject (once per wc) the inspector IIFE, then read the WXML tree. */
|
|
22
22
|
getWxml(wc: WebContents): Promise<WxmlNode | null>;
|
|
@@ -10,7 +10,13 @@ export interface WorkbenchSettings {
|
|
|
10
10
|
};
|
|
11
11
|
compile: {
|
|
12
12
|
/** Watch project files and auto-recompile on change. */
|
|
13
|
-
|
|
13
|
+
autoBuild: boolean;
|
|
14
|
+
};
|
|
15
|
+
preview: {
|
|
16
|
+
/** Reload the simulator once a watcher-triggered rebuild lands. Independent
|
|
17
|
+
* of `compile.autoBuild`: "auto-compile on save, reload manually" is valid
|
|
18
|
+
* and preserves the running page stack / form state across a save. */
|
|
19
|
+
autoReload: boolean;
|
|
14
20
|
};
|
|
15
21
|
theme: ThemeSource;
|
|
16
22
|
/**
|
|
@@ -12,7 +12,10 @@ const DEFAULTS = {
|
|
|
12
12
|
port: 7789,
|
|
13
13
|
},
|
|
14
14
|
compile: {
|
|
15
|
-
|
|
15
|
+
autoBuild: true,
|
|
16
|
+
},
|
|
17
|
+
preview: {
|
|
18
|
+
autoReload: true,
|
|
16
19
|
},
|
|
17
20
|
theme: 'system',
|
|
18
21
|
lastCreateBaseDir: null,
|
|
@@ -20,6 +23,13 @@ const DEFAULTS = {
|
|
|
20
23
|
function getSettingsFile() {
|
|
21
24
|
return path.join(app.getPath('userData'), 'dimina-workbench-settings.json');
|
|
22
25
|
}
|
|
26
|
+
/** Accept `value` only when it is a real boolean, else `fallback`. A bare `??`
|
|
27
|
+
* chain guards only null/undefined, so a hand-edited or corrupt config with a
|
|
28
|
+
* stringy `"false"` would pass through and read as truthy downstream — silently
|
|
29
|
+
* keeping a toggle ON when the user meant OFF. */
|
|
30
|
+
function pickBool(value, fallback) {
|
|
31
|
+
return typeof value === 'boolean' ? value : fallback;
|
|
32
|
+
}
|
|
23
33
|
export function loadWorkbenchSettings() {
|
|
24
34
|
try {
|
|
25
35
|
const data = JSON.parse(fs.readFileSync(getSettingsFile(), 'utf-8'));
|
|
@@ -36,7 +46,16 @@ export function loadWorkbenchSettings() {
|
|
|
36
46
|
port: data.mcp?.port ?? DEFAULTS.mcp.port,
|
|
37
47
|
},
|
|
38
48
|
compile: {
|
|
39
|
-
|
|
49
|
+
// Legacy files persisted a single `compile.watch`; the new schema
|
|
50
|
+
// splits it into `compile.autoBuild` (recompile on save) and
|
|
51
|
+
// `preview.autoReload` (reload the simulator afterwards). Prefer the new
|
|
52
|
+
// key, fall back to the legacy one so an old settings file keeps its
|
|
53
|
+
// "auto-compile" choice; `preview.autoReload` defaults to true (the old
|
|
54
|
+
// always-reload behavior) when the file predates the split.
|
|
55
|
+
autoBuild: pickBool(data.compile?.autoBuild, pickBool(data.compile?.watch, DEFAULTS.compile.autoBuild)),
|
|
56
|
+
},
|
|
57
|
+
preview: {
|
|
58
|
+
autoReload: pickBool(data.preview?.autoReload, DEFAULTS.preview.autoReload),
|
|
40
59
|
},
|
|
41
60
|
theme,
|
|
42
61
|
lastCreateBaseDir: typeof data.lastCreateBaseDir === 'string'
|
|
@@ -50,6 +69,7 @@ export function loadWorkbenchSettings() {
|
|
|
50
69
|
cdp: { ...DEFAULTS.cdp },
|
|
51
70
|
mcp: { ...DEFAULTS.mcp },
|
|
52
71
|
compile: { ...DEFAULTS.compile },
|
|
72
|
+
preview: { ...DEFAULTS.preview },
|
|
53
73
|
};
|
|
54
74
|
}
|
|
55
75
|
}
|
|
@@ -206,8 +206,15 @@ async function fsReaddir(ctx) {
|
|
|
206
206
|
// every level: the workbench mirror and the WAL ledger seed walk whatever
|
|
207
207
|
// this returns, so listing them would pull entire dependency trees into the
|
|
208
208
|
// editor memfs and the OPFS ledger. Same-named FILES stay visible.
|
|
209
|
-
const visible = entries.filter((e) => !(e.isDirectory
|
|
210
|
-
|
|
209
|
+
const visible = entries.filter((e) => !(e.isDirectory && SKIP_DIRS.has(e.name)));
|
|
210
|
+
// Wire shape: `[name, type]` for a directory, `[name, type, size, mtimeMs]`
|
|
211
|
+
// for a file — the sync engine's watch-batch stat-diffing (workbench's
|
|
212
|
+
// wal-audit-watch-expand.ts) needs size+mtimeMs to tell a stat-unchanged
|
|
213
|
+
// survivor from an actually-modified file without re-reading its content.
|
|
214
|
+
// `size`/`mtimeMs` are simply absent (not `null`) for a stat-less entry
|
|
215
|
+
// (readdirWithin's readdir/stat race) — the client side then always
|
|
216
|
+
// treats it as changed.
|
|
217
|
+
jsonRes(ctx.res, 200, visible.map((e) => (e.isDirectory ? [e.name, 2] : [e.name, 1, e.size, e.mtimeMs])));
|
|
211
218
|
}
|
|
212
219
|
async function fsRead(ctx) {
|
|
213
220
|
const buf = await readFileBufferWithin(ctx.projectRoot, ctx.rel);
|
|
@@ -120,20 +120,20 @@ export function createWorkspaceService(ctx) {
|
|
|
120
120
|
* a superseded session's buffered lines.
|
|
121
121
|
*/
|
|
122
122
|
async function runCompile(projectPath, sessionGeneration) {
|
|
123
|
-
const { compile } = loadWorkbenchSettings();
|
|
123
|
+
const { compile, preview } = loadWorkbenchSettings();
|
|
124
124
|
try {
|
|
125
125
|
const session = await ctx.adapter.openProject({
|
|
126
126
|
projectPath,
|
|
127
127
|
sourcemap: true,
|
|
128
128
|
fileTypes: ctx.fileTypes,
|
|
129
|
-
|
|
129
|
+
// Two independent gates: autoBuild = recompile on save; autoReload = refresh the simulator afterwards (off ⇒ page/form state survives; hotReload below stays false so the native simulator, which has no SSE reload, isn't refreshed).
|
|
130
|
+
watch: compile.autoBuild,
|
|
131
|
+
autoReload: preview.autoReload,
|
|
130
132
|
onRebuild: () => {
|
|
131
|
-
// getProjectPages never throws
|
|
132
|
-
//
|
|
133
|
-
// app.json names ≥1 page) and is withheld so the renderer keeps its
|
|
134
|
-
// previous dropdown instead of blanking; the push is never blocked.
|
|
133
|
+
// getProjectPages never throws; empty pages (read failed / degenerate
|
|
134
|
+
// project) are withheld so the renderer keeps its previous dropdown.
|
|
135
135
|
const { pages } = repo.getProjectPages(projectPath);
|
|
136
|
-
sendStatus('ready', '编译完成,已重启',
|
|
136
|
+
sendStatus('ready', preview.autoReload ? '编译完成,已重启' : '编译完成', preview.autoReload, pages.length ? pages : undefined);
|
|
137
137
|
},
|
|
138
138
|
onBuildError: (err) => sendStatus('error', String(err)),
|
|
139
139
|
// Watcher died mid-session (EMFILE, permission loss, …): non-fatal, so 'ready' stays but `watcher: 'dead'` flags that saves no longer auto-rebuild.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { clearWxmlSnapshot, setWxmlSnapshot, unhighlightElement, } from '../runtime/bridge.js';
|
|
2
2
|
import { WXML_DEBOUNCE_MS, WXML_RETRY_INTERVAL_MS, WXML_RETRY_TIMEOUT_MS, NAVIGATION_POLL_INTERVAL_MS, NAVIGATION_TIMEOUT_MS, } from '../shared/constants.js';
|
|
3
|
-
import { walkInstance } from '
|
|
3
|
+
import { walkInstance } from '@dimina-kit/inspect';
|
|
4
4
|
import { getActivePageIframe } from '../shared/page-iframe.js';
|
|
5
5
|
function getVueAppFromIframe(iframe) {
|
|
6
6
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ElementInspection } from '../../shared/ipc-channels.js';
|
|
2
|
-
import { type WxmlNode } from '
|
|
3
|
-
export type { WxmlNode } from '
|
|
4
|
-
export { registerSyntheticSid } from '
|
|
2
|
+
import { type WxmlNode } from '@dimina-kit/inspect';
|
|
3
|
+
export type { WxmlNode } from '@dimina-kit/inspect';
|
|
4
|
+
export { registerSyntheticSid } from '@dimina-kit/inspect';
|
|
5
5
|
export interface Snapshot<T> {
|
|
6
6
|
gen: number;
|
|
7
7
|
ready: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { exposeOnMainWorld } from '../shared/expose.js';
|
|
2
2
|
import { getActivePageIframe } from '../shared/page-iframe.js';
|
|
3
|
-
import { findElementBySid } from '
|
|
4
|
-
export { registerSyntheticSid } from '
|
|
3
|
+
import { findElementBySid } from '@dimina-kit/inspect';
|
|
4
|
+
export { registerSyntheticSid } from '@dimina-kit/inspect';
|
|
5
5
|
const state = {
|
|
6
6
|
appdata: { gen: 0, ready: true, data: {} },
|
|
7
7
|
storage: { gen: 0, ready: false, namespace: null, data: {} },
|