@mindexec/cli 0.2.478 → 0.2.479
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/README.md +323 -323
- package/codex-model-catalog.js +202 -202
- package/codex-runtime.js +1608 -1608
- package/desktop-workspace-state.cjs +120 -120
- package/electron/main.cjs +517 -517
- package/electron/preload.cjs +17 -17
- package/electron/recurring-update-owner-smoke.mjs +55 -55
- package/electron/recurring-update-owner.cjs +97 -97
- package/electron/source-smoke.mjs +108 -108
- package/electron/update-feed-resolver.cjs +79 -79
- package/electron/update-feed.json +10 -10
- package/electron/update-manager-smoke.mjs +146 -146
- package/electron/update-manager.cjs +297 -297
- package/electron/windows-package-smoke.mjs +156 -156
- package/launch-bridge.cjs +236 -236
- package/lzo1x.js +110 -110
- package/mode4-atlas-worker.js +440 -440
- package/mode4-atlas.js +130 -130
- package/package.json +1 -1
- package/port-guard.cjs +285 -285
- package/remote-fast/osx-arm64/MacScreenCaptureKitH264.swift +339 -339
- package/remote-fast/osx-arm64/MacSystemAudioCapture.swift +214 -214
- package/remote-fast/osx-arm64/UnixRawCaptureHelper.mjs +80 -80
- package/remote-fast/osx-arm64/livedesk-raw-capture-resampler.mjs +73 -73
- package/remote-fast/osx-arm64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/osx-x64/MacScreenCaptureKitH264.swift +339 -339
- package/remote-fast/osx-x64/MacSystemAudioCapture.swift +214 -214
- package/remote-fast/osx-x64/UnixRawCaptureHelper.mjs +80 -80
- package/remote-fast/osx-x64/livedesk-raw-capture-resampler.mjs +73 -73
- package/remote-fast/osx-x64/mindexec-remote-fast.dll +0 -0
- package/remote-fast/win-x64/mindexec-remote-fast.dll +0 -0
- package/remote-hub.js +3698 -3698
- package/scripts/auth-session-smoke.mjs +262 -262
- package/scripts/board-render-ownership-smoke.mjs +85 -85
- package/scripts/codex-model-catalog-smoke.mjs +150 -150
- package/scripts/codex-runtime-home-smoke.mjs +58 -58
- package/scripts/codex-sdk-image-live-smoke.mjs +43 -43
- package/scripts/codex-sdk-image-runtime-smoke.mjs +122 -122
- package/scripts/codex-sdk-runtime-smoke.mjs +89 -89
- package/scripts/desktop-update-publisher-smoke.mjs +89 -89
- package/scripts/desktop-update-worker-smoke.mjs +72 -72
- package/scripts/desktop-workspace-state-smoke.mjs +81 -81
- package/scripts/drive-installed-update-smoke.mjs +67 -67
- package/scripts/npm-fresh-install-smoke.mjs +216 -216
- package/scripts/publish-mindexec-desktop-updates.mjs +224 -224
- package/scripts/remote-agent-managed-smoke.mjs +318 -318
- package/scripts/remote-agent-package-smoke.mjs +64 -64
- package/scripts/remote-agent-ws-smoke.mjs +269 -269
- package/scripts/remote-fast-live-rate-smoke.mjs +343 -343
- package/scripts/remote-fast-mdm-browser-smoke.mjs +453 -453
- package/scripts/remote-fleet-render-smoke.mjs +1350 -1350
- package/scripts/remote-frame-ws-smoke.mjs +234 -234
- package/scripts/remote-http-smoke.mjs +592 -592
- package/scripts/remote-hub-identity-smoke.mjs +146 -146
- package/scripts/remote-hub-scale-smoke.mjs +124 -124
- package/scripts/remote-hub-smoke.mjs +699 -699
- package/scripts/remote-input-ws-smoke.mjs +263 -263
- package/scripts/remote-registry-follower-smoke.mjs +815 -815
- package/scripts/setup-tree-sitter-grammars.mjs +59 -59
- package/server.js +7510 -7510
- package/start-bridge.bat +32 -32
- package/start-bridge.sh +81 -81
- package/tree-sitter-grammars/README.md +18 -0
- package/tree-sitter-grammars/tree-sitter-c_sharp.wasm +0 -0
- package/tree-sitter-grammars/tree-sitter-go.wasm +0 -0
- package/tree-sitter-grammars/tree-sitter-java.wasm +0 -0
- package/tree-sitter-grammars/tree-sitter-javascript.wasm +0 -0
- package/tree-sitter-grammars/tree-sitter-python.wasm +0 -0
- package/tree-sitter-grammars/tree-sitter-rust.wasm +0 -0
- package/tree-sitter-grammars/tree-sitter-tsx.wasm +0 -0
- package/tree-sitter-grammars/tree-sitter-typescript.wasm +0 -0
- package/wwwroot/_content/MindExecution.Plugins.Admin/css/admin-dashboard.css +546 -546
- package/wwwroot/_content/MindExecution.Plugins.Directory/background.png +0 -0
- package/wwwroot/_content/MindExecution.Plugins.YouTube/css/youtube-search.css +251 -251
- package/wwwroot/_content/MindExecution.Shared/css/mind-map-overrides.css +3789 -3789
- package/wwwroot/_content/MindExecution.Shared/fonts/NotoSansKR-Bold.ttf +0 -0
- package/wwwroot/_content/MindExecution.Shared/fonts/NotoSansKR-Regular.ttf +0 -0
- package/wwwroot/_content/MindExecution.Shared/js/agent-visualization.js +27 -27
- package/wwwroot/_content/MindExecution.Shared/js/background-themes.js +1449 -1449
- package/wwwroot/_content/MindExecution.Shared/js/code-master.js +8316 -8316
- package/wwwroot/_content/MindExecution.Shared/js/file-system-helper.js +338 -338
- package/wwwroot/_content/MindExecution.Shared/js/marked.min.js +69 -69
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-animated-image-preview.js +270 -270
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-automation-edge-motion.js +170 -170
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-board-render-ownership.js +81 -81
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +10506 -10506
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js.backup +1059 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-hotpath.js +902 -902
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +24637 -24637
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-dev-guards.js +325 -325
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-dnd.js +1491 -1491
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-dnd.js.bak +434 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-glow-shader.js +70 -70
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-image-policy.js +218 -218
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-interactions.js +7078 -7078
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-plan-worker.js +160 -160
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-renderer.js +9958 -9958
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-lod-video-placeholder.js +107 -107
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-logic-workers.js +1004 -1004
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-menu-manager.js +1351 -1351
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-multi-select.js +865 -865
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-node-search-worker.js +554 -554
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-nodes.js +4744 -4744
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-normal-boundary-optimizer.js +624 -624
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-object-manager.js +241 -241
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-object-manager.js.backup +372 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-pipeline.js +2290 -2290
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-remote-codecs.js +202 -202
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-render-plan.js +1971 -1971
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-text-lod-system.js +93 -93
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-texture-factory.js +2391 -2391
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-texture-factory.js.backup +1258 -0
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-video-playback-controls.js +95 -95
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-visibility-worker.js +895 -895
- package/wwwroot/_content/MindExecution.Shared/js/mindmap-toolbar.js +636 -636
- package/wwwroot/_content/MindExecution.Shared/js/native-drop-handler.js +45 -45
- package/wwwroot/_content/MindExecution.Shared/js/plan-master.js +117 -117
- package/wwwroot/_content/MindExecution.Shared/js/renderers/CSS3DRenderer.js +114 -114
- package/wwwroot/_content/MindExecution.Shared/js/texture-worker-manager.js +10 -10
- package/wwwroot/_content/MindExecution.Shared/js/three.min.js +6 -6
- package/wwwroot/_content/MindExecution.Shared/js/token-manager.js +7 -7
- package/wwwroot/_content/MindExecution.Shared/js/troika-bundle.js +6 -6
- package/wwwroot/_content/MindExecution.Shared/js/troika-bundle.js.map +2 -2
- package/wwwroot/_content/MindExecution.Shared/lib/font-awesome/css/all.min.css +8 -8
- package/wwwroot/_content/MindExecution.Shared/models/vocab.txt +30522 -30522
- package/wwwroot/_framework/{Google.Protobuf.33g2gb5is0.dll → Google.Protobuf.9h59ukbel7.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Core.z100xo4mg0.dll → MindExecution.Core.xxsj2s456b.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Kernel.i9cldrx8yc.dll → MindExecution.Kernel.5jofnc0wrd.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Admin.48lzqddb0a.dll → MindExecution.Plugins.Admin.t7m4jnqjg3.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Business.7m8u1q142p.dll → MindExecution.Plugins.Business.6yjlhhavap.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Concept.cl5wmr53od.dll → MindExecution.Plugins.Concept.iikqq5zxu0.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.Directory.slipi39041.dll → MindExecution.Plugins.Directory.c5ribyne4m.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.PlanMaster.qfge05l671.dll → MindExecution.Plugins.PlanMaster.365bbuifr9.dll} +0 -0
- package/wwwroot/_framework/{MindExecution.Plugins.YouTube.tn7v29ut77.dll → MindExecution.Plugins.YouTube.ax415cilpk.dll} +0 -0
- package/wwwroot/_framework/MindExecution.Shared.21e2nvf86u.dll +0 -0
- package/wwwroot/_framework/{MindExecution.Web.rwawrxxk38.dll → MindExecution.Web.ppgm8rey59.dll} +0 -0
- package/wwwroot/_framework/{System.Collections.23yxgetbju.dll → System.Collections.zyvbaq6mpd.dll} +0 -0
- package/wwwroot/_framework/blazor.boot.json +25 -25
- package/wwwroot/_headers +40 -40
- package/wwwroot/_redirects +1 -1
- package/wwwroot/index.html +772 -772
- package/wwwroot/js/marketing-tool.js +180 -180
- package/wwwroot/manifest.webmanifest +23 -23
- package/wwwroot/service-worker-assets.js +109 -81
- package/wwwroot/service-worker.js +33 -33
- package/wwwroot/_framework/MindExecution.Shared.rjqlf0umjn.dll +0 -0
|
@@ -1,297 +1,297 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { resolveDesktopUpdateFeed } = require('./update-feed-resolver.cjs');
|
|
6
|
-
|
|
7
|
-
function createProductUpdateManager({
|
|
8
|
-
app,
|
|
9
|
-
onStatus = () => undefined,
|
|
10
|
-
beforeInstall = async () => undefined,
|
|
11
|
-
onInstallError = async () => undefined,
|
|
12
|
-
updater = null,
|
|
13
|
-
platform = process.platform,
|
|
14
|
-
arch = process.arch,
|
|
15
|
-
installKind = 'installed',
|
|
16
|
-
startupCheckTimeoutMs = 2_500,
|
|
17
|
-
updateFeedConfig = null,
|
|
18
|
-
updateChannel = '',
|
|
19
|
-
overrideUrl = process.env.MINDEXEC_UPDATE_URL || ''
|
|
20
|
-
} = {}) {
|
|
21
|
-
if (!app) throw new TypeError('desktop-update-app-required');
|
|
22
|
-
if (!updater) updater = require('electron-updater').autoUpdater;
|
|
23
|
-
|
|
24
|
-
let feedConfig = updateFeedConfig;
|
|
25
|
-
let packageMetadata = {};
|
|
26
|
-
try {
|
|
27
|
-
packageMetadata = JSON.parse(fs.readFileSync(path.join(app.getAppPath(), 'package.json'), 'utf8'));
|
|
28
|
-
} catch {
|
|
29
|
-
packageMetadata = {};
|
|
30
|
-
}
|
|
31
|
-
if (!feedConfig) {
|
|
32
|
-
try {
|
|
33
|
-
feedConfig = JSON.parse(fs.readFileSync(path.join(app.getAppPath(), 'electron', 'update-feed.json'), 'utf8'));
|
|
34
|
-
} catch {
|
|
35
|
-
feedConfig = {};
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const packagedChannel = String(updateChannel || packageMetadata?.desktopUpdateChannel || '')
|
|
40
|
-
.trim()
|
|
41
|
-
.toLowerCase();
|
|
42
|
-
if (packagedChannel) feedConfig = { ...feedConfig, channel: packagedChannel };
|
|
43
|
-
const feed = resolveDesktopUpdateFeed({ config: feedConfig, overrideUrl, platform, arch });
|
|
44
|
-
const updateSupported = Boolean(app.isPackaged && installKind === 'installed' && platform === 'win32');
|
|
45
|
-
|
|
46
|
-
let status = {
|
|
47
|
-
state: 'idle',
|
|
48
|
-
currentVersion: app.getVersion(),
|
|
49
|
-
availableVersion: '',
|
|
50
|
-
downloaded: false,
|
|
51
|
-
progress: 0,
|
|
52
|
-
error: '',
|
|
53
|
-
configured: feed.configured,
|
|
54
|
-
feedUrl: feed.url,
|
|
55
|
-
channel: feed.channel,
|
|
56
|
-
platform: feed.platform,
|
|
57
|
-
arch: feed.arch,
|
|
58
|
-
installKind,
|
|
59
|
-
updateSupported,
|
|
60
|
-
startupCheck: 'idle'
|
|
61
|
-
};
|
|
62
|
-
let installPromise = null;
|
|
63
|
-
let checkPromise = null;
|
|
64
|
-
let downloadPromise = null;
|
|
65
|
-
let cyclePromise = null;
|
|
66
|
-
let startupPromise = null;
|
|
67
|
-
let checkOutcome = 'idle';
|
|
68
|
-
let installRuntimePreparationStarted = false;
|
|
69
|
-
let installRecoveryPromise = null;
|
|
70
|
-
|
|
71
|
-
const publish = patch => {
|
|
72
|
-
status = { ...status, ...patch };
|
|
73
|
-
onStatus({ ...status });
|
|
74
|
-
};
|
|
75
|
-
const snapshot = () => ({ ...status, packaged: Boolean(app.isPackaged) });
|
|
76
|
-
const recoverPreparedRuntime = error => {
|
|
77
|
-
if (!installRuntimePreparationStarted) return Promise.resolve();
|
|
78
|
-
installRuntimePreparationStarted = false;
|
|
79
|
-
if (!installRecoveryPromise) {
|
|
80
|
-
installRecoveryPromise = Promise.resolve(onInstallError(error))
|
|
81
|
-
.catch(() => undefined)
|
|
82
|
-
.finally(() => {
|
|
83
|
-
installRecoveryPromise = null;
|
|
84
|
-
if (status.state === 'error') installPromise = null;
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
return installRecoveryPromise;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
updater.autoDownload = false;
|
|
91
|
-
updater.autoInstallOnAppQuit = false;
|
|
92
|
-
if (feed.url) updater.setFeedURL({ provider: 'generic', url: feed.url });
|
|
93
|
-
|
|
94
|
-
updater.on('checking-for-update', () => {
|
|
95
|
-
checkOutcome = 'checking';
|
|
96
|
-
publish({ state: 'checking', error: '' });
|
|
97
|
-
});
|
|
98
|
-
updater.on('update-available', info => {
|
|
99
|
-
checkOutcome = 'available';
|
|
100
|
-
publish({
|
|
101
|
-
state: 'available',
|
|
102
|
-
availableVersion: String(info?.version || ''),
|
|
103
|
-
downloaded: false,
|
|
104
|
-
progress: 0,
|
|
105
|
-
error: ''
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
updater.on('update-not-available', () => {
|
|
109
|
-
checkOutcome = 'current';
|
|
110
|
-
publish({ state: 'current', availableVersion: '', downloaded: false, progress: 0, error: '' });
|
|
111
|
-
});
|
|
112
|
-
updater.on('download-progress', progress => {
|
|
113
|
-
publish({ state: 'downloading', progress: Number(progress?.percent || 0), error: '' });
|
|
114
|
-
});
|
|
115
|
-
updater.on('update-downloaded', info => {
|
|
116
|
-
publish({
|
|
117
|
-
state: 'downloaded',
|
|
118
|
-
downloaded: true,
|
|
119
|
-
progress: 100,
|
|
120
|
-
availableVersion: String(info?.version || status.availableVersion || ''),
|
|
121
|
-
error: ''
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
updater.on('error', error => {
|
|
125
|
-
checkOutcome = 'error';
|
|
126
|
-
publish({ state: 'error', error: String(error?.message || error) });
|
|
127
|
-
void recoverPreparedRuntime(error);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const blockedStatus = () => {
|
|
131
|
-
if (!app.isPackaged) {
|
|
132
|
-
return { ...snapshot(), state: 'development', error: 'desktop-updates-require-packaged-app' };
|
|
133
|
-
}
|
|
134
|
-
if (!updateSupported) {
|
|
135
|
-
return { ...snapshot(), state: 'unsupported', error: 'desktop-updates-require-installed-windows-app' };
|
|
136
|
-
}
|
|
137
|
-
return null;
|
|
138
|
-
};
|
|
139
|
-
const unavailableStatus = () => ({
|
|
140
|
-
...snapshot(),
|
|
141
|
-
state: 'unavailable',
|
|
142
|
-
error: feed.error || 'desktop-update-feed-not-configured'
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
const checkForUpdates = async () => {
|
|
146
|
-
const blocked = blockedStatus();
|
|
147
|
-
if (blocked) return blocked;
|
|
148
|
-
if (!feed.url) return unavailableStatus();
|
|
149
|
-
if (checkPromise) return checkPromise;
|
|
150
|
-
|
|
151
|
-
const operation = (async () => {
|
|
152
|
-
checkOutcome = 'checking';
|
|
153
|
-
publish({ state: 'checking', error: '' });
|
|
154
|
-
try {
|
|
155
|
-
const result = await updater.checkForUpdates();
|
|
156
|
-
if (checkOutcome === 'checking') {
|
|
157
|
-
const availableVersion = String(result?.updateInfo?.version || status.availableVersion || '');
|
|
158
|
-
const updateAvailable = Boolean(availableVersion && availableVersion !== app.getVersion());
|
|
159
|
-
checkOutcome = updateAvailable ? 'available' : 'current';
|
|
160
|
-
publish({
|
|
161
|
-
state: checkOutcome,
|
|
162
|
-
availableVersion: updateAvailable ? availableVersion : '',
|
|
163
|
-
downloaded: updateAvailable ? status.downloaded : false,
|
|
164
|
-
progress: updateAvailable ? status.progress : 0,
|
|
165
|
-
error: ''
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
} catch (error) {
|
|
169
|
-
checkOutcome = 'error';
|
|
170
|
-
publish({ state: 'error', error: String(error?.message || error) });
|
|
171
|
-
}
|
|
172
|
-
return snapshot();
|
|
173
|
-
})();
|
|
174
|
-
checkPromise = operation;
|
|
175
|
-
try {
|
|
176
|
-
return await operation;
|
|
177
|
-
} finally {
|
|
178
|
-
if (checkPromise === operation) checkPromise = null;
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
const downloadUpdate = async () => {
|
|
183
|
-
const blocked = blockedStatus();
|
|
184
|
-
if (blocked) return blocked;
|
|
185
|
-
if (!feed.url) return unavailableStatus();
|
|
186
|
-
if (status.downloaded) return snapshot();
|
|
187
|
-
if (downloadPromise) return downloadPromise;
|
|
188
|
-
|
|
189
|
-
const operation = (async () => {
|
|
190
|
-
try {
|
|
191
|
-
publish({ state: 'downloading', progress: Math.max(0, Number(status.progress || 0)), error: '' });
|
|
192
|
-
await updater.downloadUpdate();
|
|
193
|
-
if (!status.downloaded) {
|
|
194
|
-
publish({ state: 'downloaded', downloaded: true, progress: 100, error: '' });
|
|
195
|
-
}
|
|
196
|
-
} catch (error) {
|
|
197
|
-
publish({ state: 'error', error: String(error?.message || error) });
|
|
198
|
-
}
|
|
199
|
-
return snapshot();
|
|
200
|
-
})();
|
|
201
|
-
downloadPromise = operation;
|
|
202
|
-
try {
|
|
203
|
-
return await operation;
|
|
204
|
-
} finally {
|
|
205
|
-
if (downloadPromise === operation) downloadPromise = null;
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
const checkAndDownload = async () => {
|
|
210
|
-
if (cyclePromise) return cyclePromise;
|
|
211
|
-
const operation = (async () => {
|
|
212
|
-
const checked = await checkForUpdates();
|
|
213
|
-
if (checked.state === 'available') return downloadUpdate();
|
|
214
|
-
return checked;
|
|
215
|
-
})();
|
|
216
|
-
cyclePromise = operation;
|
|
217
|
-
try {
|
|
218
|
-
return await operation;
|
|
219
|
-
} finally {
|
|
220
|
-
if (cyclePromise === operation) cyclePromise = null;
|
|
221
|
-
}
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
return {
|
|
225
|
-
getStatus() {
|
|
226
|
-
return snapshot();
|
|
227
|
-
},
|
|
228
|
-
async check() {
|
|
229
|
-
return checkAndDownload();
|
|
230
|
-
},
|
|
231
|
-
async checkAtStartup() {
|
|
232
|
-
if (startupPromise) return startupPromise;
|
|
233
|
-
const operation = (async () => {
|
|
234
|
-
const blocked = blockedStatus();
|
|
235
|
-
if (blocked || !feed.url) return checkForUpdates();
|
|
236
|
-
|
|
237
|
-
publish({ startupCheck: 'checking' });
|
|
238
|
-
const background = checkAndDownload().finally(() => {
|
|
239
|
-
publish({ startupCheck: 'complete' });
|
|
240
|
-
});
|
|
241
|
-
let timeoutId;
|
|
242
|
-
const timeout = new Promise(resolve => {
|
|
243
|
-
timeoutId = setTimeout(
|
|
244
|
-
() => resolve('timeout'),
|
|
245
|
-
Math.max(10, Number(startupCheckTimeoutMs) || 2_500)
|
|
246
|
-
);
|
|
247
|
-
timeoutId.unref?.();
|
|
248
|
-
});
|
|
249
|
-
const result = await Promise.race([background, timeout]);
|
|
250
|
-
clearTimeout(timeoutId);
|
|
251
|
-
if (result === 'timeout') {
|
|
252
|
-
publish({ startupCheck: 'timed-out' });
|
|
253
|
-
return snapshot();
|
|
254
|
-
}
|
|
255
|
-
return result;
|
|
256
|
-
})();
|
|
257
|
-
startupPromise = operation;
|
|
258
|
-
try {
|
|
259
|
-
return await operation;
|
|
260
|
-
} finally {
|
|
261
|
-
if (startupPromise === operation) startupPromise = null;
|
|
262
|
-
}
|
|
263
|
-
},
|
|
264
|
-
async install() {
|
|
265
|
-
const blocked = blockedStatus();
|
|
266
|
-
if (blocked) return blocked;
|
|
267
|
-
if (!feed.url) return unavailableStatus();
|
|
268
|
-
if (installPromise) return installPromise;
|
|
269
|
-
|
|
270
|
-
const operation = (async () => {
|
|
271
|
-
try {
|
|
272
|
-
if (!status.downloaded) {
|
|
273
|
-
const downloadResult = await downloadUpdate();
|
|
274
|
-
if (!downloadResult.downloaded) return downloadResult;
|
|
275
|
-
}
|
|
276
|
-
installRuntimePreparationStarted = true;
|
|
277
|
-
await beforeInstall();
|
|
278
|
-
publish({ state: 'installing', error: '' });
|
|
279
|
-
updater.quitAndInstall(true, true);
|
|
280
|
-
return snapshot();
|
|
281
|
-
} catch (error) {
|
|
282
|
-
await recoverPreparedRuntime(error);
|
|
283
|
-
publish({ state: 'error', error: String(error?.message || error) });
|
|
284
|
-
return snapshot();
|
|
285
|
-
}
|
|
286
|
-
})();
|
|
287
|
-
installPromise = operation;
|
|
288
|
-
try {
|
|
289
|
-
return await operation;
|
|
290
|
-
} finally {
|
|
291
|
-
if (installPromise === operation && status.state !== 'installing') installPromise = null;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
module.exports = { createProductUpdateManager };
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { resolveDesktopUpdateFeed } = require('./update-feed-resolver.cjs');
|
|
6
|
+
|
|
7
|
+
function createProductUpdateManager({
|
|
8
|
+
app,
|
|
9
|
+
onStatus = () => undefined,
|
|
10
|
+
beforeInstall = async () => undefined,
|
|
11
|
+
onInstallError = async () => undefined,
|
|
12
|
+
updater = null,
|
|
13
|
+
platform = process.platform,
|
|
14
|
+
arch = process.arch,
|
|
15
|
+
installKind = 'installed',
|
|
16
|
+
startupCheckTimeoutMs = 2_500,
|
|
17
|
+
updateFeedConfig = null,
|
|
18
|
+
updateChannel = '',
|
|
19
|
+
overrideUrl = process.env.MINDEXEC_UPDATE_URL || ''
|
|
20
|
+
} = {}) {
|
|
21
|
+
if (!app) throw new TypeError('desktop-update-app-required');
|
|
22
|
+
if (!updater) updater = require('electron-updater').autoUpdater;
|
|
23
|
+
|
|
24
|
+
let feedConfig = updateFeedConfig;
|
|
25
|
+
let packageMetadata = {};
|
|
26
|
+
try {
|
|
27
|
+
packageMetadata = JSON.parse(fs.readFileSync(path.join(app.getAppPath(), 'package.json'), 'utf8'));
|
|
28
|
+
} catch {
|
|
29
|
+
packageMetadata = {};
|
|
30
|
+
}
|
|
31
|
+
if (!feedConfig) {
|
|
32
|
+
try {
|
|
33
|
+
feedConfig = JSON.parse(fs.readFileSync(path.join(app.getAppPath(), 'electron', 'update-feed.json'), 'utf8'));
|
|
34
|
+
} catch {
|
|
35
|
+
feedConfig = {};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const packagedChannel = String(updateChannel || packageMetadata?.desktopUpdateChannel || '')
|
|
40
|
+
.trim()
|
|
41
|
+
.toLowerCase();
|
|
42
|
+
if (packagedChannel) feedConfig = { ...feedConfig, channel: packagedChannel };
|
|
43
|
+
const feed = resolveDesktopUpdateFeed({ config: feedConfig, overrideUrl, platform, arch });
|
|
44
|
+
const updateSupported = Boolean(app.isPackaged && installKind === 'installed' && platform === 'win32');
|
|
45
|
+
|
|
46
|
+
let status = {
|
|
47
|
+
state: 'idle',
|
|
48
|
+
currentVersion: app.getVersion(),
|
|
49
|
+
availableVersion: '',
|
|
50
|
+
downloaded: false,
|
|
51
|
+
progress: 0,
|
|
52
|
+
error: '',
|
|
53
|
+
configured: feed.configured,
|
|
54
|
+
feedUrl: feed.url,
|
|
55
|
+
channel: feed.channel,
|
|
56
|
+
platform: feed.platform,
|
|
57
|
+
arch: feed.arch,
|
|
58
|
+
installKind,
|
|
59
|
+
updateSupported,
|
|
60
|
+
startupCheck: 'idle'
|
|
61
|
+
};
|
|
62
|
+
let installPromise = null;
|
|
63
|
+
let checkPromise = null;
|
|
64
|
+
let downloadPromise = null;
|
|
65
|
+
let cyclePromise = null;
|
|
66
|
+
let startupPromise = null;
|
|
67
|
+
let checkOutcome = 'idle';
|
|
68
|
+
let installRuntimePreparationStarted = false;
|
|
69
|
+
let installRecoveryPromise = null;
|
|
70
|
+
|
|
71
|
+
const publish = patch => {
|
|
72
|
+
status = { ...status, ...patch };
|
|
73
|
+
onStatus({ ...status });
|
|
74
|
+
};
|
|
75
|
+
const snapshot = () => ({ ...status, packaged: Boolean(app.isPackaged) });
|
|
76
|
+
const recoverPreparedRuntime = error => {
|
|
77
|
+
if (!installRuntimePreparationStarted) return Promise.resolve();
|
|
78
|
+
installRuntimePreparationStarted = false;
|
|
79
|
+
if (!installRecoveryPromise) {
|
|
80
|
+
installRecoveryPromise = Promise.resolve(onInstallError(error))
|
|
81
|
+
.catch(() => undefined)
|
|
82
|
+
.finally(() => {
|
|
83
|
+
installRecoveryPromise = null;
|
|
84
|
+
if (status.state === 'error') installPromise = null;
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return installRecoveryPromise;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
updater.autoDownload = false;
|
|
91
|
+
updater.autoInstallOnAppQuit = false;
|
|
92
|
+
if (feed.url) updater.setFeedURL({ provider: 'generic', url: feed.url });
|
|
93
|
+
|
|
94
|
+
updater.on('checking-for-update', () => {
|
|
95
|
+
checkOutcome = 'checking';
|
|
96
|
+
publish({ state: 'checking', error: '' });
|
|
97
|
+
});
|
|
98
|
+
updater.on('update-available', info => {
|
|
99
|
+
checkOutcome = 'available';
|
|
100
|
+
publish({
|
|
101
|
+
state: 'available',
|
|
102
|
+
availableVersion: String(info?.version || ''),
|
|
103
|
+
downloaded: false,
|
|
104
|
+
progress: 0,
|
|
105
|
+
error: ''
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
updater.on('update-not-available', () => {
|
|
109
|
+
checkOutcome = 'current';
|
|
110
|
+
publish({ state: 'current', availableVersion: '', downloaded: false, progress: 0, error: '' });
|
|
111
|
+
});
|
|
112
|
+
updater.on('download-progress', progress => {
|
|
113
|
+
publish({ state: 'downloading', progress: Number(progress?.percent || 0), error: '' });
|
|
114
|
+
});
|
|
115
|
+
updater.on('update-downloaded', info => {
|
|
116
|
+
publish({
|
|
117
|
+
state: 'downloaded',
|
|
118
|
+
downloaded: true,
|
|
119
|
+
progress: 100,
|
|
120
|
+
availableVersion: String(info?.version || status.availableVersion || ''),
|
|
121
|
+
error: ''
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
updater.on('error', error => {
|
|
125
|
+
checkOutcome = 'error';
|
|
126
|
+
publish({ state: 'error', error: String(error?.message || error) });
|
|
127
|
+
void recoverPreparedRuntime(error);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const blockedStatus = () => {
|
|
131
|
+
if (!app.isPackaged) {
|
|
132
|
+
return { ...snapshot(), state: 'development', error: 'desktop-updates-require-packaged-app' };
|
|
133
|
+
}
|
|
134
|
+
if (!updateSupported) {
|
|
135
|
+
return { ...snapshot(), state: 'unsupported', error: 'desktop-updates-require-installed-windows-app' };
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
};
|
|
139
|
+
const unavailableStatus = () => ({
|
|
140
|
+
...snapshot(),
|
|
141
|
+
state: 'unavailable',
|
|
142
|
+
error: feed.error || 'desktop-update-feed-not-configured'
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const checkForUpdates = async () => {
|
|
146
|
+
const blocked = blockedStatus();
|
|
147
|
+
if (blocked) return blocked;
|
|
148
|
+
if (!feed.url) return unavailableStatus();
|
|
149
|
+
if (checkPromise) return checkPromise;
|
|
150
|
+
|
|
151
|
+
const operation = (async () => {
|
|
152
|
+
checkOutcome = 'checking';
|
|
153
|
+
publish({ state: 'checking', error: '' });
|
|
154
|
+
try {
|
|
155
|
+
const result = await updater.checkForUpdates();
|
|
156
|
+
if (checkOutcome === 'checking') {
|
|
157
|
+
const availableVersion = String(result?.updateInfo?.version || status.availableVersion || '');
|
|
158
|
+
const updateAvailable = Boolean(availableVersion && availableVersion !== app.getVersion());
|
|
159
|
+
checkOutcome = updateAvailable ? 'available' : 'current';
|
|
160
|
+
publish({
|
|
161
|
+
state: checkOutcome,
|
|
162
|
+
availableVersion: updateAvailable ? availableVersion : '',
|
|
163
|
+
downloaded: updateAvailable ? status.downloaded : false,
|
|
164
|
+
progress: updateAvailable ? status.progress : 0,
|
|
165
|
+
error: ''
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
checkOutcome = 'error';
|
|
170
|
+
publish({ state: 'error', error: String(error?.message || error) });
|
|
171
|
+
}
|
|
172
|
+
return snapshot();
|
|
173
|
+
})();
|
|
174
|
+
checkPromise = operation;
|
|
175
|
+
try {
|
|
176
|
+
return await operation;
|
|
177
|
+
} finally {
|
|
178
|
+
if (checkPromise === operation) checkPromise = null;
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const downloadUpdate = async () => {
|
|
183
|
+
const blocked = blockedStatus();
|
|
184
|
+
if (blocked) return blocked;
|
|
185
|
+
if (!feed.url) return unavailableStatus();
|
|
186
|
+
if (status.downloaded) return snapshot();
|
|
187
|
+
if (downloadPromise) return downloadPromise;
|
|
188
|
+
|
|
189
|
+
const operation = (async () => {
|
|
190
|
+
try {
|
|
191
|
+
publish({ state: 'downloading', progress: Math.max(0, Number(status.progress || 0)), error: '' });
|
|
192
|
+
await updater.downloadUpdate();
|
|
193
|
+
if (!status.downloaded) {
|
|
194
|
+
publish({ state: 'downloaded', downloaded: true, progress: 100, error: '' });
|
|
195
|
+
}
|
|
196
|
+
} catch (error) {
|
|
197
|
+
publish({ state: 'error', error: String(error?.message || error) });
|
|
198
|
+
}
|
|
199
|
+
return snapshot();
|
|
200
|
+
})();
|
|
201
|
+
downloadPromise = operation;
|
|
202
|
+
try {
|
|
203
|
+
return await operation;
|
|
204
|
+
} finally {
|
|
205
|
+
if (downloadPromise === operation) downloadPromise = null;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const checkAndDownload = async () => {
|
|
210
|
+
if (cyclePromise) return cyclePromise;
|
|
211
|
+
const operation = (async () => {
|
|
212
|
+
const checked = await checkForUpdates();
|
|
213
|
+
if (checked.state === 'available') return downloadUpdate();
|
|
214
|
+
return checked;
|
|
215
|
+
})();
|
|
216
|
+
cyclePromise = operation;
|
|
217
|
+
try {
|
|
218
|
+
return await operation;
|
|
219
|
+
} finally {
|
|
220
|
+
if (cyclePromise === operation) cyclePromise = null;
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
getStatus() {
|
|
226
|
+
return snapshot();
|
|
227
|
+
},
|
|
228
|
+
async check() {
|
|
229
|
+
return checkAndDownload();
|
|
230
|
+
},
|
|
231
|
+
async checkAtStartup() {
|
|
232
|
+
if (startupPromise) return startupPromise;
|
|
233
|
+
const operation = (async () => {
|
|
234
|
+
const blocked = blockedStatus();
|
|
235
|
+
if (blocked || !feed.url) return checkForUpdates();
|
|
236
|
+
|
|
237
|
+
publish({ startupCheck: 'checking' });
|
|
238
|
+
const background = checkAndDownload().finally(() => {
|
|
239
|
+
publish({ startupCheck: 'complete' });
|
|
240
|
+
});
|
|
241
|
+
let timeoutId;
|
|
242
|
+
const timeout = new Promise(resolve => {
|
|
243
|
+
timeoutId = setTimeout(
|
|
244
|
+
() => resolve('timeout'),
|
|
245
|
+
Math.max(10, Number(startupCheckTimeoutMs) || 2_500)
|
|
246
|
+
);
|
|
247
|
+
timeoutId.unref?.();
|
|
248
|
+
});
|
|
249
|
+
const result = await Promise.race([background, timeout]);
|
|
250
|
+
clearTimeout(timeoutId);
|
|
251
|
+
if (result === 'timeout') {
|
|
252
|
+
publish({ startupCheck: 'timed-out' });
|
|
253
|
+
return snapshot();
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
})();
|
|
257
|
+
startupPromise = operation;
|
|
258
|
+
try {
|
|
259
|
+
return await operation;
|
|
260
|
+
} finally {
|
|
261
|
+
if (startupPromise === operation) startupPromise = null;
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
async install() {
|
|
265
|
+
const blocked = blockedStatus();
|
|
266
|
+
if (blocked) return blocked;
|
|
267
|
+
if (!feed.url) return unavailableStatus();
|
|
268
|
+
if (installPromise) return installPromise;
|
|
269
|
+
|
|
270
|
+
const operation = (async () => {
|
|
271
|
+
try {
|
|
272
|
+
if (!status.downloaded) {
|
|
273
|
+
const downloadResult = await downloadUpdate();
|
|
274
|
+
if (!downloadResult.downloaded) return downloadResult;
|
|
275
|
+
}
|
|
276
|
+
installRuntimePreparationStarted = true;
|
|
277
|
+
await beforeInstall();
|
|
278
|
+
publish({ state: 'installing', error: '' });
|
|
279
|
+
updater.quitAndInstall(true, true);
|
|
280
|
+
return snapshot();
|
|
281
|
+
} catch (error) {
|
|
282
|
+
await recoverPreparedRuntime(error);
|
|
283
|
+
publish({ state: 'error', error: String(error?.message || error) });
|
|
284
|
+
return snapshot();
|
|
285
|
+
}
|
|
286
|
+
})();
|
|
287
|
+
installPromise = operation;
|
|
288
|
+
try {
|
|
289
|
+
return await operation;
|
|
290
|
+
} finally {
|
|
291
|
+
if (installPromise === operation && status.state !== 'installing') installPromise = null;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
module.exports = { createProductUpdateManager };
|