@dimina-kit/devtools 0.4.0-dev.20260615083030 → 0.4.0-dev.20260616024534
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/app/app.js +11 -0
- package/dist/main/app/lifecycle.d.ts +1 -0
- package/dist/main/app/lifecycle.js +10 -0
- package/dist/main/index.bundle.js +60 -42
- package/dist/main/runtime/miniapp-runtime.d.ts +4 -2
- package/dist/main/services/workbench-context.d.ts +9 -0
- package/dist/main/services/workbench-context.js +1 -0
- package/dist/main/services/workspace/workspace-service.js +13 -0
- package/dist/main/windows/main-window/create.d.ts +6 -0
- package/dist/main/windows/main-window/create.js +5 -1
- package/dist/shared/types.d.ts +17 -0
- package/package.json +4 -4
package/dist/main/app/app.js
CHANGED
|
@@ -6,6 +6,7 @@ import path from 'path';
|
|
|
6
6
|
import { rendererDir as defaultRendererDir, defaultPreloadPath } from '../utils/paths.js';
|
|
7
7
|
import { installThemeBackgroundSync } from '../utils/theme.js';
|
|
8
8
|
import { createMainWindow, wireMainWindowEvents } from '../windows/main-window/index.js';
|
|
9
|
+
import { isAppQuitting } from './lifecycle.js';
|
|
9
10
|
// eslint-disable-next-line no-restricted-syntax -- grandfathered(workbench-context): shrink-only
|
|
10
11
|
import { createWorkbenchContext } from '../services/workbench-context.js';
|
|
11
12
|
import { loadWorkbenchSettings, applyTheme } from '../services/settings/index.js';
|
|
@@ -131,6 +132,7 @@ function createConfiguredMainWindow(config, rendererDir) {
|
|
|
131
132
|
height: config.window?.height,
|
|
132
133
|
minWidth: config.window?.minWidth,
|
|
133
134
|
minHeight: config.window?.minHeight,
|
|
135
|
+
autoShow: config.window?.autoShow,
|
|
134
136
|
});
|
|
135
137
|
// Set window/taskbar icon if provided (Linux/Windows; macOS uses app bundle icon)
|
|
136
138
|
if (config.icon) {
|
|
@@ -157,6 +159,7 @@ function createContext(config, mainWindow, rendererDir) {
|
|
|
157
159
|
projectTemplates: config.projectTemplates,
|
|
158
160
|
builtinTemplates: config.builtinTemplates,
|
|
159
161
|
customCreateProjectDialog: config.customCreateProjectDialog,
|
|
162
|
+
onBeforeOpenProject: config.onBeforeOpenProject,
|
|
160
163
|
});
|
|
161
164
|
}
|
|
162
165
|
function registerBuiltinModules(config, context) {
|
|
@@ -229,6 +232,14 @@ function wireAppWindowEvents(config, instance) {
|
|
|
229
232
|
context,
|
|
230
233
|
onResize: () => context.views.repositionAll(),
|
|
231
234
|
onClose: async (e) => {
|
|
235
|
+
// A real application quit (⌘Q / menu "Quit" / app.quit()) fires
|
|
236
|
+
// `before-quit` first, then this window's `close`. Let it through so the
|
|
237
|
+
// app actually exits — do NOT convert it into "close the project".
|
|
238
|
+
// Without this, `hasActiveSession()` would be true and the quit gets
|
|
239
|
+
// swallowed into closeProject(), so the app can never be quit while a
|
|
240
|
+
// project is open.
|
|
241
|
+
if (isAppQuitting())
|
|
242
|
+
return;
|
|
232
243
|
if (!context.workspace.hasActiveSession())
|
|
233
244
|
return;
|
|
234
245
|
// Close button while a project session is open: stay in the workbench
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { app, globalShortcut } from 'electron';
|
|
2
|
+
// Flips to `true` once Electron's `before-quit` fires — a real application
|
|
3
|
+
// quit (⌘Q / menu "Quit" / app.quit()) is underway. `before-quit` is emitted
|
|
4
|
+
// BEFORE each window's `close` event, so the main-window onClose handler can
|
|
5
|
+
// read this to tell "the whole app is exiting" apart from "the user closed a
|
|
6
|
+
// single project window" and avoid swallowing the quit.
|
|
7
|
+
let appIsQuitting = false;
|
|
8
|
+
export function isAppQuitting() {
|
|
9
|
+
return appIsQuitting;
|
|
10
|
+
}
|
|
2
11
|
export function registerAppLifecycle() {
|
|
3
12
|
app.on('window-all-closed', () => {
|
|
4
13
|
globalShortcut.unregisterAll();
|
|
5
14
|
app.quit();
|
|
6
15
|
});
|
|
7
16
|
app.on('before-quit', () => {
|
|
17
|
+
appIsQuitting = true;
|
|
8
18
|
globalShortcut.unregisterAll();
|
|
9
19
|
});
|
|
10
20
|
}
|
|
@@ -761,7 +761,7 @@ function registerProjectFsIpc(ctx) {
|
|
|
761
761
|
}
|
|
762
762
|
|
|
763
763
|
// src/main/app/app.ts
|
|
764
|
-
import { app as
|
|
764
|
+
import { app as app15, BrowserWindow as BrowserWindow8, nativeImage, session as session4 } from "electron";
|
|
765
765
|
import fs10 from "fs";
|
|
766
766
|
import path21 from "path";
|
|
767
767
|
|
|
@@ -888,7 +888,9 @@ function createMainWindow(opts) {
|
|
|
888
888
|
if (process.env.NODE_ENV === "test") {
|
|
889
889
|
mainWindow.showInactive();
|
|
890
890
|
} else {
|
|
891
|
-
|
|
891
|
+
if (opts.autoShow !== false) {
|
|
892
|
+
mainWindow.show();
|
|
893
|
+
}
|
|
892
894
|
if (!app3.isPackaged && process.env.DIMINA_DEVTOOLS_MAIN_INSPECTOR === "1") {
|
|
893
895
|
mainWindow.webContents.openDevTools({ mode: "detach" });
|
|
894
896
|
}
|
|
@@ -943,6 +945,23 @@ function wireMainWindowEvents(win, state = {}) {
|
|
|
943
945
|
return registry;
|
|
944
946
|
}
|
|
945
947
|
|
|
948
|
+
// src/main/app/lifecycle.ts
|
|
949
|
+
import { app as app4, globalShortcut as globalShortcut2 } from "electron";
|
|
950
|
+
var appIsQuitting = false;
|
|
951
|
+
function isAppQuitting() {
|
|
952
|
+
return appIsQuitting;
|
|
953
|
+
}
|
|
954
|
+
function registerAppLifecycle() {
|
|
955
|
+
app4.on("window-all-closed", () => {
|
|
956
|
+
globalShortcut2.unregisterAll();
|
|
957
|
+
app4.quit();
|
|
958
|
+
});
|
|
959
|
+
app4.on("before-quit", () => {
|
|
960
|
+
appIsQuitting = true;
|
|
961
|
+
globalShortcut2.unregisterAll();
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
|
|
946
965
|
// src/main/services/workbench-context.ts
|
|
947
966
|
import {
|
|
948
967
|
createConnectionRegistry,
|
|
@@ -966,12 +985,12 @@ function createWorkbenchSenderPolicy(ctx) {
|
|
|
966
985
|
|
|
967
986
|
// src/main/services/default-adapter.ts
|
|
968
987
|
import path6 from "path";
|
|
969
|
-
import { app as
|
|
988
|
+
import { app as app5 } from "electron";
|
|
970
989
|
var defaultAdapter = {
|
|
971
990
|
async openProject(opts) {
|
|
972
991
|
const diminaKit = await import("@dimina-kit/devkit");
|
|
973
992
|
const openProjectOpts = {
|
|
974
|
-
outputDir: path6.join(
|
|
993
|
+
outputDir: path6.join(app5.getPath("userData"), "dimina-fe-output"),
|
|
975
994
|
...opts,
|
|
976
995
|
simulatorDir
|
|
977
996
|
};
|
|
@@ -2707,12 +2726,12 @@ async function openSettingsWindow(deps) {
|
|
|
2707
2726
|
import { z as z2 } from "zod";
|
|
2708
2727
|
|
|
2709
2728
|
// src/main/services/projects/project-repository.ts
|
|
2710
|
-
import { app as
|
|
2729
|
+
import { app as app6 } from "electron";
|
|
2711
2730
|
import path9 from "path";
|
|
2712
2731
|
import fs4 from "fs";
|
|
2713
2732
|
var log2 = createLogger("projects");
|
|
2714
2733
|
function getProjectsFile() {
|
|
2715
|
-
return path9.join(
|
|
2734
|
+
return path9.join(app6.getPath("userData"), "dimina-projects.json");
|
|
2716
2735
|
}
|
|
2717
2736
|
function load() {
|
|
2718
2737
|
try {
|
|
@@ -2927,6 +2946,13 @@ function createWorkspaceService(ctx) {
|
|
|
2927
2946
|
},
|
|
2928
2947
|
validateProjectDir: async (dirPath) => provider.validateProjectDir ? provider.validateProjectDir(dirPath) : null,
|
|
2929
2948
|
async openProject(projectPath) {
|
|
2949
|
+
if (ctx.onBeforeOpenProject) {
|
|
2950
|
+
try {
|
|
2951
|
+
await ctx.onBeforeOpenProject(projectPath);
|
|
2952
|
+
} catch (err) {
|
|
2953
|
+
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2930
2956
|
clearSimulatorServicewechatReferer();
|
|
2931
2957
|
logGeneration++;
|
|
2932
2958
|
await disposeSession();
|
|
@@ -3046,9 +3072,9 @@ function createWorkspaceService(ctx) {
|
|
|
3046
3072
|
import { createHash } from "crypto";
|
|
3047
3073
|
import fs5 from "fs";
|
|
3048
3074
|
import path10 from "path";
|
|
3049
|
-
import { app as
|
|
3075
|
+
import { app as app7 } from "electron";
|
|
3050
3076
|
function getThumbnailDir() {
|
|
3051
|
-
return path10.join(
|
|
3077
|
+
return path10.join(app7.getPath("userData"), "thumbnails");
|
|
3052
3078
|
}
|
|
3053
3079
|
function hashProjectPath(projectPath) {
|
|
3054
3080
|
return createHash("sha256").update(projectPath).digest("hex").slice(0, 16);
|
|
@@ -3157,6 +3183,7 @@ function createWorkbenchContext(opts) {
|
|
|
3157
3183
|
opts.builtinTemplates ?? "all"
|
|
3158
3184
|
);
|
|
3159
3185
|
ctx.customCreateProjectDialog = opts.customCreateProjectDialog;
|
|
3186
|
+
ctx.onBeforeOpenProject = opts.onBeforeOpenProject;
|
|
3160
3187
|
ctx.workspace = createWorkspaceService(ctx);
|
|
3161
3188
|
ctx.senderPolicy = createWorkbenchSenderPolicy(ctx);
|
|
3162
3189
|
return ctx;
|
|
@@ -3463,7 +3490,7 @@ var popoverModule = {
|
|
|
3463
3490
|
};
|
|
3464
3491
|
|
|
3465
3492
|
// src/main/ipc/projects.ts
|
|
3466
|
-
import { app as
|
|
3493
|
+
import { app as app8, dialog } from "electron";
|
|
3467
3494
|
import path13 from "path";
|
|
3468
3495
|
|
|
3469
3496
|
// src/main/services/projects/create-project-service.ts
|
|
@@ -3617,7 +3644,7 @@ function registerProjectsIpc(ctx) {
|
|
|
3617
3644
|
}
|
|
3618
3645
|
function safeAppPath(name) {
|
|
3619
3646
|
try {
|
|
3620
|
-
return
|
|
3647
|
+
return app8.getPath(name);
|
|
3621
3648
|
} catch {
|
|
3622
3649
|
return null;
|
|
3623
3650
|
}
|
|
@@ -3671,7 +3698,7 @@ var sessionModule = {
|
|
|
3671
3698
|
};
|
|
3672
3699
|
|
|
3673
3700
|
// src/main/ipc/settings.ts
|
|
3674
|
-
import { app as
|
|
3701
|
+
import { app as app9 } from "electron";
|
|
3675
3702
|
|
|
3676
3703
|
// src/main/services/mcp/status.ts
|
|
3677
3704
|
var status = { running: false, port: null, error: null };
|
|
@@ -3710,8 +3737,8 @@ function registerSettingsIpc(ctx) {
|
|
|
3710
3737
|
applyTheme(theme);
|
|
3711
3738
|
}).handle(WorkbenchSettingsChannel.GetCdpStatus, () => {
|
|
3712
3739
|
const settings = loadWorkbenchSettings();
|
|
3713
|
-
const switchValue =
|
|
3714
|
-
const implicitDevDefault = !
|
|
3740
|
+
const switchValue = app9.commandLine.getSwitchValue("remote-debugging-port");
|
|
3741
|
+
const implicitDevDefault = !app9.isPackaged && !settings.cdp.enabled && switchValue === String(DEFAULT_CDP_PORT);
|
|
3715
3742
|
return {
|
|
3716
3743
|
configured: settings.cdp.enabled,
|
|
3717
3744
|
port: settings.cdp.port,
|
|
@@ -3772,7 +3799,7 @@ var settingsModule = {
|
|
|
3772
3799
|
import { DisposableRegistry as DisposableRegistry6 } from "@dimina-kit/electron-deck/main";
|
|
3773
3800
|
|
|
3774
3801
|
// src/main/ipc/bridge-router.ts
|
|
3775
|
-
import { app as
|
|
3802
|
+
import { app as app12, ipcMain as ipcMain3, protocol as protocol2, session as electronSession, webContents as webContents2 } from "electron";
|
|
3776
3803
|
import path16 from "node:path";
|
|
3777
3804
|
import { pathToFileURL as pathToFileURL3 } from "node:url";
|
|
3778
3805
|
|
|
@@ -3880,7 +3907,7 @@ function setCorsHeaders(res) {
|
|
|
3880
3907
|
}
|
|
3881
3908
|
|
|
3882
3909
|
// src/main/windows/service-host-window/create.ts
|
|
3883
|
-
import { app as
|
|
3910
|
+
import { app as app10, BrowserWindow as BrowserWindow4 } from "electron";
|
|
3884
3911
|
import path15 from "node:path";
|
|
3885
3912
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
3886
3913
|
var SERVICE_HOST_PARTITION = SHARED_MINIAPP_PARTITION;
|
|
@@ -3921,7 +3948,7 @@ function navigateServiceHost(win, url) {
|
|
|
3921
3948
|
() => void 0,
|
|
3922
3949
|
() => void 0
|
|
3923
3950
|
);
|
|
3924
|
-
if (!
|
|
3951
|
+
if (!app10.isPackaged && process.env.NODE_ENV !== "test") {
|
|
3925
3952
|
const w = win;
|
|
3926
3953
|
if (w.__diminaDevToolsHook) {
|
|
3927
3954
|
try {
|
|
@@ -4318,7 +4345,7 @@ function createConsoleForwarder(bridge) {
|
|
|
4318
4345
|
}
|
|
4319
4346
|
|
|
4320
4347
|
// src/main/services/simulator-storage/index.ts
|
|
4321
|
-
import { app as
|
|
4348
|
+
import { app as app11, webContents as wcStatic } from "electron";
|
|
4322
4349
|
import { DisposableRegistry as DisposableRegistry5 } from "@dimina-kit/electron-deck/main";
|
|
4323
4350
|
|
|
4324
4351
|
// src/main/services/simulator-storage/service-storage-ops.ts
|
|
@@ -4688,9 +4715,9 @@ function setupSimulatorStorage(host, options) {
|
|
|
4688
4715
|
}
|
|
4689
4716
|
}
|
|
4690
4717
|
};
|
|
4691
|
-
|
|
4718
|
+
app11.on("web-contents-created", onWcCreated);
|
|
4692
4719
|
registry.add(() => {
|
|
4693
|
-
|
|
4720
|
+
app11.removeListener("web-contents-created", onWcCreated);
|
|
4694
4721
|
});
|
|
4695
4722
|
registry.add(async () => {
|
|
4696
4723
|
const subs = Array.from(wcSubs.values());
|
|
@@ -5864,7 +5891,7 @@ function makeHostEnv(snapshot) {
|
|
|
5864
5891
|
windowWidth: 390,
|
|
5865
5892
|
windowHeight: 844,
|
|
5866
5893
|
statusBarHeight: 24,
|
|
5867
|
-
language:
|
|
5894
|
+
language: app12.getLocale(),
|
|
5868
5895
|
theme: "light",
|
|
5869
5896
|
...snapshot
|
|
5870
5897
|
};
|
|
@@ -8661,7 +8688,7 @@ function setupSimulatorSessionPolicy() {
|
|
|
8661
8688
|
}
|
|
8662
8689
|
|
|
8663
8690
|
// src/main/services/update/update-manager.ts
|
|
8664
|
-
import { app as
|
|
8691
|
+
import { app as app13, shell as shell3 } from "electron";
|
|
8665
8692
|
var UpdateManager = class {
|
|
8666
8693
|
checker;
|
|
8667
8694
|
mainWindow;
|
|
@@ -8684,7 +8711,7 @@ var UpdateManager = class {
|
|
|
8684
8711
|
constructor(opts) {
|
|
8685
8712
|
this.checker = opts.checker;
|
|
8686
8713
|
this.mainWindow = opts.mainWindow;
|
|
8687
|
-
this.getCurrentVersion = opts.getCurrentVersion ?? (() =>
|
|
8714
|
+
this.getCurrentVersion = opts.getCurrentVersion ?? (() => app13.getVersion());
|
|
8688
8715
|
this.ipc = new IpcRegistry(opts.senderPolicy);
|
|
8689
8716
|
this.registerIpc();
|
|
8690
8717
|
this.startPeriodicCheck(opts.checkInterval ?? 60 * 60 * 1e3, opts.initialDelay ?? 5e3);
|
|
@@ -8725,7 +8752,7 @@ var UpdateManager = class {
|
|
|
8725
8752
|
install() {
|
|
8726
8753
|
if (this.downloadedPath) {
|
|
8727
8754
|
shell3.openPath(this.downloadedPath);
|
|
8728
|
-
|
|
8755
|
+
app13.quit();
|
|
8729
8756
|
}
|
|
8730
8757
|
}
|
|
8731
8758
|
/**
|
|
@@ -8759,7 +8786,7 @@ var UpdateManager = class {
|
|
|
8759
8786
|
};
|
|
8760
8787
|
|
|
8761
8788
|
// src/main/services/update/github-release-checker.ts
|
|
8762
|
-
import { app as
|
|
8789
|
+
import { app as app14 } from "electron";
|
|
8763
8790
|
|
|
8764
8791
|
// src/main/app/app.ts
|
|
8765
8792
|
import { toDisposable as toDisposable8 } from "@dimina-kit/electron-deck/main";
|
|
@@ -8834,7 +8861,8 @@ function createConfiguredMainWindow(config, rendererDir2) {
|
|
|
8834
8861
|
width: config.window?.width,
|
|
8835
8862
|
height: config.window?.height,
|
|
8836
8863
|
minWidth: config.window?.minWidth,
|
|
8837
|
-
minHeight: config.window?.minHeight
|
|
8864
|
+
minHeight: config.window?.minHeight,
|
|
8865
|
+
autoShow: config.window?.autoShow
|
|
8838
8866
|
});
|
|
8839
8867
|
if (config.icon) {
|
|
8840
8868
|
const icon = nativeImage.createFromPath(config.icon);
|
|
@@ -8858,7 +8886,8 @@ function createContext(config, mainWindow, rendererDir2) {
|
|
|
8858
8886
|
projectsProvider: config.projectsProvider,
|
|
8859
8887
|
projectTemplates: config.projectTemplates,
|
|
8860
8888
|
builtinTemplates: config.builtinTemplates,
|
|
8861
|
-
customCreateProjectDialog: config.customCreateProjectDialog
|
|
8889
|
+
customCreateProjectDialog: config.customCreateProjectDialog,
|
|
8890
|
+
onBeforeOpenProject: config.onBeforeOpenProject
|
|
8862
8891
|
});
|
|
8863
8892
|
}
|
|
8864
8893
|
function registerBuiltinModules(config, context) {
|
|
@@ -8903,7 +8932,7 @@ async function setupAutomation(instance) {
|
|
|
8903
8932
|
function setupMcp() {
|
|
8904
8933
|
const settings = loadWorkbenchSettings();
|
|
8905
8934
|
if (!settings.mcp.enabled) return null;
|
|
8906
|
-
const cdpPortSwitch =
|
|
8935
|
+
const cdpPortSwitch = app15.commandLine.getSwitchValue("remote-debugging-port");
|
|
8907
8936
|
const cdpPort2 = cdpPortSwitch ? parseInt(cdpPortSwitch, 10) : settings.cdp.port;
|
|
8908
8937
|
return startMcpServer(cdpPort2, settings.mcp.port);
|
|
8909
8938
|
}
|
|
@@ -8914,6 +8943,7 @@ function wireAppWindowEvents(config, instance) {
|
|
|
8914
8943
|
context,
|
|
8915
8944
|
onResize: () => context.views.repositionAll(),
|
|
8916
8945
|
onClose: async (e) => {
|
|
8946
|
+
if (isAppQuitting()) return;
|
|
8917
8947
|
if (!context.workspace.hasActiveSession()) return;
|
|
8918
8948
|
e.preventDefault();
|
|
8919
8949
|
if (closing) return;
|
|
@@ -8931,7 +8961,7 @@ function wireAppWindowEvents(config, instance) {
|
|
|
8931
8961
|
});
|
|
8932
8962
|
}
|
|
8933
8963
|
function enableDevRendererAutoReload(rendererDir2) {
|
|
8934
|
-
if (
|
|
8964
|
+
if (app15.isPackaged) {
|
|
8935
8965
|
return toDisposable8(() => {
|
|
8936
8966
|
});
|
|
8937
8967
|
}
|
|
@@ -8954,7 +8984,7 @@ function enableDevRendererAutoReload(rendererDir2) {
|
|
|
8954
8984
|
}
|
|
8955
8985
|
function runDevtoolsBootstrap(config = {}) {
|
|
8956
8986
|
try {
|
|
8957
|
-
|
|
8987
|
+
app15.setName(config.appName ?? "Dimina DevTools");
|
|
8958
8988
|
} catch {
|
|
8959
8989
|
}
|
|
8960
8990
|
setupCdpPort();
|
|
@@ -8962,7 +8992,7 @@ function runDevtoolsBootstrap(config = {}) {
|
|
|
8962
8992
|
registerDifileScheme();
|
|
8963
8993
|
}
|
|
8964
8994
|
async function createDevtoolsRuntime(config = {}) {
|
|
8965
|
-
await
|
|
8995
|
+
await app15.whenReady();
|
|
8966
8996
|
applyTheme(loadWorkbenchSettings().theme);
|
|
8967
8997
|
const rendererDir2 = config.rendererDir ?? rendererDir;
|
|
8968
8998
|
const mainWindow = createConfiguredMainWindow(config, rendererDir2);
|
|
@@ -9111,18 +9141,6 @@ async function createDevtoolsRuntime(config = {}) {
|
|
|
9111
9141
|
return instance;
|
|
9112
9142
|
}
|
|
9113
9143
|
|
|
9114
|
-
// src/main/app/lifecycle.ts
|
|
9115
|
-
import { app as app15, globalShortcut as globalShortcut2 } from "electron";
|
|
9116
|
-
function registerAppLifecycle() {
|
|
9117
|
-
app15.on("window-all-closed", () => {
|
|
9118
|
-
globalShortcut2.unregisterAll();
|
|
9119
|
-
app15.quit();
|
|
9120
|
-
});
|
|
9121
|
-
app15.on("before-quit", () => {
|
|
9122
|
-
globalShortcut2.unregisterAll();
|
|
9123
|
-
});
|
|
9124
|
-
}
|
|
9125
|
-
|
|
9126
9144
|
// src/main/runtime/devtools-backend.ts
|
|
9127
9145
|
function createDevtoolsBackend(config = {}) {
|
|
9128
9146
|
let instance = null;
|
|
@@ -15,8 +15,10 @@
|
|
|
15
15
|
* syntax: under strictFunctionTypes method signatures compare bivariantly,
|
|
16
16
|
* which would let a wrongly-narrowed implementation or host override slip
|
|
17
17
|
* past the drift sentinel.
|
|
18
|
-
* - `workspace.openProject` stays writable (no `readonly`)
|
|
19
|
-
*
|
|
18
|
+
* - `workspace.openProject` stays writable (no `readonly`) for backward
|
|
19
|
+
* compat: hosts MAY still gate permissions by reassigning it. The preferred
|
|
20
|
+
* path is now the declarative `WorkbenchAppConfig.onBeforeOpenProject` hook
|
|
21
|
+
* (runs before any side effect, throw to veto) — see host-migration.md §7.
|
|
20
22
|
*
|
|
21
23
|
* `asMiniappRuntime(ctx)` is an identity return — the contract is a typed
|
|
22
24
|
* VIEW onto the live context, not a snapshot/projection. That is what makes
|
|
@@ -74,6 +74,13 @@ export interface WorkbenchContext {
|
|
|
74
74
|
parentWindow: BrowserWindow;
|
|
75
75
|
templates: ProjectTemplate[];
|
|
76
76
|
}) => Promise<CustomCreateProjectDialogResult>;
|
|
77
|
+
/**
|
|
78
|
+
* Host permission gate consulted by `workspace.openProject` BEFORE any side
|
|
79
|
+
* effect. Throwing vetoes the open (see `WorkbenchAppConfig.onBeforeOpenProject`).
|
|
80
|
+
* Wired from the config by `createDevtoolsRuntime`; undefined for the
|
|
81
|
+
* single-tenant default.
|
|
82
|
+
*/
|
|
83
|
+
onBeforeOpenProject?: (projectPath: string) => void | Promise<void>;
|
|
77
84
|
/**
|
|
78
85
|
* Trust predicate consulted by `IpcRegistry` for every incoming IPC.
|
|
79
86
|
* Resolves the currently-trusted senders (main renderer + overlays)
|
|
@@ -183,6 +190,8 @@ export interface CreateContextOptions extends Pick<WorkbenchConfig, 'adapter' |
|
|
|
183
190
|
builtinTemplates?: 'all' | 'none' | readonly string[];
|
|
184
191
|
/** Host-supplied "新建项目" dialog hook. */
|
|
185
192
|
customCreateProjectDialog?: WorkbenchContext['customCreateProjectDialog'];
|
|
193
|
+
/** Host permission gate run before a project opens (throw to veto). */
|
|
194
|
+
onBeforeOpenProject?: WorkbenchContext['onBeforeOpenProject'];
|
|
186
195
|
}
|
|
187
196
|
export declare function createWorkbenchContext(opts: CreateContextOptions): WorkbenchContext;
|
|
188
197
|
export { sanitizeTemplates };
|
|
@@ -37,6 +37,7 @@ export function createWorkbenchContext(opts) {
|
|
|
37
37
|
ctx.projectsProvider = opts.projectsProvider ?? createLocalProjectsProvider();
|
|
38
38
|
ctx.projectTemplates = resolveTemplates(BUILTIN_TEMPLATES, opts.projectTemplates ?? [], opts.builtinTemplates ?? 'all');
|
|
39
39
|
ctx.customCreateProjectDialog = opts.customCreateProjectDialog;
|
|
40
|
+
ctx.onBeforeOpenProject = opts.onBeforeOpenProject;
|
|
40
41
|
ctx.workspace = createWorkspaceService(ctx);
|
|
41
42
|
ctx.senderPolicy = createWorkbenchSenderPolicy(ctx);
|
|
42
43
|
return ctx;
|
|
@@ -80,6 +80,19 @@ export function createWorkspaceService(ctx) {
|
|
|
80
80
|
? provider.validateProjectDir(dirPath)
|
|
81
81
|
: null,
|
|
82
82
|
async openProject(projectPath) {
|
|
83
|
+
// Host permission gate — runs BEFORE any side effect (referer reset,
|
|
84
|
+
// session teardown, compile/dev-server spin-up). A throwing hook vetoes
|
|
85
|
+
// the open: return early with the error and leave the currently-active
|
|
86
|
+
// session fully intact. The declarative replacement for monkey-patching
|
|
87
|
+
// this method. See WorkbenchAppConfig.onBeforeOpenProject.
|
|
88
|
+
if (ctx.onBeforeOpenProject) {
|
|
89
|
+
try {
|
|
90
|
+
await ctx.onBeforeOpenProject(projectPath);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
83
96
|
clearSimulatorServicewechatReferer();
|
|
84
97
|
// Invalidate the outgoing session's onLog BEFORE teardown starts (same
|
|
85
98
|
// order as closeProject below): the dying compile worker flushes
|
|
@@ -6,6 +6,12 @@ export interface WindowOptions {
|
|
|
6
6
|
minWidth?: number;
|
|
7
7
|
minHeight?: number;
|
|
8
8
|
indexHtml: string;
|
|
9
|
+
/**
|
|
10
|
+
* Auto-show the window on `ready-to-show` in non-test envs. Defaults to
|
|
11
|
+
* `true`. `false` lets a login-gating host keep the window hidden and call
|
|
12
|
+
* `show()` itself. The test env always uses `showInactive()` regardless.
|
|
13
|
+
*/
|
|
14
|
+
autoShow?: boolean;
|
|
9
15
|
}
|
|
10
16
|
export declare function createMainWindow(opts: WindowOptions): BrowserWindow;
|
|
11
17
|
//# sourceMappingURL=create.d.ts.map
|
|
@@ -26,7 +26,11 @@ export function createMainWindow(opts) {
|
|
|
26
26
|
mainWindow.showInactive();
|
|
27
27
|
}
|
|
28
28
|
else {
|
|
29
|
-
|
|
29
|
+
// A login-gating host opts out via `autoShow: false` and shows the
|
|
30
|
+
// window itself once auth passes — don't flash an un-authed window.
|
|
31
|
+
if (opts.autoShow !== false) {
|
|
32
|
+
mainWindow.show();
|
|
33
|
+
}
|
|
30
34
|
// Don't auto-open a detached DevTools for the devtools UI shell itself —
|
|
31
35
|
// it's noise for normal use (the mini-app's Console lives in the embedded
|
|
32
36
|
// right-panel DevTools, not here). Opt in via env for debugging the shell.
|
package/dist/shared/types.d.ts
CHANGED
|
@@ -108,6 +108,14 @@ export interface WorkbenchWindowConfig {
|
|
|
108
108
|
height?: number;
|
|
109
109
|
minWidth?: number;
|
|
110
110
|
minHeight?: number;
|
|
111
|
+
/**
|
|
112
|
+
* Auto-show the main window on `ready-to-show`. Defaults to `true`. Set
|
|
113
|
+
* `false` when the host gates the window behind its own startup flow (e.g. a
|
|
114
|
+
* login screen) and wants to call `mainWindow.show()` itself once ready —
|
|
115
|
+
* avoids an un-authed window flashing on screen. Does not affect the test
|
|
116
|
+
* environment, which always uses `showInactive()` (e2e depends on it).
|
|
117
|
+
*/
|
|
118
|
+
autoShow?: boolean;
|
|
111
119
|
}
|
|
112
120
|
export interface UpdateInfo {
|
|
113
121
|
/** New version string (e.g. '1.2.0') */
|
|
@@ -205,6 +213,15 @@ export interface WorkbenchAppConfig extends WorkbenchConfig {
|
|
|
205
213
|
onSetup?: (instance: WorkbenchHostInstance) => void | Promise<void>;
|
|
206
214
|
/** Called before window close when a session is active. Session disposal happens automatically after this hook. */
|
|
207
215
|
onBeforeClose?: (instance: WorkbenchHostInstance) => void | Promise<void>;
|
|
216
|
+
/**
|
|
217
|
+
* Called before a project is opened, BEFORE any side effect (session
|
|
218
|
+
* teardown, compile, dev-server). Use to gate the open on login/permission
|
|
219
|
+
* state. THROW to veto: `openProject` then resolves `{ success: false,
|
|
220
|
+
* error }`, leaves any currently-active session untouched, and never spins
|
|
221
|
+
* up the adapter. Resolve normally (or omit) to allow the open. The
|
|
222
|
+
* declarative alternative to monkey-patching `workspace.openProject`.
|
|
223
|
+
*/
|
|
224
|
+
onBeforeOpenProject?: (projectPath: string) => void | Promise<void>;
|
|
208
225
|
/** Custom update checker. If provided, enables the check-for-updates feature. */
|
|
209
226
|
updateChecker?: UpdateChecker;
|
|
210
227
|
/** Extra options applied when an updateChecker is provided. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dimina-kit/devtools",
|
|
3
|
-
"version": "0.4.0-dev.
|
|
3
|
+
"version": "0.4.0-dev.20260616024534",
|
|
4
4
|
"description": "Dimina DevTools - modular developer tools for mini app debugging",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dimina",
|
|
@@ -86,9 +86,9 @@
|
|
|
86
86
|
"monaco-editor": "^0.55.1",
|
|
87
87
|
"ws": "^8.20.0",
|
|
88
88
|
"zod": "^4.3.6",
|
|
89
|
-
"@dimina-kit/devkit": "0.1.2-dev.
|
|
90
|
-
"@dimina-kit/view-anchor": "0.1.0-dev.
|
|
91
|
-
"@dimina-kit/electron-deck": "0.1.0-dev.
|
|
89
|
+
"@dimina-kit/devkit": "0.1.2-dev.20260616024534",
|
|
90
|
+
"@dimina-kit/view-anchor": "0.1.0-dev.20260616024534",
|
|
91
|
+
"@dimina-kit/electron-deck": "0.1.0-dev.20260616024534"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@playwright/test": "^1.59.1",
|