@nervekit/desktop 0.1.0

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.
Files changed (87) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/build/README.md +1 -0
  4. package/build/icons/1024x1024.png +0 -0
  5. package/build/icons/128x128.png +0 -0
  6. package/build/icons/16x16.png +0 -0
  7. package/build/icons/24x24.png +0 -0
  8. package/build/icons/256x256.png +0 -0
  9. package/build/icons/32x32.png +0 -0
  10. package/build/icons/48x48.png +0 -0
  11. package/build/icons/512x512.png +0 -0
  12. package/build/icons/64x64.png +0 -0
  13. package/build/tray/tray-dark-16.png +0 -0
  14. package/build/tray/tray-dark-24.png +0 -0
  15. package/build/tray/tray-dark.png +0 -0
  16. package/build/tray/tray-light-16.png +0 -0
  17. package/build/tray/tray-light-24.png +0 -0
  18. package/build/tray/tray-light.png +0 -0
  19. package/build/tray/tray-template-16.png +0 -0
  20. package/build/tray/tray-template-24.png +0 -0
  21. package/build/tray/tray-template.png +0 -0
  22. package/dist/app/cli-options.d.ts +7 -0
  23. package/dist/app/cli-options.d.ts.map +1 -0
  24. package/dist/app/cli-options.js +101 -0
  25. package/dist/app/cli-options.js.map +1 -0
  26. package/dist/bin.d.ts +3 -0
  27. package/dist/bin.d.ts.map +1 -0
  28. package/dist/bin.js +75 -0
  29. package/dist/bin.js.map +1 -0
  30. package/dist/daemon-helpers.d.ts +31 -0
  31. package/dist/daemon-helpers.d.ts.map +1 -0
  32. package/dist/daemon-helpers.js +224 -0
  33. package/dist/daemon-helpers.js.map +1 -0
  34. package/dist/daemon.d.ts +38 -0
  35. package/dist/daemon.d.ts.map +1 -0
  36. package/dist/daemon.js +494 -0
  37. package/dist/daemon.js.map +1 -0
  38. package/dist/electron.d.ts +3 -0
  39. package/dist/electron.d.ts.map +1 -0
  40. package/dist/electron.js +4 -0
  41. package/dist/electron.js.map +1 -0
  42. package/dist/ipc/notifications-ipc.d.ts +4 -0
  43. package/dist/ipc/notifications-ipc.d.ts.map +1 -0
  44. package/dist/ipc/notifications-ipc.js +42 -0
  45. package/dist/ipc/notifications-ipc.js.map +1 -0
  46. package/dist/ipc/window-ipc.d.ts +15 -0
  47. package/dist/ipc/window-ipc.d.ts.map +1 -0
  48. package/dist/ipc/window-ipc.js +71 -0
  49. package/dist/ipc/window-ipc.js.map +1 -0
  50. package/dist/logging.d.ts +7 -0
  51. package/dist/logging.d.ts.map +1 -0
  52. package/dist/logging.js +61 -0
  53. package/dist/logging.js.map +1 -0
  54. package/dist/main.d.ts +2 -0
  55. package/dist/main.d.ts.map +1 -0
  56. package/dist/main.js +328 -0
  57. package/dist/main.js.map +1 -0
  58. package/dist/preload.cjs +44 -0
  59. package/dist/settings/desktop-settings.d.ts +4 -0
  60. package/dist/settings/desktop-settings.d.ts.map +1 -0
  61. package/dist/settings/desktop-settings.js +45 -0
  62. package/dist/settings/desktop-settings.js.map +1 -0
  63. package/dist/shared/ozone-platform.d.ts +3 -0
  64. package/dist/shared/ozone-platform.d.ts.map +1 -0
  65. package/dist/shared/ozone-platform.js +16 -0
  66. package/dist/shared/ozone-platform.js.map +1 -0
  67. package/dist/tray/tray.d.ts +21 -0
  68. package/dist/tray/tray.d.ts.map +1 -0
  69. package/dist/tray/tray.js +122 -0
  70. package/dist/tray/tray.js.map +1 -0
  71. package/dist/types.d.ts +26 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/types.js +2 -0
  74. package/dist/types.js.map +1 -0
  75. package/dist/window/loading-pages.d.ts +4 -0
  76. package/dist/window/loading-pages.d.ts.map +1 -0
  77. package/dist/window/loading-pages.js +137 -0
  78. package/dist/window/loading-pages.js.map +1 -0
  79. package/dist/window/navigation-guards.d.ts +3 -0
  80. package/dist/window/navigation-guards.d.ts.map +1 -0
  81. package/dist/window/navigation-guards.js +53 -0
  82. package/dist/window/navigation-guards.js.map +1 -0
  83. package/dist/window/preload-paths.d.ts +5 -0
  84. package/dist/window/preload-paths.d.ts.map +1 -0
  85. package/dist/window/preload-paths.js +31 -0
  86. package/dist/window/preload-paths.js.map +1 -0
  87. package/package.json +54 -0
@@ -0,0 +1,71 @@
1
+ import { BrowserWindow, clipboard, ipcMain } from "../electron.js";
2
+ import { desktopLog } from "../logging.js";
3
+ export function registerDesktopIpc(options) {
4
+ ipcMain.handle("desktop.window.minimize", (event) => {
5
+ windowFromEvent(event)?.minimize();
6
+ });
7
+ ipcMain.handle("desktop.window.toggleMaximize", (event) => {
8
+ const window = windowFromEvent(event);
9
+ if (!window)
10
+ return;
11
+ if (window.isMaximized())
12
+ window.unmaximize();
13
+ else
14
+ window.maximize();
15
+ options.sendWindowState(window);
16
+ });
17
+ ipcMain.handle("desktop.window.close", (event, closeOptions) => {
18
+ const startedAt = Date.now();
19
+ const window = windowFromEvent(event);
20
+ if (!window)
21
+ return;
22
+ updateCloseToTrayOption(closeOptions, options.setCloseToTray);
23
+ void desktopLog("info", "window", "Desktop close requested", {
24
+ durationMs: Date.now() - startedAt,
25
+ context: { closeToTray: options.getCloseToTray() },
26
+ });
27
+ options.closeWindowOrQuit(window, "titlebar-close");
28
+ });
29
+ ipcMain.handle("desktop.settings.setCloseToTray", (_event, value) => {
30
+ if (typeof value !== "boolean") {
31
+ throw new Error("desktop.settings.setCloseToTray expects a boolean.");
32
+ }
33
+ options.setCloseToTray(value);
34
+ return { closeToTray: options.getCloseToTray() };
35
+ });
36
+ ipcMain.handle("desktop.window.getState", (event) => {
37
+ const window = windowFromEvent(event);
38
+ return window
39
+ ? windowState(window)
40
+ : {
41
+ maximized: false,
42
+ focused: BrowserWindow.getFocusedWindow() !== null,
43
+ };
44
+ });
45
+ ipcMain.handle("desktop.notifications.show", (_event, payload) => options.showDesktopNotification(payload));
46
+ ipcMain.handle("desktop.clipboard.writeText", (_event, text) => {
47
+ if (typeof text !== "string") {
48
+ throw new Error("desktop.clipboard.writeText expects a string.");
49
+ }
50
+ clipboard.writeText(text);
51
+ return { ok: true };
52
+ });
53
+ }
54
+ export function windowState(window) {
55
+ return {
56
+ maximized: window.isMaximized(),
57
+ focused: window.isFocused(),
58
+ };
59
+ }
60
+ function windowFromEvent(event) {
61
+ const window = BrowserWindow.fromWebContents(event.sender);
62
+ return window && !window.isDestroyed() ? window : undefined;
63
+ }
64
+ function updateCloseToTrayOption(options, setCloseToTray) {
65
+ if (!options || typeof options !== "object")
66
+ return;
67
+ const value = options.closeToTray;
68
+ if (typeof value === "boolean")
69
+ setCloseToTray(value);
70
+ }
71
+ //# sourceMappingURL=window-ipc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"window-ipc.js","sourceRoot":"","sources":["../../src/ipc/window-ipc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { type ApplicationLogLevel } from "@nervekit/shared";
2
+ export declare function desktopLog(level: ApplicationLogLevel, component: string, message: string, details?: {
3
+ context?: Record<string, unknown>;
4
+ error?: unknown;
5
+ durationMs?: number;
6
+ }): Promise<void>;
7
+ //# sourceMappingURL=logging.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,mBAAmB,EAGzB,MAAM,kBAAkB,CAAC;AAI1B,wBAAsB,UAAU,CAC9B,KAAK,EAAE,mBAAmB,EAC1B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CAChB,GACL,OAAO,CAAC,IAAI,CAAC,CAsBf"}
@@ -0,0 +1,61 @@
1
+ import { appendFile, mkdir } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ import { createId, } from "@nervekit/shared";
5
+ let seq = 0;
6
+ export async function desktopLog(level, component, message, details = {}) {
7
+ const ts = new Date().toISOString();
8
+ seq += 1;
9
+ const record = {
10
+ seq,
11
+ id: createId("log"),
12
+ ts,
13
+ level,
14
+ source: "desktop",
15
+ component,
16
+ message,
17
+ durationMs: details.durationMs,
18
+ context: details.context,
19
+ error: details.error ? serializeError(details.error) : undefined,
20
+ };
21
+ const path = join(resolveDataDir(), "logs", `desktop-${ts.slice(0, 10)}.jsonl`);
22
+ await mkdir(dirname(path), { recursive: true });
23
+ await appendFile(path, `${JSON.stringify(record)}\n`, "utf8");
24
+ }
25
+ function resolveDataDir() {
26
+ const explicitHome = process.env.NERVE_HOME;
27
+ return explicitHome?.trim() ? explicitHome : join(homedir(), ".nerve");
28
+ }
29
+ function serializeError(error) {
30
+ if (error instanceof Error) {
31
+ return { name: error.name, message: error.message, stack: error.stack };
32
+ }
33
+ if (typeof error === "string") {
34
+ return { message: error };
35
+ }
36
+ if (error && typeof error === "object") {
37
+ const pretty = safeStringify(error);
38
+ const message = typeof error.message === "string"
39
+ ? error.message
40
+ : pretty.split("\n", 1)[0];
41
+ return { message, stack: pretty };
42
+ }
43
+ return { message: String(error) };
44
+ }
45
+ function safeStringify(value) {
46
+ try {
47
+ const seen = new WeakSet();
48
+ return JSON.stringify(value, (_key, val) => {
49
+ if (val && typeof val === "object") {
50
+ if (seen.has(val))
51
+ return "[Circular]";
52
+ seen.add(val);
53
+ }
54
+ return val;
55
+ }, 2);
56
+ }
57
+ catch {
58
+ return String(value);
59
+ }
60
+ }
61
+ //# sourceMappingURL=logging.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../src/logging.ts"],"names":[],"mappings":"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"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":""}
package/dist/main.js ADDED
@@ -0,0 +1,328 @@
1
+ import { applyElectronOzonePlatform, parseDesktopOptions, parseElectronOzonePlatform, } from "./app/cli-options.js";
2
+ import { ensureDaemon, } from "./daemon.js";
3
+ import { app, BrowserWindow, nativeTheme } from "./electron.js";
4
+ import { showDesktopNotification } from "./ipc/notifications-ipc.js";
5
+ import { registerDesktopIpc, windowState } from "./ipc/window-ipc.js";
6
+ import { desktopLog } from "./logging.js";
7
+ import { installDaemonCookie, refreshDesktopSettingsFromDaemon, } from "./settings/desktop-settings.js";
8
+ import { createTrayController } from "./tray/tray.js";
9
+ import { createDataUrl, errorHtml, loadingHtml, } from "./window/loading-pages.js";
10
+ import { installNavigationGuards } from "./window/navigation-guards.js";
11
+ import { resolveAppIconPath, resolvePackagedWebDistPath, resolvePreloadPath, } from "./window/preload-paths.js";
12
+ const desktopOptions = parseDesktopOptions(process.argv.slice(1));
13
+ const electronOzonePlatform = parseElectronOzonePlatform(process.env.NERVE_ELECTRON_OZONE_PLATFORM);
14
+ applyElectronOzonePlatform(electronOzonePlatform);
15
+ let mainWindow;
16
+ let managedDaemon;
17
+ let daemonStopped = false;
18
+ let appQuitting = false;
19
+ let closeToTray = true;
20
+ let stopDaemonPromise;
21
+ let unsubscribeDaemonStatus;
22
+ const trayController = createTrayController({
23
+ getMainWindow: () => mainWindow,
24
+ getManagedDaemon: () => managedDaemon,
25
+ showMainWindow,
26
+ hideWindow,
27
+ requestQuit,
28
+ restartDaemon: () => {
29
+ void managedDaemon?.restart().catch((error) => {
30
+ void desktopLog("error", "daemon", "Manual daemon restart failed", {
31
+ error,
32
+ });
33
+ });
34
+ },
35
+ });
36
+ const gotSingleInstanceLock = app.requestSingleInstanceLock();
37
+ if (!gotSingleInstanceLock) {
38
+ app.quit();
39
+ }
40
+ else {
41
+ app.setName("Nerve");
42
+ app.setAppUserModelId("io.github.thilinatlm.nerve");
43
+ registerDesktopIpc({
44
+ getCloseToTray: () => closeToTray,
45
+ setCloseToTray: (value) => {
46
+ closeToTray = value;
47
+ },
48
+ closeWindowOrQuit,
49
+ sendWindowState,
50
+ showDesktopNotification: (payload) => showDesktopNotification(payload, showMainWindow),
51
+ });
52
+ app.on("second-instance", () => {
53
+ void desktopLog("info", "app", "Existing desktop instance handled second launch");
54
+ void showMainWindow();
55
+ });
56
+ app
57
+ .whenReady()
58
+ .then(async () => {
59
+ void desktopLog("info", "app", "Electron app ready");
60
+ trayController.ensureTray();
61
+ nativeTheme.on("updated", trayController.updateTrayIcon);
62
+ await openMainWindow();
63
+ })
64
+ .catch((error) => {
65
+ void desktopLog("error", "app", "Failed during app startup", { error });
66
+ console.error(error);
67
+ requestQuit({ source: "startup-error" });
68
+ });
69
+ app.on("activate", () => {
70
+ if (BrowserWindow.getAllWindows().length === 0)
71
+ void openMainWindow();
72
+ else
73
+ void showMainWindow();
74
+ });
75
+ app.on("window-all-closed", () => {
76
+ if (appQuitting && process.platform !== "darwin")
77
+ app.quit();
78
+ });
79
+ app.on("before-quit", (event) => {
80
+ const startedAt = Date.now();
81
+ appQuitting = true;
82
+ notifyQuitStarted();
83
+ void desktopLog("info", "app", "Electron before-quit received", {
84
+ context: {
85
+ daemonOwned: managedDaemon?.owned ?? false,
86
+ daemonStopped,
87
+ stopInProgress: stopDaemonPromise !== undefined,
88
+ },
89
+ });
90
+ if (daemonStopped || !managedDaemon?.owned)
91
+ return;
92
+ event.preventDefault();
93
+ if (stopDaemonPromise)
94
+ return;
95
+ void desktopLog("info", "daemon", "Stopping owned daemon before quit");
96
+ stopDaemonPromise = managedDaemon
97
+ .stop()
98
+ .then(() => {
99
+ void desktopLog("info", "daemon", "Owned daemon stopped", {
100
+ durationMs: Date.now() - startedAt,
101
+ });
102
+ })
103
+ .catch((error) => {
104
+ void desktopLog("error", "daemon", "Failed to stop Nerve daemon", {
105
+ error,
106
+ durationMs: Date.now() - startedAt,
107
+ });
108
+ console.error("Failed to stop Nerve daemon", error);
109
+ })
110
+ .finally(() => {
111
+ daemonStopped = true;
112
+ void desktopLog("info", "app", "Retrying Electron quit after daemon stop", {
113
+ durationMs: Date.now() - startedAt,
114
+ });
115
+ app.quit();
116
+ });
117
+ });
118
+ process.on("SIGINT", (signal) => requestQuit({ source: "signal", signal }));
119
+ process.on("SIGTERM", (signal) => requestQuit({ source: "signal", signal }));
120
+ }
121
+ async function openMainWindow() {
122
+ if (mainWindow) {
123
+ showWindow(mainWindow);
124
+ return;
125
+ }
126
+ const window = createMainWindow();
127
+ void desktopLog("info", "window", "Opening main window");
128
+ mainWindow = window;
129
+ window.on("closed", () => {
130
+ if (mainWindow === window)
131
+ mainWindow = undefined;
132
+ });
133
+ await window.loadURL(createDataUrl(loadingHtml()));
134
+ try {
135
+ managedDaemon ??= await ensureDaemon({
136
+ webDistPath: resolvePackagedWebDistPath(),
137
+ ...desktopOptions,
138
+ });
139
+ void desktopLog("info", "daemon", "Daemon connection established", {
140
+ context: {
141
+ url: managedDaemon.url,
142
+ mode: managedDaemon.mode,
143
+ owned: managedDaemon.owned,
144
+ shareUrlAvailable: Boolean(managedDaemon.shareUrl),
145
+ mobileHttpsAvailable: Boolean(managedDaemon.mobileSetupUrl),
146
+ },
147
+ });
148
+ await installDaemonCookie(managedDaemon);
149
+ await refreshDesktopSettingsFromDaemon(managedDaemon, (value) => {
150
+ closeToTray = value;
151
+ });
152
+ await clearDesktopServiceWorkerStorage(window, managedDaemon.url);
153
+ subscribeToDaemonStatus(managedDaemon);
154
+ trayController.updateTrayMenu();
155
+ if (window.isDestroyed())
156
+ return;
157
+ await window.loadURL(managedDaemon.url);
158
+ }
159
+ catch (error) {
160
+ void desktopLog("error", "daemon", "Failed to open Nerve daemon", {
161
+ error,
162
+ });
163
+ console.error(error);
164
+ if (!window.isDestroyed())
165
+ await window.loadURL(createDataUrl(errorHtml(error)));
166
+ }
167
+ }
168
+ async function clearDesktopServiceWorkerStorage(window, daemonUrl) {
169
+ if (window.isDestroyed())
170
+ return;
171
+ const startedAt = Date.now();
172
+ try {
173
+ const origin = new URL(daemonUrl).origin;
174
+ await window.webContents.session.clearStorageData({
175
+ origin,
176
+ storages: ["serviceworkers", "cachestorage"],
177
+ });
178
+ void desktopLog("info", "window", "Cleared desktop PWA cache storage", {
179
+ durationMs: Date.now() - startedAt,
180
+ context: { origin },
181
+ });
182
+ }
183
+ catch (error) {
184
+ void desktopLog("warn", "window", "Failed to clear desktop PWA cache storage", {
185
+ error,
186
+ durationMs: Date.now() - startedAt,
187
+ context: { daemonUrl },
188
+ });
189
+ }
190
+ }
191
+ function subscribeToDaemonStatus(daemon) {
192
+ unsubscribeDaemonStatus?.();
193
+ unsubscribeDaemonStatus = daemon.onStatusChange((status, info) => {
194
+ void handleDaemonStatusChange(status, info);
195
+ });
196
+ }
197
+ async function handleDaemonStatusChange(status, info) {
198
+ void desktopLog("info", "daemon", "Daemon status changed", {
199
+ context: { status, attempt: info?.attempt, error: info?.error },
200
+ });
201
+ trayController.updateTrayMenu();
202
+ const window = mainWindow;
203
+ if (appQuitting || !window || window.isDestroyed())
204
+ return;
205
+ try {
206
+ if (status === "restarting") {
207
+ await window.loadURL(createDataUrl(loadingHtml("Reconnecting to Nerve daemon…")));
208
+ }
209
+ else if (status === "ready" && managedDaemon) {
210
+ await window.loadURL(managedDaemon.url);
211
+ }
212
+ else if (status === "failed") {
213
+ await window.loadURL(createDataUrl(errorHtml(new Error(info?.error ?? "The Nerve daemon stopped and could not restart."))));
214
+ }
215
+ }
216
+ catch (error) {
217
+ void desktopLog("error", "daemon", "Failed to update window for status", {
218
+ error,
219
+ context: { status },
220
+ });
221
+ }
222
+ }
223
+ function createMainWindow() {
224
+ const window = new BrowserWindow({
225
+ width: 1320,
226
+ height: 860,
227
+ minWidth: 960,
228
+ minHeight: 640,
229
+ autoHideMenuBar: true,
230
+ frame: false,
231
+ title: "Nerve",
232
+ ...(process.platform === "darwin" ? {} : { icon: resolveAppIconPath() }),
233
+ webPreferences: {
234
+ contextIsolation: true,
235
+ nodeIntegration: false,
236
+ preload: resolvePreloadPath(),
237
+ sandbox: true,
238
+ },
239
+ });
240
+ installWindowLifecycle(window);
241
+ installNavigationGuards(window, () => managedDaemon?.url);
242
+ return window;
243
+ }
244
+ function installWindowLifecycle(window) {
245
+ window.on("close", (event) => {
246
+ if (appQuitting)
247
+ return;
248
+ event.preventDefault();
249
+ closeWindowOrQuit(window, "native-window-close");
250
+ });
251
+ window.on("maximize", () => sendWindowState(window));
252
+ window.on("unmaximize", () => sendWindowState(window));
253
+ window.on("focus", () => sendWindowState(window));
254
+ window.on("blur", () => sendWindowState(window));
255
+ }
256
+ function sendWindowState(window) {
257
+ if (window.isDestroyed())
258
+ return;
259
+ window.webContents.send("desktop.window.stateChanged", windowState(window));
260
+ }
261
+ async function showMainWindow() {
262
+ if (!mainWindow) {
263
+ await openMainWindow();
264
+ return;
265
+ }
266
+ showWindow(mainWindow);
267
+ }
268
+ function showWindow(window) {
269
+ if (window.isMinimized())
270
+ window.restore();
271
+ window.show();
272
+ window.focus();
273
+ trayController.updateTrayMenu();
274
+ sendWindowState(window);
275
+ }
276
+ function hideWindow(window) {
277
+ window.hide();
278
+ trayController.updateTrayMenu();
279
+ sendWindowState(window);
280
+ }
281
+ function closeWindowOrQuit(window, source = "unknown") {
282
+ const startedAt = Date.now();
283
+ if (closeToTray && trayController.hasTray() && !appQuitting) {
284
+ hideWindow(window);
285
+ void desktopLog("info", "window", "Window hidden to tray", {
286
+ durationMs: Date.now() - startedAt,
287
+ context: { source },
288
+ });
289
+ return;
290
+ }
291
+ void desktopLog("info", "window", "Window close is quitting app", {
292
+ durationMs: Date.now() - startedAt,
293
+ context: { source },
294
+ });
295
+ requestQuit({ source, hideWindows: true });
296
+ }
297
+ function requestQuit(options = {}) {
298
+ const startedAt = Date.now();
299
+ appQuitting = true;
300
+ notifyQuitStarted();
301
+ if (options.hideWindows)
302
+ hideAllWindowsForQuit();
303
+ void desktopLog("info", "app", "Electron quit requested", {
304
+ durationMs: Date.now() - startedAt,
305
+ context: {
306
+ source: options.source ?? "unknown",
307
+ signal: options.signal,
308
+ hideWindows: options.hideWindows ?? false,
309
+ daemonOwned: managedDaemon?.owned ?? false,
310
+ },
311
+ });
312
+ app.quit();
313
+ }
314
+ function notifyQuitStarted() {
315
+ for (const window of BrowserWindow.getAllWindows()) {
316
+ if (window.isDestroyed())
317
+ continue;
318
+ window.webContents.send("desktop.app.quitStarted");
319
+ }
320
+ }
321
+ function hideAllWindowsForQuit() {
322
+ for (const window of BrowserWindow.getAllWindows()) {
323
+ if (!window.isDestroyed() && window.isVisible())
324
+ window.hide();
325
+ }
326
+ trayController.updateTrayMenu();
327
+ }
328
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ const { contextBridge, ipcRenderer } = require("electron");
2
+
3
+ contextBridge.exposeInMainWorld("nerveDesktop", {
4
+ kind: "electron",
5
+ platform: process.platform,
6
+ window: {
7
+ minimize: () => ipcRenderer.invoke("desktop.window.minimize"),
8
+ toggleMaximize: () => ipcRenderer.invoke("desktop.window.toggleMaximize"),
9
+ close: (options) => ipcRenderer.invoke("desktop.window.close", options),
10
+ getState: () => ipcRenderer.invoke("desktop.window.getState"),
11
+ onStateChange: (listener) => {
12
+ const handler = (_event, state) => {
13
+ listener(state);
14
+ };
15
+ ipcRenderer.on("desktop.window.stateChanged", handler);
16
+ return () => {
17
+ ipcRenderer.off("desktop.window.stateChanged", handler);
18
+ };
19
+ },
20
+ },
21
+ app: {
22
+ onQuitStarted: (listener) => {
23
+ const handler = () => {
24
+ listener();
25
+ };
26
+ ipcRenderer.on("desktop.app.quitStarted", handler);
27
+ return () => {
28
+ ipcRenderer.off("desktop.app.quitStarted", handler);
29
+ };
30
+ },
31
+ },
32
+ settings: {
33
+ setCloseToTray: (closeToTray) =>
34
+ ipcRenderer.invoke("desktop.settings.setCloseToTray", closeToTray),
35
+ },
36
+ notifications: {
37
+ show: (payload) =>
38
+ ipcRenderer.invoke("desktop.notifications.show", payload),
39
+ },
40
+ clipboard: {
41
+ writeText: (text) =>
42
+ ipcRenderer.invoke("desktop.clipboard.writeText", text),
43
+ },
44
+ });
@@ -0,0 +1,4 @@
1
+ import type { ManagedDaemon } from "../daemon.js";
2
+ export declare function refreshDesktopSettingsFromDaemon(daemon: ManagedDaemon, setCloseToTray: (value: boolean) => void): Promise<void>;
3
+ export declare function installDaemonCookie(daemon: ManagedDaemon): Promise<void>;
4
+ //# sourceMappingURL=desktop-settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desktop-settings.d.ts","sourceRoot":"","sources":["../../src/settings/desktop-settings.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,wBAAsB,gCAAgC,CACpD,MAAM,EAAE,aAAa,EACrB,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GACvC,OAAO,CAAC,IAAI,CAAC,CAYf;AAcD,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAaf"}
@@ -0,0 +1,45 @@
1
+ import { settingsSchema } from "@nervekit/shared";
2
+ import { session } from "../electron.js";
3
+ import { desktopLog } from "../logging.js";
4
+ export async function refreshDesktopSettingsFromDaemon(daemon, setCloseToTray) {
5
+ try {
6
+ const settings = await fetchDaemonSettings(daemon);
7
+ setCloseToTray(settings.desktop.closeToTray);
8
+ void desktopLog("info", "settings", "Loaded desktop settings", {
9
+ context: { closeToTray: settings.desktop.closeToTray },
10
+ });
11
+ }
12
+ catch (error) {
13
+ void desktopLog("warn", "settings", "Could not load desktop settings", {
14
+ error,
15
+ });
16
+ }
17
+ }
18
+ async function fetchDaemonSettings(daemon) {
19
+ const headers = {};
20
+ if (daemon.token)
21
+ headers.authorization = `Bearer ${daemon.token}`;
22
+ const response = await fetch(new URL("/api/settings", daemon.url), {
23
+ headers,
24
+ });
25
+ if (!response.ok) {
26
+ throw new Error(`Settings request failed with status ${response.status}.`);
27
+ }
28
+ return settingsSchema.parse(await response.json());
29
+ }
30
+ export async function installDaemonCookie(daemon) {
31
+ if (!daemon.token)
32
+ return;
33
+ const url = new URL(daemon.url);
34
+ await session.defaultSession.cookies.set({
35
+ url: url.origin,
36
+ name: "nerve_token",
37
+ value: daemon.token,
38
+ path: "/",
39
+ httpOnly: true,
40
+ secure: url.protocol === "https:",
41
+ sameSite: "strict",
42
+ expirationDate: Math.floor(Date.now() / 1000) + 31_536_000,
43
+ });
44
+ }
45
+ //# sourceMappingURL=desktop-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desktop-settings.js","sourceRoot":"","sources":["../../src/settings/desktop-settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEjE,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,MAAqB,EACrB,cAAwC;IAExC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACnD,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAC7C,KAAK,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,yBAAyB,EAAE;YAC7D,OAAO,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE;SACvD,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,KAAK,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,iCAAiC,EAAE;YACrE,KAAK;SACN,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,MAAqB;IACtD,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,MAAM,CAAC,KAAK;QAAE,OAAO,CAAC,aAAa,GAAG,UAAU,MAAM,CAAC,KAAK,EAAE,CAAC;IACnE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE;QACjE,OAAO;KACR,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,uCAAuC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,cAAc,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAqB;IAErB,IAAI,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO;IAC1B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC;QACvC,GAAG,EAAE,GAAG,CAAC,MAAM;QACf,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,IAAI,EAAE,GAAG;QACT,QAAQ,EAAE,IAAI;QACd,MAAM,EAAE,GAAG,CAAC,QAAQ,KAAK,QAAQ;QACjC,QAAQ,EAAE,QAAQ;QAClB,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,UAAU;KAC3D,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type ElectronOzonePlatform = "x11" | "wayland" | "auto";
2
+ export declare function parseElectronOzonePlatform(value: string | undefined): ElectronOzonePlatform | undefined;
3
+ //# sourceMappingURL=ozone-platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ozone-platform.d.ts","sourceRoot":"","sources":["../../src/shared/ozone-platform.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;AAE/D,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,qBAAqB,GAAG,SAAS,CAcnC"}
@@ -0,0 +1,16 @@
1
+ // Node-safe helpers shared between the Electron main process and the
2
+ // `bin.ts` launcher. This module must not import Electron so it can run in a
3
+ // plain Node context (for example under `npx @nervekit/desktop`).
4
+ export function parseElectronOzonePlatform(value) {
5
+ const normalized = value?.trim().toLowerCase();
6
+ if (!normalized)
7
+ return undefined;
8
+ if (normalized === "x11" ||
9
+ normalized === "wayland" ||
10
+ normalized === "auto") {
11
+ return normalized;
12
+ }
13
+ console.warn(`Ignoring invalid NERVE_ELECTRON_OZONE_PLATFORM=${JSON.stringify(value)}. Expected x11, wayland, or auto.`);
14
+ return undefined;
15
+ }
16
+ //# sourceMappingURL=ozone-platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ozone-platform.js","sourceRoot":"","sources":["../../src/shared/ozone-platform.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,6EAA6E;AAC7E,kEAAkE;AAIlE,MAAM,UAAU,0BAA0B,CACxC,KAAyB;IAEzB,MAAM,UAAU,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/C,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,IACE,UAAU,KAAK,KAAK;QACpB,UAAU,KAAK,SAAS;QACxB,UAAU,KAAK,MAAM,EACrB,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,CAAC,IAAI,CACV,kDAAkD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,mCAAmC,CAC3G,CAAC;IACF,OAAO,SAAS,CAAC;AACnB,CAAC"}