@noego/wood 0.6.0 → 0.6.1

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.
@@ -0,0 +1,81 @@
1
+ import { Logger } from '@noego/logger';
2
+
3
+ /**
4
+ * Bounded time the last renderers get to acknowledge the shutdown drain
5
+ * (trace transport close + app-registered persistence hooks) before their
6
+ * windows are destroyed.
7
+ */
8
+ declare const RENDERER_SHUTDOWN_DRAIN_TIMEOUT_MS = 1000;
9
+ type ShutdownWindow = Readonly<{
10
+ isDestroyed(): boolean;
11
+ hide(): void;
12
+ destroy(): void;
13
+ }>;
14
+ type ShutdownPreventableEvent = Readonly<{
15
+ preventDefault(): void;
16
+ }>;
17
+ type ShutdownReason = 'last-window-close' | 'quit';
18
+ type ShutdownPhase = 'idle' | 'draining' | 'windows-destroyed' | 'cleaning-backend' | 'complete';
19
+ type ShutdownCoordinatorDependencies = Readonly<{
20
+ /** Live view of the tracked windows; iterated as a snapshot on each use. */
21
+ trackedWindows(): Iterable<readonly [string, ShutdownWindow]>;
22
+ /** Forget every tracked window after destruction. */
23
+ clearTrackedWindows(): void;
24
+ /** Bounded renderer drain (traces + persistence acknowledgements). */
25
+ drainRenderers(): Promise<void>;
26
+ /** Backend runtime/service teardown; runs only after windows are gone. */
27
+ cleanupBackend(): Promise<void>;
28
+ /** Ask Electron to quit; the coordinator calls this exactly once, at the end. */
29
+ requestQuit(): void;
30
+ logger: Pick<Logger, 'debug' | 'info' | 'warn'>;
31
+ }>;
32
+ declare function shouldDeferLastWindowCloseForCleanup(trackedWindowCount: number, cleanupComplete: boolean): boolean;
33
+ /**
34
+ * Owns the Desktop shutdown sequence so windows disappear first and the
35
+ * backend is torn down last:
36
+ *
37
+ * accepted last-window Close or Quit
38
+ * -> hide every tracked window immediately
39
+ * -> bounded renderer drain (trace close + persistence acknowledgements)
40
+ * -> destroy every tracked window
41
+ * -> backend runtime/service cleanup
42
+ * -> app.quit()
43
+ *
44
+ * The sequence runs exactly once. Every Electron quit attempt that arrives
45
+ * while it is in flight (repeated Cmd+Q, the `closed` -> `window-all-closed`
46
+ * cascade caused by our own window destruction, a second Close) is prevented
47
+ * so the process cannot exit before cleanup finishes. Once complete, the final
48
+ * `requestQuit()` is allowed through untouched.
49
+ */
50
+ declare class ShutdownCoordinator {
51
+ private readonly deps;
52
+ private currentPhase;
53
+ private shutdown;
54
+ constructor(deps: ShutdownCoordinatorDependencies);
55
+ get phase(): ShutdownPhase;
56
+ get isActive(): boolean;
57
+ get isComplete(): boolean;
58
+ /** Resolves when the in-flight (or already finished) shutdown sequence settles. */
59
+ whenSettled(): Promise<void>;
60
+ /**
61
+ * `close` handler for a tracked BrowserWindow. Returns true when the close
62
+ * was intercepted (last window, or a shutdown is already running); false
63
+ * means the window may close normally.
64
+ */
65
+ handleTrackedWindowClose(event: ShutdownPreventableEvent, trackedWindowCount: number): boolean;
66
+ /** `before-quit` handler. Prevents every quit until the sequence completes. */
67
+ handleBeforeQuit(event: ShutdownPreventableEvent): void;
68
+ /**
69
+ * `window-all-closed` / last `closed` handler. While a shutdown is in flight
70
+ * the coordinator issues the final quit itself, so the cascade caused by
71
+ * destroying our own windows must not request another one.
72
+ */
73
+ handleAllWindowsClosed(): void;
74
+ private begin;
75
+ private run;
76
+ private hideAllWindows;
77
+ private hideWindow;
78
+ private destroyAllWindows;
79
+ }
80
+
81
+ export { RENDERER_SHUTDOWN_DRAIN_TIMEOUT_MS, ShutdownCoordinator, type ShutdownCoordinatorDependencies, type ShutdownPhase, type ShutdownPreventableEvent, type ShutdownReason, type ShutdownWindow, shouldDeferLastWindowCloseForCleanup };
@@ -0,0 +1,81 @@
1
+ import { Logger } from '@noego/logger';
2
+
3
+ /**
4
+ * Bounded time the last renderers get to acknowledge the shutdown drain
5
+ * (trace transport close + app-registered persistence hooks) before their
6
+ * windows are destroyed.
7
+ */
8
+ declare const RENDERER_SHUTDOWN_DRAIN_TIMEOUT_MS = 1000;
9
+ type ShutdownWindow = Readonly<{
10
+ isDestroyed(): boolean;
11
+ hide(): void;
12
+ destroy(): void;
13
+ }>;
14
+ type ShutdownPreventableEvent = Readonly<{
15
+ preventDefault(): void;
16
+ }>;
17
+ type ShutdownReason = 'last-window-close' | 'quit';
18
+ type ShutdownPhase = 'idle' | 'draining' | 'windows-destroyed' | 'cleaning-backend' | 'complete';
19
+ type ShutdownCoordinatorDependencies = Readonly<{
20
+ /** Live view of the tracked windows; iterated as a snapshot on each use. */
21
+ trackedWindows(): Iterable<readonly [string, ShutdownWindow]>;
22
+ /** Forget every tracked window after destruction. */
23
+ clearTrackedWindows(): void;
24
+ /** Bounded renderer drain (traces + persistence acknowledgements). */
25
+ drainRenderers(): Promise<void>;
26
+ /** Backend runtime/service teardown; runs only after windows are gone. */
27
+ cleanupBackend(): Promise<void>;
28
+ /** Ask Electron to quit; the coordinator calls this exactly once, at the end. */
29
+ requestQuit(): void;
30
+ logger: Pick<Logger, 'debug' | 'info' | 'warn'>;
31
+ }>;
32
+ declare function shouldDeferLastWindowCloseForCleanup(trackedWindowCount: number, cleanupComplete: boolean): boolean;
33
+ /**
34
+ * Owns the Desktop shutdown sequence so windows disappear first and the
35
+ * backend is torn down last:
36
+ *
37
+ * accepted last-window Close or Quit
38
+ * -> hide every tracked window immediately
39
+ * -> bounded renderer drain (trace close + persistence acknowledgements)
40
+ * -> destroy every tracked window
41
+ * -> backend runtime/service cleanup
42
+ * -> app.quit()
43
+ *
44
+ * The sequence runs exactly once. Every Electron quit attempt that arrives
45
+ * while it is in flight (repeated Cmd+Q, the `closed` -> `window-all-closed`
46
+ * cascade caused by our own window destruction, a second Close) is prevented
47
+ * so the process cannot exit before cleanup finishes. Once complete, the final
48
+ * `requestQuit()` is allowed through untouched.
49
+ */
50
+ declare class ShutdownCoordinator {
51
+ private readonly deps;
52
+ private currentPhase;
53
+ private shutdown;
54
+ constructor(deps: ShutdownCoordinatorDependencies);
55
+ get phase(): ShutdownPhase;
56
+ get isActive(): boolean;
57
+ get isComplete(): boolean;
58
+ /** Resolves when the in-flight (or already finished) shutdown sequence settles. */
59
+ whenSettled(): Promise<void>;
60
+ /**
61
+ * `close` handler for a tracked BrowserWindow. Returns true when the close
62
+ * was intercepted (last window, or a shutdown is already running); false
63
+ * means the window may close normally.
64
+ */
65
+ handleTrackedWindowClose(event: ShutdownPreventableEvent, trackedWindowCount: number): boolean;
66
+ /** `before-quit` handler. Prevents every quit until the sequence completes. */
67
+ handleBeforeQuit(event: ShutdownPreventableEvent): void;
68
+ /**
69
+ * `window-all-closed` / last `closed` handler. While a shutdown is in flight
70
+ * the coordinator issues the final quit itself, so the cascade caused by
71
+ * destroying our own windows must not request another one.
72
+ */
73
+ handleAllWindowsClosed(): void;
74
+ private begin;
75
+ private run;
76
+ private hideAllWindows;
77
+ private hideWindow;
78
+ private destroyAllWindows;
79
+ }
80
+
81
+ export { RENDERER_SHUTDOWN_DRAIN_TIMEOUT_MS, ShutdownCoordinator, type ShutdownCoordinatorDependencies, type ShutdownPhase, type ShutdownPreventableEvent, type ShutdownReason, type ShutdownWindow, shouldDeferLastWindowCloseForCleanup };
@@ -0,0 +1,127 @@
1
+ const RENDERER_SHUTDOWN_DRAIN_TIMEOUT_MS = 1e3;
2
+ function shouldDeferLastWindowCloseForCleanup(trackedWindowCount, cleanupComplete) {
3
+ return trackedWindowCount === 1 && !cleanupComplete;
4
+ }
5
+ class ShutdownCoordinator {
6
+ constructor(deps) {
7
+ this.deps = deps;
8
+ this.currentPhase = "idle";
9
+ this.shutdown = null;
10
+ }
11
+ get phase() {
12
+ return this.currentPhase;
13
+ }
14
+ get isActive() {
15
+ return this.shutdown !== null;
16
+ }
17
+ get isComplete() {
18
+ return this.currentPhase === "complete";
19
+ }
20
+ /** Resolves when the in-flight (or already finished) shutdown sequence settles. */
21
+ whenSettled() {
22
+ return this.shutdown ?? Promise.resolve();
23
+ }
24
+ /**
25
+ * `close` handler for a tracked BrowserWindow. Returns true when the close
26
+ * was intercepted (last window, or a shutdown is already running); false
27
+ * means the window may close normally.
28
+ */
29
+ handleTrackedWindowClose(event, trackedWindowCount) {
30
+ if (this.isComplete) {
31
+ return false;
32
+ }
33
+ if (this.shutdown) {
34
+ event.preventDefault();
35
+ return true;
36
+ }
37
+ if (!shouldDeferLastWindowCloseForCleanup(trackedWindowCount, false)) {
38
+ return false;
39
+ }
40
+ event.preventDefault();
41
+ this.begin("last-window-close");
42
+ return true;
43
+ }
44
+ /** `before-quit` handler. Prevents every quit until the sequence completes. */
45
+ handleBeforeQuit(event) {
46
+ if (this.isComplete) {
47
+ return;
48
+ }
49
+ event.preventDefault();
50
+ if (this.shutdown) {
51
+ return;
52
+ }
53
+ this.begin("quit");
54
+ }
55
+ /**
56
+ * `window-all-closed` / last `closed` handler. While a shutdown is in flight
57
+ * the coordinator issues the final quit itself, so the cascade caused by
58
+ * destroying our own windows must not request another one.
59
+ */
60
+ handleAllWindowsClosed() {
61
+ if (this.shutdown) {
62
+ return;
63
+ }
64
+ this.deps.requestQuit();
65
+ }
66
+ begin(reason) {
67
+ this.deps.logger.info("shutdown started", { reason });
68
+ this.shutdown = this.run();
69
+ }
70
+ async run() {
71
+ this.hideAllWindows();
72
+ this.currentPhase = "draining";
73
+ try {
74
+ await this.deps.drainRenderers();
75
+ } catch (error) {
76
+ this.deps.logger.warn("renderer shutdown drain failed", { error: toErrorMessage(error) });
77
+ }
78
+ this.destroyAllWindows();
79
+ this.currentPhase = "windows-destroyed";
80
+ this.currentPhase = "cleaning-backend";
81
+ try {
82
+ await this.deps.cleanupBackend();
83
+ } catch (error) {
84
+ this.deps.logger.warn("backend shutdown cleanup failed", { error: toErrorMessage(error) });
85
+ }
86
+ this.currentPhase = "complete";
87
+ this.deps.logger.info("shutdown complete");
88
+ this.deps.requestQuit();
89
+ }
90
+ hideAllWindows() {
91
+ for (const [id, window] of [...this.deps.trackedWindows()]) {
92
+ this.hideWindow(id, window);
93
+ }
94
+ }
95
+ hideWindow(id, window) {
96
+ try {
97
+ if (!window.isDestroyed()) {
98
+ window.hide();
99
+ this.deps.logger.debug("hid window for shutdown", { windowId: id });
100
+ }
101
+ } catch (error) {
102
+ this.deps.logger.warn("hiding window for shutdown failed", { windowId: id, error: toErrorMessage(error) });
103
+ }
104
+ }
105
+ destroyAllWindows() {
106
+ for (const [id, window] of [...this.deps.trackedWindows()]) {
107
+ try {
108
+ if (!window.isDestroyed()) {
109
+ window.destroy();
110
+ this.deps.logger.debug("destroyed window on shutdown", { windowId: id });
111
+ }
112
+ } catch (error) {
113
+ this.deps.logger.warn("destroying window on shutdown failed", { windowId: id, error: toErrorMessage(error) });
114
+ }
115
+ }
116
+ this.deps.clearTrackedWindows();
117
+ }
118
+ }
119
+ function toErrorMessage(error) {
120
+ return error instanceof Error ? error.message : String(error);
121
+ }
122
+ export {
123
+ RENDERER_SHUTDOWN_DRAIN_TIMEOUT_MS,
124
+ ShutdownCoordinator,
125
+ shouldDeferLastWindowCloseForCleanup
126
+ };
127
+ //# sourceMappingURL=shutdown_coordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/main/shutdown_coordinator.ts"],"sourcesContent":["import type { Logger } from '@noego/logger';\n\n/**\n * Bounded time the last renderers get to acknowledge the shutdown drain\n * (trace transport close + app-registered persistence hooks) before their\n * windows are destroyed.\n */\nexport const RENDERER_SHUTDOWN_DRAIN_TIMEOUT_MS = 1_000;\n\nexport type ShutdownWindow = Readonly<{\n isDestroyed(): boolean;\n hide(): void;\n destroy(): void;\n}>;\n\nexport type ShutdownPreventableEvent = Readonly<{\n preventDefault(): void;\n}>;\n\nexport type ShutdownReason = 'last-window-close' | 'quit';\n\nexport type ShutdownPhase =\n | 'idle'\n | 'draining'\n | 'windows-destroyed'\n | 'cleaning-backend'\n | 'complete';\n\nexport type ShutdownCoordinatorDependencies = Readonly<{\n /** Live view of the tracked windows; iterated as a snapshot on each use. */\n trackedWindows(): Iterable<readonly [string, ShutdownWindow]>;\n /** Forget every tracked window after destruction. */\n clearTrackedWindows(): void;\n /** Bounded renderer drain (traces + persistence acknowledgements). */\n drainRenderers(): Promise<void>;\n /** Backend runtime/service teardown; runs only after windows are gone. */\n cleanupBackend(): Promise<void>;\n /** Ask Electron to quit; the coordinator calls this exactly once, at the end. */\n requestQuit(): void;\n logger: Pick<Logger, 'debug' | 'info' | 'warn'>;\n}>;\n\nexport function shouldDeferLastWindowCloseForCleanup(\n trackedWindowCount: number,\n cleanupComplete: boolean,\n): boolean {\n return trackedWindowCount === 1 && !cleanupComplete;\n}\n\n/**\n * Owns the Desktop shutdown sequence so windows disappear first and the\n * backend is torn down last:\n *\n * accepted last-window Close or Quit\n * -> hide every tracked window immediately\n * -> bounded renderer drain (trace close + persistence acknowledgements)\n * -> destroy every tracked window\n * -> backend runtime/service cleanup\n * -> app.quit()\n *\n * The sequence runs exactly once. Every Electron quit attempt that arrives\n * while it is in flight (repeated Cmd+Q, the `closed` -> `window-all-closed`\n * cascade caused by our own window destruction, a second Close) is prevented\n * so the process cannot exit before cleanup finishes. Once complete, the final\n * `requestQuit()` is allowed through untouched.\n */\nexport class ShutdownCoordinator {\n private currentPhase: ShutdownPhase = 'idle';\n private shutdown: Promise<void> | null = null;\n\n constructor(private readonly deps: ShutdownCoordinatorDependencies) {}\n\n get phase(): ShutdownPhase {\n return this.currentPhase;\n }\n\n get isActive(): boolean {\n return this.shutdown !== null;\n }\n\n get isComplete(): boolean {\n return this.currentPhase === 'complete';\n }\n\n /** Resolves when the in-flight (or already finished) shutdown sequence settles. */\n whenSettled(): Promise<void> {\n return this.shutdown ?? Promise.resolve();\n }\n\n /**\n * `close` handler for a tracked BrowserWindow. Returns true when the close\n * was intercepted (last window, or a shutdown is already running); false\n * means the window may close normally.\n */\n handleTrackedWindowClose(\n event: ShutdownPreventableEvent,\n trackedWindowCount: number,\n ): boolean {\n if (this.isComplete) {\n return false;\n }\n if (this.shutdown) {\n // Shutdown owns window destruction; do not let a competing close race it.\n event.preventDefault();\n return true;\n }\n if (!shouldDeferLastWindowCloseForCleanup(trackedWindowCount, false)) {\n return false;\n }\n event.preventDefault();\n // begin() hides every tracked window synchronously, including this one.\n this.begin('last-window-close');\n return true;\n }\n\n /** `before-quit` handler. Prevents every quit until the sequence completes. */\n handleBeforeQuit(event: ShutdownPreventableEvent): void {\n if (this.isComplete) {\n return;\n }\n event.preventDefault();\n if (this.shutdown) {\n return;\n }\n this.begin('quit');\n }\n\n /**\n * `window-all-closed` / last `closed` handler. While a shutdown is in flight\n * the coordinator issues the final quit itself, so the cascade caused by\n * destroying our own windows must not request another one.\n */\n handleAllWindowsClosed(): void {\n if (this.shutdown) {\n return;\n }\n this.deps.requestQuit();\n }\n\n private begin(reason: ShutdownReason): void {\n this.deps.logger.info('shutdown started', { reason });\n this.shutdown = this.run();\n }\n\n private async run(): Promise<void> {\n this.hideAllWindows();\n\n this.currentPhase = 'draining';\n try {\n await this.deps.drainRenderers();\n } catch (error) {\n this.deps.logger.warn('renderer shutdown drain failed', { error: toErrorMessage(error) });\n }\n\n this.destroyAllWindows();\n this.currentPhase = 'windows-destroyed';\n\n this.currentPhase = 'cleaning-backend';\n try {\n await this.deps.cleanupBackend();\n } catch (error) {\n this.deps.logger.warn('backend shutdown cleanup failed', { error: toErrorMessage(error) });\n }\n\n this.currentPhase = 'complete';\n this.deps.logger.info('shutdown complete');\n this.deps.requestQuit();\n }\n\n private hideAllWindows(): void {\n for (const [id, window] of [...this.deps.trackedWindows()]) {\n this.hideWindow(id, window);\n }\n }\n\n private hideWindow(id: string, window: ShutdownWindow): void {\n try {\n if (!window.isDestroyed()) {\n window.hide();\n this.deps.logger.debug('hid window for shutdown', { windowId: id });\n }\n } catch (error) {\n this.deps.logger.warn('hiding window for shutdown failed', { windowId: id, error: toErrorMessage(error) });\n }\n }\n\n private destroyAllWindows(): void {\n for (const [id, window] of [...this.deps.trackedWindows()]) {\n try {\n if (!window.isDestroyed()) {\n window.destroy();\n this.deps.logger.debug('destroyed window on shutdown', { windowId: id });\n }\n } catch (error) {\n this.deps.logger.warn('destroying window on shutdown failed', { windowId: id, error: toErrorMessage(error) });\n }\n }\n this.deps.clearTrackedWindows();\n }\n}\n\nfunction toErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noego/wood",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",