livedesk 0.1.605 → 0.1.607
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/client/bin/livedesk-client.js +95 -49
- package/client/package.json +5 -5
- package/client/src/runtime/client-runtime-server.js +16 -8
- package/diagnostics/livedesk-mode3-capture-smoke.mjs +177 -110
- package/electron/main.mjs +83 -54
- package/package.json +6 -6
- package/web/dist/app.webmanifest +1 -1
- package/web/dist/assets/{LiveDeskApp-Bv0fQKd_.js → LiveDeskApp-Dw86X0VP.js} +3 -3
- package/web/dist/assets/{index-DRenaErr.js → index-C4QRbhif.js} +2 -2
- package/web/dist/index.html +1 -1
- package/web/dist/livedesk-build-evidence.json +19 -19
- package/web/dist/sw.js +1 -1
package/electron/main.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { spawn } from 'node:child_process';
|
|
|
6
6
|
import { createRequire } from 'node:module';
|
|
7
7
|
import { createProductUpdateManager } from './update-manager.mjs';
|
|
8
8
|
import { createRecurringProductUpdateOwner } from './recurring-update-owner.mjs';
|
|
9
|
-
import { createPkceAuthorizationUrl, exchangePkceCode, fetchSupabaseUser, parsePkceCallbackUrl, refreshSupabaseSession } from './oauth-pkce.mjs';
|
|
9
|
+
import { AUTH_REQUEST_TIMEOUT_MS, createPkceAuthorizationUrl, exchangePkceCode, fetchSupabaseUser, parsePkceCallbackUrl, refreshSupabaseSession } from './oauth-pkce.mjs';
|
|
10
10
|
import { getRuntimeAuthEnvironment, resolveDesktopAuthConfig, resolveDesktopBuildFlavor } from './auth-config.mjs';
|
|
11
11
|
import { createBoundedDesktopLogger } from './bounded-desktop-log.mjs';
|
|
12
12
|
import {
|
|
@@ -671,46 +671,59 @@ async function prepareRuntimeForUpdateInstall() {
|
|
|
671
671
|
throw new Error('desktop-update-install-already-started');
|
|
672
672
|
}
|
|
673
673
|
updateInstallSequenceStarted = true;
|
|
674
|
-
isQuitting = true;
|
|
675
|
-
recurringProductUpdates?.stop();
|
|
676
|
-
try {
|
|
677
|
-
await
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
674
|
+
isQuitting = true;
|
|
675
|
+
recurringProductUpdates?.stop();
|
|
676
|
+
try {
|
|
677
|
+
await quiesceDesktopAuthOwner('desktop-update-install');
|
|
678
|
+
await stopRuntime();
|
|
679
|
+
} catch (error) {
|
|
680
|
+
updateInstallSequenceStarted = false;
|
|
681
|
+
isQuitting = false;
|
|
682
|
+
scheduleDesktopAuthRefresh(readEncryptedSession());
|
|
683
|
+
throw error;
|
|
684
|
+
}
|
|
683
685
|
}
|
|
684
686
|
|
|
685
687
|
async function recoverRuntimeAfterUpdateInstallError(error) {
|
|
686
688
|
log(`desktop update install launch failed after runtime drain: ${error?.message || error}`);
|
|
687
|
-
updateInstallSequenceStarted = false;
|
|
688
|
-
isQuitting = false;
|
|
689
|
-
|
|
689
|
+
updateInstallSequenceStarted = false;
|
|
690
|
+
isQuitting = false;
|
|
691
|
+
scheduleDesktopAuthRefresh(readEncryptedSession());
|
|
692
|
+
if (!runtimeChild) {
|
|
690
693
|
startRuntime();
|
|
691
694
|
const ready = await waitForRuntime();
|
|
692
695
|
if (ready) mainWindow?.loadURL(LOCAL_RUNTIME_URL);
|
|
693
696
|
}
|
|
694
697
|
}
|
|
695
698
|
|
|
696
|
-
async function syncSessionToRuntime(session) {
|
|
697
|
-
const normalized = normalizeSession(session);
|
|
698
|
-
if (!normalized) throw new Error('oauth-session-invalid');
|
|
699
|
-
const
|
|
700
|
-
const
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
699
|
+
async function syncSessionToRuntime(session) {
|
|
700
|
+
const normalized = normalizeSession(session);
|
|
701
|
+
if (!normalized) throw new Error('oauth-session-invalid');
|
|
702
|
+
const deadline = Date.now() + AUTH_REQUEST_TIMEOUT_MS + 2_500;
|
|
703
|
+
const csrfToken = await getRuntimeCsrfToken(Math.min(deadline, Date.now() + 2_500));
|
|
704
|
+
const response = await fetchBeforeRuntimeDeadline(
|
|
705
|
+
fetch,
|
|
706
|
+
`${LOCAL_RUNTIME_URL}api/auth/session`,
|
|
707
|
+
{
|
|
708
|
+
method: 'POST',
|
|
709
|
+
headers: {
|
|
710
|
+
'Content-Type': 'application/json',
|
|
711
|
+
...(csrfToken ? { 'X-LiveDesk-CSRF': csrfToken } : {})
|
|
712
|
+
},
|
|
713
|
+
body: JSON.stringify({
|
|
714
|
+
accessToken: normalized.access_token,
|
|
715
|
+
refreshToken: normalized.refresh_token,
|
|
716
|
+
expiresAt: normalized.expires_at,
|
|
717
|
+
userId: normalized.user?.id,
|
|
718
|
+
user: { id: normalized.user?.id, email: normalized.user?.email }
|
|
719
|
+
})
|
|
720
|
+
},
|
|
721
|
+
{
|
|
722
|
+
deadline,
|
|
723
|
+
maxDurationMs: Math.min(AUTH_REQUEST_TIMEOUT_MS, remainingRuntimeDeadlineMs(deadline)),
|
|
724
|
+
label: 'runtime-auth-sync-deadline'
|
|
725
|
+
}
|
|
726
|
+
);
|
|
714
727
|
if (!response.ok) {
|
|
715
728
|
const payload = await response.json().catch(() => ({}));
|
|
716
729
|
throw new Error(String(payload?.error || `runtime-session-sync-failed:${response.status}`));
|
|
@@ -854,18 +867,29 @@ async function restoreEncryptedSessionOwned({ syncRuntime = true } = {}) {
|
|
|
854
867
|
return session;
|
|
855
868
|
}
|
|
856
869
|
|
|
857
|
-
async function restoreEncryptedSession(options = {}) {
|
|
858
|
-
if (desktopSessionRestorePromise) return desktopSessionRestorePromise;
|
|
859
|
-
|
|
870
|
+
async function restoreEncryptedSession(options = {}) {
|
|
871
|
+
if (desktopSessionRestorePromise) return desktopSessionRestorePromise;
|
|
872
|
+
if (isQuitting) return readEncryptedSession();
|
|
873
|
+
const operation = restoreEncryptedSessionOwned(options);
|
|
860
874
|
desktopSessionRestorePromise = operation;
|
|
861
875
|
try {
|
|
862
876
|
return await operation;
|
|
863
877
|
} finally {
|
|
864
878
|
if (desktopSessionRestorePromise === operation) desktopSessionRestorePromise = null;
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
async function
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
async function quiesceDesktopAuthOwner(reason = 'application-exit') {
|
|
883
|
+
clearDesktopAuthRefreshTimer();
|
|
884
|
+
while (desktopSessionRestorePromise) {
|
|
885
|
+
const pending = desktopSessionRestorePromise;
|
|
886
|
+
log(`waiting for secure auth owner before ${reason}`);
|
|
887
|
+
await pending;
|
|
888
|
+
if (desktopSessionRestorePromise === pending) break;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
async function signOutDesktopSession() {
|
|
869
893
|
desktopSessionEpoch += 1;
|
|
870
894
|
desktopAuthInvalidationGuard.observeSuccess();
|
|
871
895
|
clearEncryptedSession();
|
|
@@ -1071,19 +1095,21 @@ function registerIpc() {
|
|
|
1071
1095
|
if (quitSequenceStarted || updateInstallSequenceStarted) {
|
|
1072
1096
|
return { ok: false, error: 'application-exit-already-started' };
|
|
1073
1097
|
}
|
|
1074
|
-
quitSequenceStarted = true;
|
|
1075
|
-
isQuitting = true;
|
|
1076
|
-
try {
|
|
1077
|
-
await
|
|
1098
|
+
quitSequenceStarted = true;
|
|
1099
|
+
isQuitting = true;
|
|
1100
|
+
try {
|
|
1101
|
+
await quiesceDesktopAuthOwner('application-restart');
|
|
1102
|
+
await stopRuntime();
|
|
1078
1103
|
await desktopClipboardOwner?.close();
|
|
1079
1104
|
await closeDesktopLog();
|
|
1080
1105
|
app.relaunch();
|
|
1081
1106
|
app.exit(0);
|
|
1082
1107
|
return { ok: true };
|
|
1083
|
-
} catch (error) {
|
|
1084
|
-
isQuitting = false;
|
|
1085
|
-
quitSequenceStarted = false;
|
|
1086
|
-
|
|
1108
|
+
} catch (error) {
|
|
1109
|
+
isQuitting = false;
|
|
1110
|
+
quitSequenceStarted = false;
|
|
1111
|
+
scheduleDesktopAuthRefresh(readEncryptedSession());
|
|
1112
|
+
updateTray('Runtime cleanup blocked');
|
|
1087
1113
|
log(`runtime cleanup blocked application restart: ${error?.message || error}`);
|
|
1088
1114
|
if (!runtimeChild) {
|
|
1089
1115
|
startRuntime();
|
|
@@ -1277,19 +1303,22 @@ if (!app.requestSingleInstanceLock()) {
|
|
|
1277
1303
|
if (quitSequenceStarted) return;
|
|
1278
1304
|
event.preventDefault();
|
|
1279
1305
|
recurringProductUpdates?.stop();
|
|
1280
|
-
quitSequenceStarted = true;
|
|
1281
|
-
isQuitting = true;
|
|
1282
|
-
void
|
|
1283
|
-
return
|
|
1306
|
+
quitSequenceStarted = true;
|
|
1307
|
+
isQuitting = true;
|
|
1308
|
+
void quiesceDesktopAuthOwner('application-quit').then(() => {
|
|
1309
|
+
return stopRuntime();
|
|
1310
|
+
}).then(() => {
|
|
1311
|
+
return desktopClipboardOwner?.close();
|
|
1284
1312
|
}).then(() => {
|
|
1285
1313
|
return closeDesktopLog();
|
|
1286
1314
|
}).then(() => {
|
|
1287
1315
|
app.quit();
|
|
1288
1316
|
}).catch(error => {
|
|
1289
|
-
isQuitting = false;
|
|
1290
|
-
quitSequenceStarted = false;
|
|
1291
|
-
updateInstallSequenceStarted = false;
|
|
1292
|
-
|
|
1317
|
+
isQuitting = false;
|
|
1318
|
+
quitSequenceStarted = false;
|
|
1319
|
+
updateInstallSequenceStarted = false;
|
|
1320
|
+
scheduleDesktopAuthRefresh(readEncryptedSession());
|
|
1321
|
+
updateTray('Runtime cleanup blocked');
|
|
1293
1322
|
log(`runtime cleanup blocked application quit: ${error?.message || error}`);
|
|
1294
1323
|
});
|
|
1295
1324
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livedesk",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"livedeskClientVersion": "0.1.
|
|
3
|
+
"version": "0.1.607",
|
|
4
|
+
"livedeskClientVersion": "0.1.262",
|
|
5
5
|
"buildFlavor": "production",
|
|
6
6
|
"description": "VuvoDesk Hub and client launcher",
|
|
7
7
|
"type": "module",
|
|
@@ -51,10 +51,10 @@
|
|
|
51
51
|
"ws": "^8.18.3"
|
|
52
52
|
},
|
|
53
53
|
"optionalDependencies": {
|
|
54
|
-
"@livedesk/fast-linux-x64": "0.1.
|
|
55
|
-
"@livedesk/fast-osx-arm64": "0.1.
|
|
56
|
-
"@livedesk/fast-osx-x64": "0.1.
|
|
57
|
-
"@livedesk/fast-win-x64": "0.1.
|
|
54
|
+
"@livedesk/fast-linux-x64": "0.1.458",
|
|
55
|
+
"@livedesk/fast-osx-arm64": "0.1.458",
|
|
56
|
+
"@livedesk/fast-osx-x64": "0.1.458",
|
|
57
|
+
"@livedesk/fast-win-x64": "0.1.458"
|
|
58
58
|
},
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public"
|
package/web/dist/app.webmanifest
CHANGED