@dimina-kit/devtools 0.1.0 → 0.2.0-dev.20260424031451
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/api.d.ts +3 -1
- package/dist/main/api.js +2 -0
- package/dist/main/app/app.d.ts +2 -0
- package/dist/main/app/app.js +29 -7
- package/dist/main/index.bundle.js +2716 -0
- package/dist/main/services/automation/index.d.ts +2 -1
- package/dist/main/services/automation/index.js +28 -4
- package/dist/main/services/projects/project-repository.js +6 -0
- package/dist/main/services/simulator-storage/index.d.ts +20 -0
- package/dist/main/services/simulator-storage/index.js +136 -0
- package/dist/main/services/update/github-release-checker.d.ts +49 -0
- package/dist/main/services/update/github-release-checker.js +248 -0
- package/dist/main/services/update/index.d.ts +5 -0
- package/dist/main/services/update/index.js +3 -0
- package/dist/main/services/update/update-manager.d.ts +37 -0
- package/dist/main/services/update/update-manager.js +90 -0
- package/dist/main/services/workspace/workspace-service.js +12 -0
- package/dist/preload/instrumentation/index.d.ts +0 -1
- package/dist/preload/instrumentation/index.js +0 -1
- package/dist/preload/windows/main.d.ts +0 -1
- package/dist/preload/windows/main.js +0 -1
- package/dist/preload/windows/simulator.js +1 -109
- package/dist/renderer/assets/index-D_HFRqZA.js +46 -0
- package/dist/renderer/assets/{input-B7sz4y1r.js → input-VLotwer2.js} +2 -2
- package/dist/renderer/assets/ipc-transport-6Gy3FXIL.css +1 -0
- package/dist/renderer/assets/{ipc-transport-L_WD9x12.js → ipc-transport-COKIC6Ny.js} +6 -6
- package/dist/renderer/assets/{popover-CzMIs2j4.js → popover-Dn0RwMLI.js} +2 -2
- package/dist/renderer/assets/{select-BBXJVe8R.js → select-DzIsLaKX.js} +2 -2
- package/dist/renderer/assets/{settings-Db1pvrBJ.js → settings-CD-dacWB.js} +2 -2
- package/dist/renderer/assets/settings-api-BV9MPckG.js +2 -0
- package/dist/renderer/assets/{workbenchSettings-BnQsvWkQ.js → workbenchSettings-ClwgsvJL.js} +2 -2
- package/dist/renderer/entries/main/index.html +5 -5
- 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 +26 -3
- package/dist/shared/ipc-channels.js +10 -3
- package/dist/shared/types.d.ts +27 -0
- package/package.json +6 -4
- package/dist/main/api.d.ts.map +0 -1
- package/dist/main/api.js.map +0 -1
- package/dist/main/app/app.d.ts.map +0 -1
- package/dist/main/app/app.js.map +0 -1
- package/dist/main/app/bootstrap.d.ts.map +0 -1
- package/dist/main/app/bootstrap.js.map +0 -1
- package/dist/main/app/launch.d.ts.map +0 -1
- package/dist/main/app/launch.js.map +0 -1
- package/dist/main/app/lifecycle.d.ts.map +0 -1
- package/dist/main/app/lifecycle.js.map +0 -1
- package/dist/main/index.d.ts.map +0 -1
- package/dist/main/index.js.map +0 -1
- package/dist/main/ipc/app.d.ts.map +0 -1
- package/dist/main/ipc/app.js.map +0 -1
- package/dist/main/ipc/index.d.ts.map +0 -1
- package/dist/main/ipc/index.js.map +0 -1
- package/dist/main/ipc/panels.d.ts.map +0 -1
- package/dist/main/ipc/panels.js.map +0 -1
- package/dist/main/ipc/popover.d.ts.map +0 -1
- package/dist/main/ipc/popover.js.map +0 -1
- package/dist/main/ipc/projects.d.ts.map +0 -1
- package/dist/main/ipc/projects.js.map +0 -1
- package/dist/main/ipc/session.d.ts.map +0 -1
- package/dist/main/ipc/session.js.map +0 -1
- package/dist/main/ipc/settings.d.ts.map +0 -1
- package/dist/main/ipc/settings.js.map +0 -1
- package/dist/main/ipc/simulator.d.ts.map +0 -1
- package/dist/main/ipc/simulator.js.map +0 -1
- package/dist/main/ipc/toolbar.d.ts.map +0 -1
- package/dist/main/ipc/toolbar.js.map +0 -1
- package/dist/main/menu/index.d.ts.map +0 -1
- package/dist/main/menu/index.js.map +0 -1
- package/dist/main/services/automation/exec.d.ts.map +0 -1
- package/dist/main/services/automation/exec.js.map +0 -1
- package/dist/main/services/automation/handlers/app.d.ts.map +0 -1
- package/dist/main/services/automation/handlers/app.js.map +0 -1
- package/dist/main/services/automation/handlers/element.d.ts.map +0 -1
- package/dist/main/services/automation/handlers/element.js.map +0 -1
- package/dist/main/services/automation/handlers/page.d.ts.map +0 -1
- package/dist/main/services/automation/handlers/page.js.map +0 -1
- package/dist/main/services/automation/handlers/tool.d.ts.map +0 -1
- package/dist/main/services/automation/handlers/tool.js.map +0 -1
- package/dist/main/services/automation/index.d.ts.map +0 -1
- package/dist/main/services/automation/index.js.map +0 -1
- package/dist/main/services/automation/registry.d.ts.map +0 -1
- package/dist/main/services/automation/registry.js.map +0 -1
- package/dist/main/services/automation/shared.d.ts.map +0 -1
- package/dist/main/services/automation/shared.js.map +0 -1
- package/dist/main/services/default-adapter.d.ts.map +0 -1
- package/dist/main/services/default-adapter.js.map +0 -1
- package/dist/main/services/layout/index.d.ts.map +0 -1
- package/dist/main/services/layout/index.js.map +0 -1
- package/dist/main/services/mcp/index.d.ts.map +0 -1
- package/dist/main/services/mcp/index.js.map +0 -1
- package/dist/main/services/mcp/server.d.ts.map +0 -1
- package/dist/main/services/mcp/server.js.map +0 -1
- package/dist/main/services/mcp/target-manager.d.ts.map +0 -1
- package/dist/main/services/mcp/target-manager.js.map +0 -1
- package/dist/main/services/mcp/tool-registry.d.ts.map +0 -1
- package/dist/main/services/mcp/tool-registry.js.map +0 -1
- package/dist/main/services/mcp/tools/context-tools.d.ts.map +0 -1
- package/dist/main/services/mcp/tools/context-tools.js.map +0 -1
- package/dist/main/services/mcp/tools/simulator-tools.d.ts.map +0 -1
- package/dist/main/services/mcp/tools/simulator-tools.js.map +0 -1
- package/dist/main/services/mcp/tools/workbench-tools.d.ts.map +0 -1
- package/dist/main/services/mcp/tools/workbench-tools.js.map +0 -1
- package/dist/main/services/notifications/renderer-notifier.d.ts.map +0 -1
- package/dist/main/services/notifications/renderer-notifier.js.map +0 -1
- package/dist/main/services/projects/index.d.ts.map +0 -1
- package/dist/main/services/projects/index.js.map +0 -1
- package/dist/main/services/projects/project-repository.d.ts.map +0 -1
- package/dist/main/services/projects/project-repository.js.map +0 -1
- package/dist/main/services/settings/index.d.ts.map +0 -1
- package/dist/main/services/settings/index.js.map +0 -1
- package/dist/main/services/simulator/dir.d.ts.map +0 -1
- package/dist/main/services/simulator/dir.js.map +0 -1
- package/dist/main/services/simulator/referer.d.ts.map +0 -1
- package/dist/main/services/simulator/referer.js.map +0 -1
- package/dist/main/services/views/view-manager.d.ts.map +0 -1
- package/dist/main/services/views/view-manager.js.map +0 -1
- package/dist/main/services/workbench-context.d.ts.map +0 -1
- package/dist/main/services/workbench-context.js.map +0 -1
- package/dist/main/services/workspace/index.d.ts.map +0 -1
- package/dist/main/services/workspace/index.js.map +0 -1
- package/dist/main/services/workspace/workspace-service.d.ts.map +0 -1
- package/dist/main/services/workspace/workspace-service.js.map +0 -1
- package/dist/main/utils/logger.d.ts.map +0 -1
- package/dist/main/utils/logger.js.map +0 -1
- package/dist/main/utils/paths.d.ts.map +0 -1
- package/dist/main/utils/paths.js.map +0 -1
- package/dist/main/utils/theme.d.ts.map +0 -1
- package/dist/main/utils/theme.js.map +0 -1
- package/dist/main/windows/main-window/create.d.ts.map +0 -1
- package/dist/main/windows/main-window/create.js.map +0 -1
- package/dist/main/windows/main-window/events.d.ts.map +0 -1
- package/dist/main/windows/main-window/events.js.map +0 -1
- package/dist/main/windows/main-window/index.d.ts.map +0 -1
- package/dist/main/windows/main-window/index.js.map +0 -1
- package/dist/main/windows/settings-window/create.d.ts.map +0 -1
- package/dist/main/windows/settings-window/create.js.map +0 -1
- package/dist/main/windows/settings-window/events.d.ts.map +0 -1
- package/dist/main/windows/settings-window/events.js.map +0 -1
- package/dist/main/windows/settings-window/index.d.ts.map +0 -1
- package/dist/main/windows/settings-window/index.js.map +0 -1
- package/dist/preload/instrumentation/app-data.d.ts.map +0 -1
- package/dist/preload/instrumentation/app-data.js.map +0 -1
- package/dist/preload/instrumentation/console.d.ts.map +0 -1
- package/dist/preload/instrumentation/console.js.map +0 -1
- package/dist/preload/instrumentation/disposable.d.ts.map +0 -1
- package/dist/preload/instrumentation/disposable.js.map +0 -1
- package/dist/preload/instrumentation/index.d.ts.map +0 -1
- package/dist/preload/instrumentation/index.js.map +0 -1
- package/dist/preload/instrumentation/storage.d.ts +0 -2
- package/dist/preload/instrumentation/storage.d.ts.map +0 -1
- package/dist/preload/instrumentation/storage.js +0 -106
- package/dist/preload/instrumentation/storage.js.map +0 -1
- package/dist/preload/instrumentation/wxml-extract.d.ts.map +0 -1
- package/dist/preload/instrumentation/wxml-extract.js.map +0 -1
- package/dist/preload/instrumentation/wxml.d.ts.map +0 -1
- package/dist/preload/instrumentation/wxml.js.map +0 -1
- package/dist/preload/runtime/bridge.d.ts.map +0 -1
- package/dist/preload/runtime/bridge.js.map +0 -1
- package/dist/preload/runtime/host.d.ts.map +0 -1
- package/dist/preload/runtime/host.js.map +0 -1
- package/dist/preload/shared/api-compat.d.ts.map +0 -1
- package/dist/preload/shared/api-compat.js.map +0 -1
- package/dist/preload/shared/constants.d.ts.map +0 -1
- package/dist/preload/shared/constants.js.map +0 -1
- package/dist/preload/shared/types.d.ts.map +0 -1
- package/dist/preload/shared/types.js.map +0 -1
- package/dist/preload/windows/main.d.ts.map +0 -1
- package/dist/preload/windows/main.js.map +0 -1
- package/dist/preload/windows/simulator.js.map +0 -7
- package/dist/renderer/assets/index-kcmIQPCg.js +0 -2
- package/dist/renderer/assets/index-kcmIQPCg.js.map +0 -1
- package/dist/renderer/assets/input-B7sz4y1r.js.map +0 -1
- package/dist/renderer/assets/ipc-transport-C9-PPTGn.css +0 -1
- package/dist/renderer/assets/ipc-transport-L_WD9x12.js.map +0 -1
- package/dist/renderer/assets/popover-CzMIs2j4.js.map +0 -1
- package/dist/renderer/assets/select-BBXJVe8R.js.map +0 -1
- package/dist/renderer/assets/settings-Db1pvrBJ.js.map +0 -1
- package/dist/renderer/assets/settings-api-DJ1M-CNt.js +0 -2
- package/dist/renderer/assets/settings-api-DJ1M-CNt.js.map +0 -1
- package/dist/renderer/assets/workbenchSettings-BnQsvWkQ.js.map +0 -1
- package/dist/shared/constants.d.ts.map +0 -1
- package/dist/shared/constants.js.map +0 -1
- package/dist/shared/ipc-channels.d.ts.map +0 -1
- package/dist/shared/ipc-channels.js.map +0 -1
- package/dist/shared/types.d.ts.map +0 -1
- package/dist/shared/types.js.map +0 -1
- package/dist/simulator/assets/simulator-C1eHXnuq.js.map +0 -1
|
@@ -14,5 +14,6 @@ export interface AutomationServer {
|
|
|
14
14
|
close: () => void;
|
|
15
15
|
port: number;
|
|
16
16
|
}
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function getAutomationPort(): number | null;
|
|
18
|
+
export declare function startAutomationServer(ctx: WorkbenchContext, port?: number): Promise<AutomationServer>;
|
|
18
19
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
* This server handles these messages by delegating to the workbench context
|
|
10
10
|
* (simulator webContents, IPC handlers, etc.) without modifying dimina upstream.
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
import { ipcMain } from 'electron';
|
|
13
13
|
import { WebSocketServer } from 'ws';
|
|
14
|
-
import { SimulatorChannel } from '../../../shared/ipc-channels.js';
|
|
14
|
+
import { AutomationChannel, SimulatorChannel } from '../../../shared/ipc-channels.js';
|
|
15
15
|
import { getSimulator } from './exec.js';
|
|
16
16
|
import { toolHandlers } from './handlers/tool.js';
|
|
17
17
|
import { appHandlers } from './handlers/app.js';
|
|
@@ -24,9 +24,26 @@ const handlers = {
|
|
|
24
24
|
...pageHandlers,
|
|
25
25
|
...elementHandlers,
|
|
26
26
|
};
|
|
27
|
-
|
|
27
|
+
let currentPort = null;
|
|
28
|
+
let portIpcRegistered = false;
|
|
29
|
+
export function getAutomationPort() {
|
|
30
|
+
return currentPort;
|
|
31
|
+
}
|
|
32
|
+
export async function startAutomationServer(ctx, port = 0) {
|
|
28
33
|
const wss = new WebSocketServer({ port });
|
|
29
34
|
const clients = new Set();
|
|
35
|
+
await new Promise((resolve, reject) => {
|
|
36
|
+
wss.once('listening', () => resolve());
|
|
37
|
+
wss.once('error', (err) => reject(err));
|
|
38
|
+
});
|
|
39
|
+
const addr = wss.address();
|
|
40
|
+
// ws always binds via an http.Server, so address() is AddressInfo here.
|
|
41
|
+
const resolvedPort = typeof addr === 'object' && addr ? addr.port : port;
|
|
42
|
+
currentPort = resolvedPort;
|
|
43
|
+
if (!portIpcRegistered) {
|
|
44
|
+
portIpcRegistered = true;
|
|
45
|
+
ipcMain.handle(AutomationChannel.GetPort, () => currentPort);
|
|
46
|
+
}
|
|
30
47
|
function broadcast(event) {
|
|
31
48
|
const msg = JSON.stringify(event);
|
|
32
49
|
for (const ws of clients) {
|
|
@@ -90,6 +107,13 @@ export function startAutomationServer(ctx, port) {
|
|
|
90
107
|
});
|
|
91
108
|
ws.on('close', () => clients.delete(ws));
|
|
92
109
|
});
|
|
93
|
-
return {
|
|
110
|
+
return {
|
|
111
|
+
close: () => {
|
|
112
|
+
if (currentPort === resolvedPort)
|
|
113
|
+
currentPort = null;
|
|
114
|
+
wss.close();
|
|
115
|
+
},
|
|
116
|
+
port: resolvedPort,
|
|
117
|
+
};
|
|
94
118
|
}
|
|
95
119
|
//# sourceMappingURL=index.js.map
|
|
@@ -22,6 +22,12 @@ export function listProjects() {
|
|
|
22
22
|
return load();
|
|
23
23
|
}
|
|
24
24
|
export function validateProjectDir(dirPath) {
|
|
25
|
+
if (!dirPath) {
|
|
26
|
+
return '小程序目录路径为空,请选择包含小程序源码的目录';
|
|
27
|
+
}
|
|
28
|
+
if (!fs.existsSync(dirPath)) {
|
|
29
|
+
return `小程序目录不存在:${dirPath}`;
|
|
30
|
+
}
|
|
25
31
|
if (!fs.existsSync(path.join(dirPath, 'app.json'))) {
|
|
26
32
|
const configPath = path.join(dirPath, 'project.config.json');
|
|
27
33
|
if (fs.existsSync(configPath)) {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SimulatorStorageWatcher
|
|
3
|
+
*
|
|
4
|
+
* Attaches the Chrome DevTools Protocol debugger to the simulator <webview>
|
|
5
|
+
* and forwards `DOMStorage.*` events to the renderer host. Replaces the
|
|
6
|
+
* preload-side localStorage.setItem hook that used to push storage changes
|
|
7
|
+
* via SimulatorChannel.Storage / StorageAll.
|
|
8
|
+
*
|
|
9
|
+
* Trade-offs vs the preload approach:
|
|
10
|
+
* + Uses standard browser protocol; no preload injection
|
|
11
|
+
* + Captures every change including ones bypassing wx (api-compat fallback,
|
|
12
|
+
* direct localStorage.setItem from devtools, etc.)
|
|
13
|
+
* + Decouples panel UI from dimina runtime's wx implementation
|
|
14
|
+
* - debugger.attach is mutually exclusive with Chrome DevTools (F12).
|
|
15
|
+
* If a user opens DevTools on the simulator the debugger detaches and
|
|
16
|
+
* events stop flowing until they close it.
|
|
17
|
+
*/
|
|
18
|
+
import { type WebContents } from 'electron';
|
|
19
|
+
export declare function setupSimulatorStorage(host: WebContents): void;
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SimulatorStorageWatcher
|
|
3
|
+
*
|
|
4
|
+
* Attaches the Chrome DevTools Protocol debugger to the simulator <webview>
|
|
5
|
+
* and forwards `DOMStorage.*` events to the renderer host. Replaces the
|
|
6
|
+
* preload-side localStorage.setItem hook that used to push storage changes
|
|
7
|
+
* via SimulatorChannel.Storage / StorageAll.
|
|
8
|
+
*
|
|
9
|
+
* Trade-offs vs the preload approach:
|
|
10
|
+
* + Uses standard browser protocol; no preload injection
|
|
11
|
+
* + Captures every change including ones bypassing wx (api-compat fallback,
|
|
12
|
+
* direct localStorage.setItem from devtools, etc.)
|
|
13
|
+
* + Decouples panel UI from dimina runtime's wx implementation
|
|
14
|
+
* - debugger.attach is mutually exclusive with Chrome DevTools (F12).
|
|
15
|
+
* If a user opens DevTools on the simulator the debugger detaches and
|
|
16
|
+
* events stop flowing until they close it.
|
|
17
|
+
*/
|
|
18
|
+
import { app, ipcMain, webContents as wcStatic } from 'electron';
|
|
19
|
+
import { SimulatorStorageChannel, } from '../../../shared/ipc-channels.js';
|
|
20
|
+
let attachedWc = null;
|
|
21
|
+
let hostWc = null;
|
|
22
|
+
function isSimulatorWebview(wc) {
|
|
23
|
+
if (wc.isDestroyed())
|
|
24
|
+
return false;
|
|
25
|
+
if (wc.getType() !== 'webview')
|
|
26
|
+
return false;
|
|
27
|
+
return wc.getURL().includes('simulator.html');
|
|
28
|
+
}
|
|
29
|
+
function detach() {
|
|
30
|
+
if (!attachedWc)
|
|
31
|
+
return;
|
|
32
|
+
const wc = attachedWc;
|
|
33
|
+
attachedWc = null;
|
|
34
|
+
try {
|
|
35
|
+
if (!wc.isDestroyed() && wc.debugger.isAttached()) {
|
|
36
|
+
wc.debugger.detach();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// best-effort
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async function attachToSim(wc) {
|
|
44
|
+
if (attachedWc === wc)
|
|
45
|
+
return;
|
|
46
|
+
if (wc.isDestroyed())
|
|
47
|
+
return;
|
|
48
|
+
detach();
|
|
49
|
+
try {
|
|
50
|
+
if (!wc.debugger.isAttached()) {
|
|
51
|
+
wc.debugger.attach('1.3');
|
|
52
|
+
}
|
|
53
|
+
await wc.debugger.sendCommand('DOMStorage.enable');
|
|
54
|
+
wc.debugger.on('message', onCdpMessage);
|
|
55
|
+
wc.debugger.on('detach', () => {
|
|
56
|
+
if (attachedWc === wc)
|
|
57
|
+
attachedWc = null;
|
|
58
|
+
});
|
|
59
|
+
wc.once('destroyed', () => {
|
|
60
|
+
if (attachedWc === wc)
|
|
61
|
+
attachedWc = null;
|
|
62
|
+
});
|
|
63
|
+
attachedWc = wc;
|
|
64
|
+
}
|
|
65
|
+
catch (e) {
|
|
66
|
+
console.warn('[storage-watcher] attach failed:', e.message);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function onCdpMessage(_event, method, params) {
|
|
70
|
+
if (!hostWc || hostWc.isDestroyed())
|
|
71
|
+
return;
|
|
72
|
+
const p = params;
|
|
73
|
+
let evt;
|
|
74
|
+
switch (method) {
|
|
75
|
+
case 'DOMStorage.domStorageItemAdded':
|
|
76
|
+
evt = { type: 'added', key: String(p.key), newValue: String(p.newValue ?? '') };
|
|
77
|
+
break;
|
|
78
|
+
case 'DOMStorage.domStorageItemUpdated':
|
|
79
|
+
evt = {
|
|
80
|
+
type: 'updated',
|
|
81
|
+
key: String(p.key),
|
|
82
|
+
oldValue: String(p.oldValue ?? ''),
|
|
83
|
+
newValue: String(p.newValue ?? ''),
|
|
84
|
+
};
|
|
85
|
+
break;
|
|
86
|
+
case 'DOMStorage.domStorageItemRemoved':
|
|
87
|
+
evt = { type: 'removed', key: String(p.key) };
|
|
88
|
+
break;
|
|
89
|
+
case 'DOMStorage.domStorageItemsCleared':
|
|
90
|
+
evt = { type: 'cleared' };
|
|
91
|
+
break;
|
|
92
|
+
default:
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
hostWc.send(SimulatorStorageChannel.Event, evt);
|
|
96
|
+
}
|
|
97
|
+
async function getSnapshot() {
|
|
98
|
+
if (!attachedWc || attachedWc.isDestroyed())
|
|
99
|
+
return [];
|
|
100
|
+
try {
|
|
101
|
+
const origin = await attachedWc.executeJavaScript('location.origin');
|
|
102
|
+
const result = (await attachedWc.debugger.sendCommand('DOMStorage.getDOMStorageItems', {
|
|
103
|
+
storageId: { securityOrigin: origin, isLocalStorage: true },
|
|
104
|
+
}));
|
|
105
|
+
return result.entries.map(([key, value]) => ({ key, value }));
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export function setupSimulatorStorage(host) {
|
|
112
|
+
hostWc = host;
|
|
113
|
+
// Attach to any simulator webview that already exists (project may have
|
|
114
|
+
// been opened before this function runs).
|
|
115
|
+
for (const wc of wcStatic.getAllWebContents()) {
|
|
116
|
+
if (isSimulatorWebview(wc)) {
|
|
117
|
+
void attachToSim(wc);
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Catch new simulator webviews on creation. did-finish-load is the right
|
|
122
|
+
// moment because getURL() may still be 'about:blank' at creation.
|
|
123
|
+
app.on('web-contents-created', (_event, wc) => {
|
|
124
|
+
wc.on('did-finish-load', () => {
|
|
125
|
+
if (isSimulatorWebview(wc)) {
|
|
126
|
+
void attachToSim(wc);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
wc.on('did-navigate-in-page', () => {
|
|
130
|
+
// Project switched but same webview — attach already correct, debugger
|
|
131
|
+
// session survives in-page navigations. No-op.
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
ipcMain.handle(SimulatorStorageChannel.GetSnapshot, getSnapshot);
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { UpdateChecker } from '../../../shared/types.js';
|
|
2
|
+
interface GitHubReleaseAsset {
|
|
3
|
+
name: string;
|
|
4
|
+
browser_download_url: string;
|
|
5
|
+
size: number;
|
|
6
|
+
}
|
|
7
|
+
interface GitHubRelease {
|
|
8
|
+
tag_name: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
body?: string;
|
|
11
|
+
prerelease: boolean;
|
|
12
|
+
draft: boolean;
|
|
13
|
+
assets: GitHubReleaseAsset[];
|
|
14
|
+
}
|
|
15
|
+
export type VersionScheme = 'semver' | 'trailing-number';
|
|
16
|
+
export interface GitHubReleaseCheckerOptions {
|
|
17
|
+
owner: string;
|
|
18
|
+
repo: string;
|
|
19
|
+
/** Optional GitHub token (required for private repos; recommended to avoid rate limits). */
|
|
20
|
+
token?: string;
|
|
21
|
+
/** Include prereleases when resolving the latest version. Default: false. */
|
|
22
|
+
includePrereleases?: boolean;
|
|
23
|
+
/** Mark every delivered update as mandatory. Default: false. */
|
|
24
|
+
mandatory?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Built-in version scheme. Ignored when `parseVersion` is supplied.
|
|
27
|
+
* - `'semver'` (default): extract `x.y.z` from `tag_name` → release name → first asset name.
|
|
28
|
+
* - `'trailing-number'`: treat the trailing `-<N>` in `tag_name` as the version
|
|
29
|
+
* (e.g. `release-20260422-1` → `'1'`). Compared as an integer.
|
|
30
|
+
*/
|
|
31
|
+
versionScheme?: VersionScheme;
|
|
32
|
+
/**
|
|
33
|
+
* Custom asset picker. Receives the release assets plus the current
|
|
34
|
+
* process platform/arch. If omitted, a built-in picker is used that
|
|
35
|
+
* matches by file extension and arch suffix.
|
|
36
|
+
*/
|
|
37
|
+
pickAsset?: (assets: GitHubReleaseAsset[], ctx: PickAssetContext) => GitHubReleaseAsset | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Extract the version string from a release. Overrides `versionScheme`.
|
|
40
|
+
*/
|
|
41
|
+
parseVersion?: (release: GitHubRelease) => string | null;
|
|
42
|
+
}
|
|
43
|
+
export interface PickAssetContext {
|
|
44
|
+
platform: NodeJS.Platform;
|
|
45
|
+
arch: string;
|
|
46
|
+
}
|
|
47
|
+
export declare function createGitHubReleaseChecker(opts: GitHubReleaseCheckerOptions): UpdateChecker;
|
|
48
|
+
export {};
|
|
49
|
+
//# sourceMappingURL=github-release-checker.d.ts.map
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import https from 'https';
|
|
4
|
+
import { app } from 'electron';
|
|
5
|
+
export function createGitHubReleaseChecker(opts) {
|
|
6
|
+
const releaseUrl = opts.includePrereleases
|
|
7
|
+
? `https://api.github.com/repos/${opts.owner}/${opts.repo}/releases`
|
|
8
|
+
: `https://api.github.com/repos/${opts.owner}/${opts.repo}/releases/latest`;
|
|
9
|
+
const parseVersion = opts.parseVersion ?? schemeParser(opts.versionScheme ?? 'semver');
|
|
10
|
+
return {
|
|
11
|
+
async checkForUpdates(currentVersion) {
|
|
12
|
+
const release = await fetchRelease(releaseUrl, opts);
|
|
13
|
+
if (!release)
|
|
14
|
+
return null;
|
|
15
|
+
const latestVersion = parseVersion(release);
|
|
16
|
+
if (!latestVersion)
|
|
17
|
+
return null;
|
|
18
|
+
if (compareSemver(latestVersion, stripV(currentVersion)) <= 0)
|
|
19
|
+
return null;
|
|
20
|
+
const asset = (opts.pickAsset ?? defaultPickAsset)(release.assets, {
|
|
21
|
+
platform: process.platform,
|
|
22
|
+
arch: process.arch,
|
|
23
|
+
});
|
|
24
|
+
if (!asset)
|
|
25
|
+
return null;
|
|
26
|
+
return {
|
|
27
|
+
version: latestVersion,
|
|
28
|
+
downloadUrl: asset.browser_download_url,
|
|
29
|
+
releaseNotes: release.body,
|
|
30
|
+
mandatory: opts.mandatory,
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
async downloadUpdate(info, onProgress) {
|
|
34
|
+
const tmpDir = path.join(app.getPath('temp'), `${opts.repo}-update`);
|
|
35
|
+
if (!fs.existsSync(tmpDir))
|
|
36
|
+
fs.mkdirSync(tmpDir, { recursive: true });
|
|
37
|
+
const fileName = path.basename(new URL(info.downloadUrl).pathname);
|
|
38
|
+
const filePath = path.join(tmpDir, fileName);
|
|
39
|
+
await downloadFile(info.downloadUrl, filePath, opts.token, onProgress);
|
|
40
|
+
return filePath;
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// ── Default pickers ───────────────────────────────────────────────────────
|
|
45
|
+
function defaultPickAsset(assets, ctx) {
|
|
46
|
+
const candidates = platformMatchers(ctx.platform, ctx.arch);
|
|
47
|
+
for (const match of candidates) {
|
|
48
|
+
const hit = assets.find((a) => match(a.name));
|
|
49
|
+
if (hit)
|
|
50
|
+
return hit;
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
function platformMatchers(platform, arch) {
|
|
55
|
+
const lc = (s) => s.toLowerCase();
|
|
56
|
+
const archTags = archAliases(arch);
|
|
57
|
+
const hasArch = (name) => archTags.some((tag) => lc(name).includes(tag));
|
|
58
|
+
const endsWith = (name, ext) => lc(name).endsWith(ext);
|
|
59
|
+
switch (platform) {
|
|
60
|
+
case 'darwin':
|
|
61
|
+
return [
|
|
62
|
+
(n) => endsWith(n, '.dmg') && hasArch(n),
|
|
63
|
+
(n) => endsWith(n, '.dmg'), // mac builds are often universal / unarch-tagged
|
|
64
|
+
(n) => endsWith(n, '.zip') && (lc(n).includes('mac') || lc(n).includes('darwin')),
|
|
65
|
+
];
|
|
66
|
+
case 'win32':
|
|
67
|
+
return [
|
|
68
|
+
(n) => endsWith(n, '.exe') && hasArch(n),
|
|
69
|
+
(n) => endsWith(n, '.zip') && (lc(n).includes('win') || lc(n).includes('windows')) && hasArch(n),
|
|
70
|
+
(n) => endsWith(n, '.exe'),
|
|
71
|
+
(n) => endsWith(n, '.zip') && (lc(n).includes('win') || lc(n).includes('windows')),
|
|
72
|
+
];
|
|
73
|
+
case 'linux':
|
|
74
|
+
return [
|
|
75
|
+
(n) => endsWith(n, '.appimage') && hasArch(n),
|
|
76
|
+
(n) => endsWith(n, '.tar.gz') && lc(n).includes('linux') && hasArch(n),
|
|
77
|
+
(n) => endsWith(n, '.appimage'),
|
|
78
|
+
(n) => endsWith(n, '.tar.gz') && lc(n).includes('linux'),
|
|
79
|
+
(n) => endsWith(n, '.deb') && hasArch(n),
|
|
80
|
+
];
|
|
81
|
+
default:
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function archAliases(arch) {
|
|
86
|
+
switch (arch) {
|
|
87
|
+
case 'x64':
|
|
88
|
+
return ['x64', 'x86_64', 'amd64'];
|
|
89
|
+
case 'arm64':
|
|
90
|
+
return ['arm64', 'aarch64'];
|
|
91
|
+
case 'ia32':
|
|
92
|
+
return ['ia32', 'x86', 'i386'];
|
|
93
|
+
default:
|
|
94
|
+
return [arch];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// ── Version parsing & comparison ──────────────────────────────────────────
|
|
98
|
+
const SEMVER_RE = /(\d+)\.(\d+)\.(\d+)(?:[-+]([0-9A-Za-z.-]+))?/;
|
|
99
|
+
const TRAILING_NUMBER_RE = /-(\d+)$/;
|
|
100
|
+
function schemeParser(scheme) {
|
|
101
|
+
if (scheme === 'trailing-number') {
|
|
102
|
+
return (release) => {
|
|
103
|
+
const m = release.tag_name.match(TRAILING_NUMBER_RE);
|
|
104
|
+
return m ? m[1] : null;
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return defaultParseVersion;
|
|
108
|
+
}
|
|
109
|
+
function defaultParseVersion(release) {
|
|
110
|
+
const fromTag = extractSemver(release.tag_name);
|
|
111
|
+
if (fromTag)
|
|
112
|
+
return fromTag;
|
|
113
|
+
if (release.name) {
|
|
114
|
+
const fromName = extractSemver(release.name);
|
|
115
|
+
if (fromName)
|
|
116
|
+
return fromName;
|
|
117
|
+
}
|
|
118
|
+
for (const asset of release.assets) {
|
|
119
|
+
const hit = extractSemver(asset.name);
|
|
120
|
+
if (hit)
|
|
121
|
+
return hit;
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
function extractSemver(input) {
|
|
126
|
+
const m = input.match(SEMVER_RE);
|
|
127
|
+
if (!m)
|
|
128
|
+
return null;
|
|
129
|
+
const [, major, minor, patch, pre] = m;
|
|
130
|
+
return pre ? `${major}.${minor}.${patch}-${pre}` : `${major}.${minor}.${patch}`;
|
|
131
|
+
}
|
|
132
|
+
function stripV(version) {
|
|
133
|
+
return version.replace(/^v/i, '');
|
|
134
|
+
}
|
|
135
|
+
function compareSemver(a, b) {
|
|
136
|
+
const [aCore, aPre] = splitPre(a);
|
|
137
|
+
const [bCore, bPre] = splitPre(b);
|
|
138
|
+
const [a1, a2, a3] = parseCore(aCore);
|
|
139
|
+
const [b1, b2, b3] = parseCore(bCore);
|
|
140
|
+
if (a1 !== b1)
|
|
141
|
+
return a1 - b1;
|
|
142
|
+
if (a2 !== b2)
|
|
143
|
+
return a2 - b2;
|
|
144
|
+
if (a3 !== b3)
|
|
145
|
+
return a3 - b3;
|
|
146
|
+
// Release > prerelease of same core.
|
|
147
|
+
if (!aPre && bPre)
|
|
148
|
+
return 1;
|
|
149
|
+
if (aPre && !bPre)
|
|
150
|
+
return -1;
|
|
151
|
+
if (!aPre && !bPre)
|
|
152
|
+
return 0;
|
|
153
|
+
return aPre.localeCompare(bPre);
|
|
154
|
+
}
|
|
155
|
+
function splitPre(v) {
|
|
156
|
+
const i = v.indexOf('-');
|
|
157
|
+
return i < 0 ? [v, null] : [v.slice(0, i), v.slice(i + 1)];
|
|
158
|
+
}
|
|
159
|
+
function parseCore(core) {
|
|
160
|
+
const parts = core.split('.').map((s) => parseInt(s, 10) || 0);
|
|
161
|
+
return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
|
|
162
|
+
}
|
|
163
|
+
// ── HTTP helpers ──────────────────────────────────────────────────────────
|
|
164
|
+
function ghHeaders(token) {
|
|
165
|
+
const headers = {
|
|
166
|
+
'User-Agent': 'dimina-kit-updater',
|
|
167
|
+
'Accept': 'application/vnd.github+json',
|
|
168
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
169
|
+
};
|
|
170
|
+
if (token)
|
|
171
|
+
headers.Authorization = `Bearer ${token}`;
|
|
172
|
+
return headers;
|
|
173
|
+
}
|
|
174
|
+
async function fetchRelease(url, opts) {
|
|
175
|
+
const body = await httpGetText(url, { headers: ghHeaders(opts.token) });
|
|
176
|
+
if (!body)
|
|
177
|
+
return null;
|
|
178
|
+
if (opts.includePrereleases) {
|
|
179
|
+
const list = JSON.parse(body);
|
|
180
|
+
const first = list.find((r) => !r.draft);
|
|
181
|
+
return first ?? null;
|
|
182
|
+
}
|
|
183
|
+
const release = JSON.parse(body);
|
|
184
|
+
return release.draft ? null : release;
|
|
185
|
+
}
|
|
186
|
+
function httpGetText(url, init) {
|
|
187
|
+
return new Promise((resolve, reject) => {
|
|
188
|
+
const req = https.get(url, { headers: init.headers }, (res) => {
|
|
189
|
+
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
190
|
+
res.resume();
|
|
191
|
+
resolve(httpGetText(res.headers.location, init));
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (res.statusCode !== 200) {
|
|
195
|
+
res.resume();
|
|
196
|
+
resolve(null);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
let body = '';
|
|
200
|
+
res.setEncoding('utf8');
|
|
201
|
+
res.on('data', (chunk) => { body += chunk; });
|
|
202
|
+
res.on('end', () => resolve(body));
|
|
203
|
+
});
|
|
204
|
+
req.on('error', reject);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
function downloadFile(url, dest, token, onProgress) {
|
|
208
|
+
return new Promise((resolve, reject) => {
|
|
209
|
+
const headers = ghHeaders(token);
|
|
210
|
+
// GitHub asset downloads redirect to signed S3 URLs; keep following them.
|
|
211
|
+
const attempt = (target, redirectsLeft) => {
|
|
212
|
+
const req = https.get(target, { headers }, (res) => {
|
|
213
|
+
if (res.statusCode &&
|
|
214
|
+
res.statusCode >= 300 &&
|
|
215
|
+
res.statusCode < 400 &&
|
|
216
|
+
res.headers.location) {
|
|
217
|
+
res.resume();
|
|
218
|
+
if (redirectsLeft <= 0) {
|
|
219
|
+
reject(new Error('Too many redirects'));
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
attempt(res.headers.location, redirectsLeft - 1);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (res.statusCode !== 200) {
|
|
226
|
+
res.resume();
|
|
227
|
+
reject(new Error(`HTTP ${res.statusCode} while downloading update`));
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const total = parseInt(res.headers['content-length'] || '0', 10);
|
|
231
|
+
let received = 0;
|
|
232
|
+
const out = fs.createWriteStream(dest);
|
|
233
|
+
res.on('data', (chunk) => {
|
|
234
|
+
received += chunk.length;
|
|
235
|
+
if (total > 0 && onProgress) {
|
|
236
|
+
onProgress((received / total) * 100);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
res.pipe(out);
|
|
240
|
+
out.on('finish', () => { out.close(); resolve(); });
|
|
241
|
+
out.on('error', (err) => { fs.unlink(dest, () => { }); reject(err); });
|
|
242
|
+
});
|
|
243
|
+
req.on('error', (err) => { fs.unlink(dest, () => { }); reject(err); });
|
|
244
|
+
};
|
|
245
|
+
attempt(url, 5);
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=github-release-checker.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { UpdateManager } from './update-manager.js';
|
|
2
|
+
export type { UpdateManagerOptions } from './update-manager.js';
|
|
3
|
+
export { createGitHubReleaseChecker } from './github-release-checker.js';
|
|
4
|
+
export type { GitHubReleaseCheckerOptions, PickAssetContext, VersionScheme, } from './github-release-checker.js';
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BrowserWindow } from 'electron';
|
|
2
|
+
import type { UpdateChecker, UpdateInfo } from '../../../shared/types.js';
|
|
3
|
+
export interface UpdateManagerOptions {
|
|
4
|
+
checker: UpdateChecker;
|
|
5
|
+
mainWindow: BrowserWindow;
|
|
6
|
+
/** Check interval in milliseconds. Default: 1 hour */
|
|
7
|
+
checkInterval?: number;
|
|
8
|
+
/** Delay before the first check after startup in ms. Default: 5000 */
|
|
9
|
+
initialDelay?: number;
|
|
10
|
+
/** Override the version string passed to the checker. Default: app.getVersion() */
|
|
11
|
+
getCurrentVersion?: () => string;
|
|
12
|
+
}
|
|
13
|
+
export declare class UpdateManager {
|
|
14
|
+
private checker;
|
|
15
|
+
private mainWindow;
|
|
16
|
+
private getCurrentVersion;
|
|
17
|
+
private latestUpdate;
|
|
18
|
+
private downloadedPath;
|
|
19
|
+
private timer;
|
|
20
|
+
private initialTimer;
|
|
21
|
+
constructor(opts: UpdateManagerOptions);
|
|
22
|
+
private registerIpc;
|
|
23
|
+
check(): Promise<{
|
|
24
|
+
hasUpdate: boolean;
|
|
25
|
+
info?: UpdateInfo;
|
|
26
|
+
}>;
|
|
27
|
+
download(): Promise<{
|
|
28
|
+
success: boolean;
|
|
29
|
+
filePath?: string;
|
|
30
|
+
error?: string;
|
|
31
|
+
}>;
|
|
32
|
+
install(): void;
|
|
33
|
+
dispose(): void;
|
|
34
|
+
private startPeriodicCheck;
|
|
35
|
+
private checkAndNotify;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=update-manager.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { app, ipcMain, shell } from 'electron';
|
|
2
|
+
export class UpdateManager {
|
|
3
|
+
checker;
|
|
4
|
+
mainWindow;
|
|
5
|
+
getCurrentVersion;
|
|
6
|
+
latestUpdate = null;
|
|
7
|
+
downloadedPath = null;
|
|
8
|
+
timer = null;
|
|
9
|
+
initialTimer = null;
|
|
10
|
+
constructor(opts) {
|
|
11
|
+
this.checker = opts.checker;
|
|
12
|
+
this.mainWindow = opts.mainWindow;
|
|
13
|
+
this.getCurrentVersion = opts.getCurrentVersion ?? (() => app.getVersion());
|
|
14
|
+
this.registerIpc();
|
|
15
|
+
this.startPeriodicCheck(opts.checkInterval ?? 60 * 60 * 1000, opts.initialDelay ?? 5000);
|
|
16
|
+
}
|
|
17
|
+
registerIpc() {
|
|
18
|
+
ipcMain.handle('updates:check', async () => {
|
|
19
|
+
return this.check();
|
|
20
|
+
});
|
|
21
|
+
ipcMain.handle('updates:download', async () => {
|
|
22
|
+
return this.download();
|
|
23
|
+
});
|
|
24
|
+
ipcMain.handle('updates:install', async () => {
|
|
25
|
+
this.install();
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async check() {
|
|
29
|
+
try {
|
|
30
|
+
const currentVersion = this.getCurrentVersion();
|
|
31
|
+
const info = await this.checker.checkForUpdates(currentVersion);
|
|
32
|
+
if (info) {
|
|
33
|
+
this.latestUpdate = info;
|
|
34
|
+
this.downloadedPath = null;
|
|
35
|
+
return { hasUpdate: true, info };
|
|
36
|
+
}
|
|
37
|
+
return { hasUpdate: false };
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
console.warn('[UpdateManager] check failed:', err);
|
|
41
|
+
return { hasUpdate: false };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async download() {
|
|
45
|
+
if (!this.latestUpdate) {
|
|
46
|
+
return { success: false, error: 'No update available' };
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const filePath = await this.checker.downloadUpdate(this.latestUpdate, (percent) => {
|
|
50
|
+
this.mainWindow.webContents.send('updates:downloadProgress', { percent });
|
|
51
|
+
});
|
|
52
|
+
this.downloadedPath = filePath;
|
|
53
|
+
return { success: true, filePath };
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
console.warn('[UpdateManager] download failed:', err);
|
|
57
|
+
return { success: false, error: String(err) };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
install() {
|
|
61
|
+
if (this.downloadedPath) {
|
|
62
|
+
shell.openPath(this.downloadedPath);
|
|
63
|
+
app.quit();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
dispose() {
|
|
67
|
+
if (this.timer) {
|
|
68
|
+
clearInterval(this.timer);
|
|
69
|
+
this.timer = null;
|
|
70
|
+
}
|
|
71
|
+
if (this.initialTimer) {
|
|
72
|
+
clearTimeout(this.initialTimer);
|
|
73
|
+
this.initialTimer = null;
|
|
74
|
+
}
|
|
75
|
+
ipcMain.removeHandler('updates:check');
|
|
76
|
+
ipcMain.removeHandler('updates:download');
|
|
77
|
+
ipcMain.removeHandler('updates:install');
|
|
78
|
+
}
|
|
79
|
+
startPeriodicCheck(interval, initialDelay) {
|
|
80
|
+
this.initialTimer = setTimeout(() => void this.checkAndNotify(), initialDelay);
|
|
81
|
+
this.timer = setInterval(() => void this.checkAndNotify(), interval);
|
|
82
|
+
}
|
|
83
|
+
async checkAndNotify() {
|
|
84
|
+
const result = await this.check();
|
|
85
|
+
if (result.hasUpdate && result.info) {
|
|
86
|
+
this.mainWindow.webContents.send('updates:available', result.info);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=update-manager.js.map
|