@omega.js/desktop 0.52.0 → 0.53.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.
- package/README.md +17 -12
- package/dist/assets/css/core/_initialize.scss +1 -1
- package/dist/assets/js/core/app-shell.js +14 -15
- package/dist/assets/themes/_template/_theme.js +6 -6
- package/dist/assets/themes/base/_includes/global/sections/account.html +4 -4
- package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +5 -5
- package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +3 -3
- package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/tags/tag.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/payment/confirmation.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.js +2 -3
- package/dist/assets/themes/base/_sections/verts/unit/section.html +1 -1
- package/dist/assets/themes/base/_sections/verts/unit/section.js +3 -4
- package/dist/assets/themes/base/_theme.js +4 -3
- package/dist/assets/themes/bootstrap/_theme.js +2 -2
- package/dist/assets/themes/bootstrap/overrides/_links.scss +1 -1
- package/dist/assets/themes/classy/_theme.js +8 -6
- package/dist/assets/themes/classy/css/marketing/_sections.scss +1 -2
- package/dist/assets/themes/classy/js/hero-demo-form.js +3 -2
- package/dist/assets/themes/neobrutalism/_theme.js +5 -5
- package/dist/assets/themes/neobrutalism/js/pages/test/libraries/layers/index.js +1 -1
- package/dist/assets/themes/newsflash/_theme.js +6 -6
- package/dist/assets/themes/newsflash/js/pages/test/libraries/layers/index.js +1 -1
- package/dist/build.js +87 -111
- package/dist/cli.js +1 -1
- package/dist/commands/build.js +2 -2
- package/dist/commands/cdp/capture.js +2 -2
- package/dist/commands/cdp/quit.js +2 -2
- package/dist/commands/cdp/relaunch.js +2 -2
- package/dist/commands/cdp/theme.js +1 -1
- package/dist/commands/clean.js +2 -2
- package/dist/commands/deploy.js +4 -4
- package/dist/commands/finalize-release.js +4 -4
- package/dist/commands/install.js +3 -3
- package/dist/commands/launch.js +2 -2
- package/dist/commands/lib/deploy-precheck.js +3 -3
- package/dist/commands/lib/ensure-target.js +6 -6
- package/dist/commands/package.js +2 -2
- package/dist/commands/publish.js +2 -2
- package/dist/commands/release.js +3 -3
- package/dist/commands/runner.js +11 -11
- package/dist/commands/sign-windows.js +5 -5
- package/dist/commands/test.js +4 -4
- package/dist/commands/update.js +2 -2
- package/dist/commands/validate-certs.js +4 -4
- package/dist/commands/version.js +3 -3
- package/dist/defaults/AGENTS.md +17 -8
- package/dist/defaults/config/omega.json5 +7 -7
- package/dist/defaults/hooks/build/post.js +1 -1
- package/dist/defaults/hooks/build/pre.js +1 -1
- package/dist/defaults/hooks/deploy/pre.js +1 -1
- package/dist/defaults/hooks/release/post.js +1 -1
- package/dist/defaults/hooks/release/pre.js +1 -1
- package/dist/defaults/src/assets/js/components/about/index.js +3 -5
- package/dist/defaults/src/assets/js/components/main/index.js +3 -5
- package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
- package/dist/defaults/src/integrations/context-menu/index.js +2 -2
- package/dist/defaults/src/integrations/menu/index.js +3 -3
- package/dist/defaults/src/integrations/tray/index.js +3 -3
- package/dist/defaults/src/main.js +3 -5
- package/dist/defaults/src/preload.js +3 -5
- package/dist/defaults/test/README.md +2 -2
- package/dist/gulp/main.js +9 -10
- package/dist/gulp/tasks/audit.js +7 -7
- package/dist/gulp/tasks/build-config.js +8 -8
- package/dist/gulp/tasks/bundle.js +16 -16
- package/dist/gulp/tasks/defaults.js +3 -3
- package/dist/gulp/tasks/distribute.js +2 -2
- package/dist/gulp/tasks/html.js +9 -9
- package/dist/gulp/tasks/package-quick.js +3 -3
- package/dist/gulp/tasks/package.js +3 -3
- package/dist/gulp/tasks/release.js +3 -3
- package/dist/gulp/tasks/sass.js +6 -6
- package/dist/gulp/tasks/serve.js +4 -4
- package/dist/hooks/notarize-artifacts.js +1 -1
- package/dist/hooks/notarize.js +1 -1
- package/dist/index.js +5 -8
- package/dist/lib/_environment-mixin.js +50 -0
- package/dist/lib/_lifecycle-mixin.js +45 -0
- package/dist/lib/analytics.js +33 -35
- package/dist/lib/app-state.js +14 -14
- package/dist/lib/auth-flow.js +18 -18
- package/dist/lib/auth-persistence.js +12 -12
- package/dist/lib/auth.js +421 -0
- package/dist/lib/auto-updater.js +49 -49
- package/dist/lib/context-menu.js +13 -13
- package/dist/lib/context.js +19 -19
- package/dist/lib/deep-link.js +34 -34
- package/dist/lib/fontawesome.js +5 -5
- package/dist/lib/ipc.js +4 -4
- package/dist/lib/menu.js +25 -25
- package/dist/lib/protocol.js +5 -5
- package/dist/lib/remote-config.js +22 -22
- package/dist/lib/remote-scripts.js +21 -21
- package/dist/lib/restart-manager/index.js +28 -28
- package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
- package/dist/lib/sign-helpers/sign-events.js +1 -1
- package/dist/lib/startup.js +18 -13
- package/dist/lib/storage.js +10 -10
- package/dist/lib/templating.js +16 -16
- package/dist/lib/theme.js +10 -10
- package/dist/lib/tray.js +27 -27
- package/dist/lib/usage.js +11 -11
- package/dist/lib/window-manager.js +26 -26
- package/dist/main.js +398 -483
- package/dist/preload.js +236 -176
- package/dist/renderer.js +417 -391
- package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
- package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
- package/dist/test/fixtures/consumer-app/src/main.js +5 -7
- package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
- package/dist/test/harness/boot-entry.js +22 -20
- package/dist/test/harness/main-entry.js +31 -30
- package/dist/test/harness/renderer-entry.js +5 -5
- package/dist/test/harness/renderer-preload.js +137 -141
- package/dist/test/index.js +10 -10
- package/dist/test/runner.js +2 -2
- package/dist/test/runners/boot.js +7 -6
- package/dist/test/runners/electron.js +3 -2
- package/dist/test/runners/render-event.js +2 -2
- package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
- package/dist/test/suites/boot/restart-manager.test.js +2 -2
- package/dist/test/suites/boot/storage-bundled.test.js +5 -5
- package/dist/test/suites/boot/theme.test.js +13 -13
- package/dist/test/suites/build/audit.test.js +1 -1
- package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
- package/dist/test/suites/build/boot-fixture.test.js +2 -2
- package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
- package/dist/test/suites/build/brand-scss.test.js +1 -1
- package/dist/test/suites/build/build-json-bake.test.js +1 -1
- package/dist/test/suites/build/cli.test.js +2 -2
- package/dist/test/suites/build/config-schema.test.js +5 -5
- package/dist/test/suites/build/defaults-scaffold.test.js +2 -2
- package/dist/test/suites/build/deploy-hook.test.js +3 -3
- package/dist/test/suites/build/ensure-target.test.js +2 -2
- package/dist/test/suites/build/env-delivery.test.js +2 -2
- package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
- package/dist/test/suites/build/exports.test.js +9 -8
- package/dist/test/suites/build/get-config.test.js +4 -4
- package/dist/test/suites/build/manifest-deps.test.js +1 -1
- package/dist/test/suites/build/merge-line-files.test.js +1 -1
- package/dist/test/suites/build/omega-shell.test.js +34 -2
- package/dist/test/suites/build/omega.test.js +350 -0
- package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
- package/dist/test/suites/build/runner.test.js +2 -2
- package/dist/test/suites/build/sentry.test.js +2 -2
- package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
- package/dist/test/suites/build/templating.test.js +3 -3
- package/dist/test/suites/build/test-stealth.test.js +7 -9
- package/dist/test/suites/build/url-helpers.test.js +55 -56
- package/dist/test/suites/build/validate-config.test.js +2 -2
- package/dist/test/suites/build/wave5-pins.test.js +2 -2
- package/dist/test/suites/main/analytics.test.js +59 -59
- package/dist/test/suites/main/app-state.test.js +66 -66
- package/dist/test/suites/main/auth-flow.test.js +41 -41
- package/dist/test/suites/main/auth-persistence.test.js +54 -43
- package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
- package/dist/test/suites/main/auth.test.js +336 -0
- package/dist/test/suites/main/auto-updater.test.js +134 -134
- package/dist/test/suites/main/boot-sequence.test.js +37 -49
- package/dist/test/suites/main/context-menu.test.js +51 -50
- package/dist/test/suites/main/context.test.js +25 -25
- package/dist/test/suites/main/deep-link.test.js +74 -74
- package/dist/test/suites/main/fontawesome.test.js +27 -27
- package/dist/test/suites/main/ipc.test.js +35 -35
- package/dist/test/suites/main/menu.test.js +101 -100
- package/dist/test/suites/main/protocol.test.js +19 -19
- package/dist/test/suites/main/remote-config.test.js +63 -63
- package/dist/test/suites/main/remote-scripts.test.js +103 -103
- package/dist/test/suites/main/request.test.js +71 -0
- package/dist/test/suites/main/restart-manager.test.js +33 -33
- package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
- package/dist/test/suites/main/startup.test.js +26 -26
- package/dist/test/suites/main/stealth-window.test.js +1 -1
- package/dist/test/suites/main/storage.test.js +25 -25
- package/dist/test/suites/main/theme.test.js +34 -34
- package/dist/test/suites/main/tray.test.js +79 -79
- package/dist/test/suites/main/url-helpers.test.js +133 -133
- package/dist/test/suites/main/usage.test.js +25 -25
- package/dist/test/suites/main/window-bounds.test.js +27 -27
- package/dist/test/suites/main/window-manager.test.js +44 -44
- package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
- package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
- package/dist/test/suites/renderer/round-trip.test.js +3 -3
- package/dist/test/suites/renderer/tooltips.test.js +15 -15
- package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +27 -7
- package/dist/test/utils/extended-mode-warning.js +1 -1
- package/dist/utils/boot-harness.js +56 -0
- package/dist/utils/mode-helpers.js +2 -15
- package/dist/utils/ship-keys.js +3 -3
- package/dist/utils/signing-status.js +51 -0
- package/dist/utils/test-events.js +7 -0
- package/dist/utils/test-stealth.js +6 -6
- package/dist/utils/url-helpers.js +52 -42
- package/dist/utils/user-agent.js +44 -0
- package/dist/vendor/account/engine.js +3 -3
- package/dist/vendor/account/index.js +14 -45
- package/dist/vendor/account/resolve-account.js +44 -0
- package/dist/vendor/account/schema.js +1 -1
- package/dist/vendor/account/user.js +99 -0
- package/dist/vendor/config/client-config.js +1 -1
- package/dist/vendor/config/environment.js +11 -30
- package/dist/vendor/config/index.js +8 -11
- package/dist/vendor/config/load.js +1 -2
- package/dist/vendor/config/platforms.js +1 -1
- package/dist/vendor/config/retired-keys.js +2 -2
- package/dist/vendor/config/schema.js +5 -8
- package/dist/vendor/config/site-global.js +2 -3
- package/dist/vendor/config/validate.js +1 -2
- package/dist/vendor/config/winback.js +1 -1
- package/dist/vendor/devkit/actions-secrets.js +1 -1
- package/dist/vendor/devkit/attach-log-file.js +1 -1
- package/dist/vendor/devkit/build-json.js +1 -1
- package/dist/vendor/devkit/cli-router.js +3 -4
- package/dist/vendor/devkit/defaults-engine.js +9 -11
- package/dist/vendor/devkit/local.js +2 -0
- package/dist/vendor/devkit/merge-line-files.js +2 -3
- package/dist/vendor/devkit/test/runner-core.js +6 -6
- package/dist/vendor/monitoring/env.js +2 -2
- package/dist/vendor/monitoring/index.js +1 -1
- package/dist/vendor/monitoring/main.js +1 -1
- package/dist/vendor/monitoring/preload.js +1 -1
- package/dist/vendor/monitoring/renderer.js +1 -1
- package/docs/analytics.md +8 -8
- package/docs/app-state.md +19 -19
- package/docs/audit.md +4 -4
- package/docs/{client-bridge.md → auth.md} +88 -73
- package/docs/auto-updater.md +8 -8
- package/docs/boot-sequence.md +11 -6
- package/docs/build-system.md +1 -1
- package/docs/cdp-debugging.md +1 -1
- package/docs/common-mistakes.md +7 -7
- package/docs/config-schema.md +1 -1
- package/docs/context-menu.md +13 -13
- package/docs/context.md +11 -11
- package/docs/css.md +3 -9
- package/docs/deep-link.md +25 -25
- package/docs/environment-detection.md +16 -16
- package/docs/fontawesome.md +7 -5
- package/docs/hooks.md +8 -8
- package/docs/index.md +38 -27
- package/docs/ipc.md +10 -10
- package/docs/lib-modules.md +9 -9
- package/docs/logging.md +12 -14
- package/docs/menu.md +18 -18
- package/docs/remote-config.md +9 -9
- package/docs/remote-scripts.md +12 -12
- package/docs/restart-manager.md +8 -8
- package/docs/sentry.md +4 -4
- package/docs/shared/analytics.md +1 -1
- package/docs/shared/breaking-changes.md +79 -13
- package/docs/shared/config.md +17 -21
- package/docs/shared/logging.md +1 -1
- package/docs/shared/monitoring.md +5 -5
- package/docs/shared/testing.md +2 -2
- package/docs/shared/theming.md +1 -1
- package/docs/shared/translation.md +19 -10
- package/docs/startup.md +16 -16
- package/docs/storage.md +11 -11
- package/docs/templating.md +3 -3
- package/docs/test-boot-layer.md +12 -12
- package/docs/test-framework.md +17 -17
- package/docs/themes.md +7 -7
- package/docs/tooltips.md +2 -2
- package/docs/tray.md +31 -31
- package/docs/usage.md +7 -7
- package/docs/verts.md +1 -1
- package/docs/windows.md +22 -22
- package/package.json +3 -4
- package/dist/lib/client-bridge.js +0 -374
- package/dist/lib/logger.js +0 -4
- package/dist/test/suites/build/manager.test.js +0 -213
- package/dist/test/suites/main/client-bridge.test.js +0 -262
package/docs/windows.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Windows
|
|
2
2
|
|
|
3
|
-
**Lazy named-window registry.** @omega.js/desktop does NOT auto-create any window. Your `main.js` calls `
|
|
3
|
+
**Lazy named-window registry.** @omega.js/desktop does NOT auto-create any window. Your `main.js` calls `omega.windows.create('main', { show: !startup.isLaunchHidden() })` from inside `omega.initialize().then(() => { ... })`. Always create `main`: its presence in the registry is what lets @omega.js/desktop's `app.on('activate')` (macOS dock click) and `app.on('second-instance')` (win/linux re-launch) handlers surface UI when the user double-clicks the running app. In hidden launches, pass `show: false` to keep the window invisible until something explicitly calls `windows.show('main')`. Use the registry for the common case (named, persistent, integrated windows). For one-off windows (a toast, a print preview), use `new BrowserWindow()` directly, `window-manager` doesn't get in the way.
|
|
4
4
|
|
|
5
5
|
## Re-surface on user re-launch
|
|
6
6
|
|
|
@@ -14,20 +14,20 @@ Both handlers are no-ops if `main` isn't in the registry. So consumers who genui
|
|
|
14
14
|
## API
|
|
15
15
|
|
|
16
16
|
```js
|
|
17
|
-
await
|
|
18
|
-
await
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
await omega.windows.create('main', overrides?) // canonical entry point
|
|
18
|
+
await omega.windows.createNamed('main', mgr, opts?) // identical; .create() is sugar
|
|
19
|
+
omega.windows.get('main') // BrowserWindow | null
|
|
20
|
+
omega.windows.show('main') // show + focus + auto app.dock.show()
|
|
21
|
+
omega.windows.hide('main')
|
|
22
|
+
omega.windows.close('main') // force-close (bypasses hideOnClose)
|
|
23
|
+
omega.windows.list() // string[] of currently-open names
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
`create()` is single-instance: a second call with the same name returns the existing window and focuses it (no double-create).
|
|
27
27
|
|
|
28
28
|
## Defaults
|
|
29
29
|
|
|
30
|
-
No JSON config required. @omega.js/desktop bakes in sensible defaults so `
|
|
30
|
+
No JSON config required. @omega.js/desktop bakes in sensible defaults so `omega.windows.create('main')` "just works":
|
|
31
31
|
|
|
32
32
|
| Window | Defaults |
|
|
33
33
|
|---|---|
|
|
@@ -37,8 +37,8 @@ No JSON config required. @omega.js/desktop bakes in sensible defaults so `manage
|
|
|
37
37
|
Override at the call site:
|
|
38
38
|
|
|
39
39
|
```js
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
omega.windows.create('main', { width: 1280, height: 800 });
|
|
41
|
+
omega.windows.create('settings', { width: 600, height: 480 });
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
## Config (optional)
|
|
@@ -60,7 +60,7 @@ Per-window keys:
|
|
|
60
60
|
| `view` | `main` | `<name>` | Folder under `src/views/`. Loads `dist/views/<view>/index.html`. |
|
|
61
61
|
| `width` / `height` | 1024 / 720 | 800 / 600 | Initial size (overridden by saved bounds if `persistBounds: true`). |
|
|
62
62
|
| `minWidth` / `minHeight` | 400 / 300 | 400 / 300 | |
|
|
63
|
-
| `show` | `true` | `true` | Auto-show on `ready-to-show`. `false` keeps the window hidden until `
|
|
63
|
+
| `show` | `true` | `true` | Auto-show on `ready-to-show`. `false` keeps the window hidden until `omega.windows.show()`. |
|
|
64
64
|
| `hideOnClose` | `true` | `false` | Discord-style: X click hides instead of closes. See "Hide-on-close" below. |
|
|
65
65
|
| `title` | `app.productName` | `app.productName` | Window title. |
|
|
66
66
|
| `backgroundColor` | `#ffffff` | `#ffffff` | Background color before the page loads. |
|
|
@@ -96,15 +96,15 @@ The `main` window's X button **hides instead of closes** by default. Real quit o
|
|
|
96
96
|
- Menu Quit (`main/quit` on mac, `file/quit` on win/linux)
|
|
97
97
|
- Tray Quit (`quit` item)
|
|
98
98
|
- Auto-updater install (`autoUpdater.installNow()`)
|
|
99
|
-
- Programmatic `
|
|
99
|
+
- Programmatic `omega.quit({ force: true })`
|
|
100
100
|
|
|
101
101
|
The window-manager close handler checks three flags before deciding to swallow vs let through:
|
|
102
102
|
|
|
103
103
|
| Flag | Set by | Means |
|
|
104
104
|
|---|---|---|
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `win._emForceClose` | `
|
|
105
|
+
| `omega._allowQuit` | `omega.quit({ force: true })`, `autoUpdater.installNow()` | Programmatic force: let the close go through. |
|
|
106
|
+
| `omega._isQuitting` | `app.on('before-quit')` (every quit path Electron knows about) | App is quitting: let close events flow naturally. |
|
|
107
|
+
| `win._emForceClose` | `omega.windows.close(name)` | Per-window override. |
|
|
108
108
|
|
|
109
109
|
Other named windows default to `hideOnClose: false` (X actually closes). Override per window via config or call-site overrides.
|
|
110
110
|
|
|
@@ -121,27 +121,27 @@ Every named window's position and size persist to storage on resize / move / max
|
|
|
121
121
|
|
|
122
122
|
## macOS dock auto-show
|
|
123
123
|
|
|
124
|
-
When `LSUIElement: true` is baked at build time (`startup.mode: 'hidden'`), the app launches with **no dock icon, no Cmd+Tab, no taskbar**. The first time `
|
|
124
|
+
When `LSUIElement: true` is baked at build time (`startup.mode: 'hidden'`), the app launches with **no dock icon, no Cmd+Tab, no taskbar**. The first time `omega.windows.create()` or `omega.windows.show()` runs, @omega.js/desktop calls `app.dock.show()` automatically: the dock icon appears alongside the window.
|
|
125
125
|
|
|
126
|
-
**And the inverse**: for `startup.mode: 'hidden'` apps, when the LAST visible named window hides (hide-on-close X, `windows.hide()`, any consumer `win.hide()`), @omega.js/desktop calls `app.dock.hide()` again
|
|
126
|
+
**And the inverse**: for `startup.mode: 'hidden'` apps, when the LAST visible named window hides (hide-on-close X, `windows.hide()`, any consumer `win.hide()`), @omega.js/desktop calls `app.dock.hide()` again: the app returns to its fully-invisible posture, dock and UI appearing and vanishing together. Normal-mode apps keep their dock icon for life; quit paths are untouched (`omega._isQuitting` guard).
|
|
127
127
|
|
|
128
128
|
This means agent / menubar apps can stay completely invisible until the user explicitly asks for UI:
|
|
129
129
|
|
|
130
130
|
```js
|
|
131
|
-
|
|
131
|
+
omega.initialize().then(() => {
|
|
132
132
|
// Don't call windows.create() here — app stays invisible.
|
|
133
133
|
// Surface UI later when something warrants it:
|
|
134
|
-
|
|
134
|
+
omega.tray.update('open', { click: () => omega.windows.create('main') });
|
|
135
135
|
});
|
|
136
136
|
```
|
|
137
137
|
|
|
138
138
|
## Auto-attach context-menu
|
|
139
139
|
|
|
140
|
-
Every window created via `
|
|
140
|
+
Every window created via `omega.windows.create()` is automatically wired up with the consumer's `src/integrations/context-menu/index.js` (see [context-menu.md](context-menu.md)). Idempotent per webContents (uses a WeakSet). For windows you create directly with `new BrowserWindow()`, call `omega.contextMenu.attach(win.webContents)` manually.
|
|
141
141
|
|
|
142
142
|
## Testing mode: stealth surfacing
|
|
143
143
|
|
|
144
|
-
When `
|
|
144
|
+
When `omega.isTesting()` (i.e. under `npx omega test`), every surfacing path in this lib (`ready-to-show`, `windows.show()`, the create-dedup focus) goes **stealth** instead of `win.show()`: `_surface()` applies the shared recipe from `src/utils/stealth-window.js` and surfaces via `showInactive()`, with no `win.focus()`/dock surfacing. **The full stealth story lives in [test-framework.md](test-framework.md) (SSOT)**: the recipe and why it's not `hide()`/`minimize()`, the raw-window `browser-window-created` hook, `webContents.focus()` suppression, macOS app-level activation suppression, and the **`OMEGA_TEST_SHOW=1`** opt-out. Covered by `suites/main/stealth-window.test.js`.
|
|
145
145
|
|
|
146
146
|
## Platform behavior
|
|
147
147
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omega.js/desktop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.0",
|
|
4
4
|
"description": "OMEGA desktop framework — build, test, and package Electron apps for macOS, Windows, and Linux",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"./lib/context-menu": "./dist/lib/context-menu.js",
|
|
24
24
|
"./lib/deep-link": "./dist/lib/deep-link.js",
|
|
25
25
|
"./lib/ipc": "./dist/lib/ipc.js",
|
|
26
|
-
"./lib/logger": "./dist/lib/logger.js",
|
|
27
26
|
"./lib/logger-lite": "./dist/lib/logger-lite.js",
|
|
28
27
|
"./lib/menu": "./dist/lib/menu.js",
|
|
29
28
|
"./lib/protocol": "./dist/lib/protocol.js",
|
|
@@ -33,7 +32,7 @@
|
|
|
33
32
|
"./lib/storage": "./dist/lib/storage.js",
|
|
34
33
|
"./lib/templating": "./dist/lib/templating.js",
|
|
35
34
|
"./lib/tray": "./dist/lib/tray.js",
|
|
36
|
-
"./lib/
|
|
35
|
+
"./lib/auth": "./dist/lib/auth.js",
|
|
37
36
|
"./lib/window-manager": "./dist/lib/window-manager.js",
|
|
38
37
|
"./cli": "./dist/cli-run.js",
|
|
39
38
|
"./ensure-target": "./dist/commands/lib/ensure-target.js",
|
|
@@ -155,7 +154,7 @@
|
|
|
155
154
|
"@fortawesome/fontawesome-free": "^7.3.0",
|
|
156
155
|
"@inquirer/prompts": "^8.5.2",
|
|
157
156
|
"@octokit/rest": "^22.0.1",
|
|
158
|
-
"@omega.js/client": "0.
|
|
157
|
+
"@omega.js/client": "0.53.0",
|
|
159
158
|
"@popperjs/core": "^2.11.8",
|
|
160
159
|
"@sentry/electron": "^7.13.0",
|
|
161
160
|
"chalk": "^5.6.2",
|
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
// Client bridge — main-process Firebase Auth, source of truth for renderers.
|
|
2
|
-
//
|
|
3
|
-
// This is @omega.js/desktop's analogue of BXM's background-service-worker auth role. The pattern:
|
|
4
|
-
//
|
|
5
|
-
// 1. Main runs its own Firebase Auth instance and is the source of truth.
|
|
6
|
-
// 2. When a deep-link auth/token arrives, main calls signInWithCustomToken with that token,
|
|
7
|
-
// then BROADCASTS the token to all renderer windows so their @omega.js/client Firebase
|
|
8
|
-
// instances can sign in with the SAME token.
|
|
9
|
-
// 3. On every renderer load, the renderer asks main "I'm at UID X (or null)" via the
|
|
10
|
-
// desktop:auth:sync-request IPC. Main compares with its own UID and either does nothing,
|
|
11
|
-
// tells the renderer to sign out, or fetches a fresh custom token from /omega
|
|
12
|
-
// and sends it to the renderer.
|
|
13
|
-
// 4. Sign-out: any renderer can request sign-out via desktop:auth:sign-out. Main signs out
|
|
14
|
-
// its own Firebase + broadcasts desktop:auth:sign-out to all renderers.
|
|
15
|
-
//
|
|
16
|
-
// Firebase is BUNDLED by esbuild from @omega.js/desktop's module context (@omega.js/client owns it in @omega.js/desktop's
|
|
17
|
-
// tree). If loading fails, the bridge stays in no-op mode and logs the reason.
|
|
18
|
-
|
|
19
|
-
const LoggerLite = require('./logger-lite.js');
|
|
20
|
-
const authPersistence = require('./auth-persistence.js');
|
|
21
|
-
const { requiredPort } = require('../utils/url-helpers.js');
|
|
22
|
-
|
|
23
|
-
const logger = new LoggerLite('client-bridge');
|
|
24
|
-
|
|
25
|
-
const FIREBASE_APP_NAME = 'omega-auth';
|
|
26
|
-
|
|
27
|
-
const bridge = {
|
|
28
|
-
_initialized: false,
|
|
29
|
-
_manager: null,
|
|
30
|
-
_firebase: null, // firebase/app
|
|
31
|
-
_firebaseAuth: null, // auth instance
|
|
32
|
-
_firebaseModule: null, // firebase/auth namespace (signInWithCustomToken, signOut, ...)
|
|
33
|
-
_stateSubs: new Set(), // main-side subscribers fn(user)
|
|
34
|
-
_ipcRegistered: false,
|
|
35
|
-
_resolvedPlan: null, // renderer-resolved subscription { plan, active, trialing, cancelling }
|
|
36
|
-
_resolvedRoles: null, // renderer-resolved account roles { admin, betaTester, ... }
|
|
37
|
-
|
|
38
|
-
async initialize(manager) {
|
|
39
|
-
if (bridge._initialized) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
bridge._manager = manager;
|
|
44
|
-
|
|
45
|
-
// Try to load firebase. If it's not installed, run in no-op mode.
|
|
46
|
-
const ok = await bridge._tryLoadFirebase();
|
|
47
|
-
if (!ok) {
|
|
48
|
-
logger.warn('firebase not installed — client-bridge running in no-op mode. `npm i firebase` to enable auth.');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
bridge._registerIpc();
|
|
52
|
-
|
|
53
|
-
if (ok) {
|
|
54
|
-
// Boot Firebase Auth. With a persistence strategy active (lib/auth-persistence.js,
|
|
55
|
-
// default safeStorage), the session survives restarts — the restore lands async
|
|
56
|
-
// via onAuthStateChanged shortly after boot.
|
|
57
|
-
try {
|
|
58
|
-
const strategy = await authPersistence.resolve(manager);
|
|
59
|
-
bridge._firebaseAuth = bridge._getFirebaseAuth(strategy);
|
|
60
|
-
// onAuthStateChanged is the source of truth listener.
|
|
61
|
-
bridge._firebaseModule.onAuthStateChanged(bridge._firebaseAuth, (user) => {
|
|
62
|
-
bridge._handleAuthStateChange(user);
|
|
63
|
-
});
|
|
64
|
-
logger.log(`initialize — firebase loaded (persistence: ${strategy ? strategy.name : 'in-memory'})`);
|
|
65
|
-
} catch (e) {
|
|
66
|
-
logger.error('firebase init failed:', e.message);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
bridge._initialized = true;
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
// Load firebase. Returns true on success. BUNDLED by esbuild from @omega.js/desktop's module context
|
|
74
|
-
// (@omega.js/client owns firebase in @omega.js/desktop's tree) — same treatment as json5 in main.js. In the
|
|
75
|
-
// webpack era it was a webpackIgnore'd runtime import(), which resolves relative to the CONSUMER's
|
|
76
|
-
// main.bundle.js: that walk never reaches @omega.js/desktop's node_modules when @omega.js/desktop is symlinked
|
|
77
|
-
// (`mgr install dev`) and depends on npm hoisting when installed — every dev app silently
|
|
78
|
-
// ran the bridge in no-op mode. Interop guards handle both namespace shapes (json5 precedent).
|
|
79
|
-
async _tryLoadFirebase() {
|
|
80
|
-
try {
|
|
81
|
-
const appMod = require('firebase/app');
|
|
82
|
-
const authMod = require('firebase/auth');
|
|
83
|
-
|
|
84
|
-
bridge._firebase = appMod.initializeApp ? appMod : (appMod.default || appMod);
|
|
85
|
-
bridge._firebaseModule = authMod.getAuth ? authMod : (authMod.default || authMod);
|
|
86
|
-
return true;
|
|
87
|
-
} catch (e) {
|
|
88
|
-
logger.warn('firebase load failed:', e.message);
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
_getFirebaseAuth(strategy) {
|
|
94
|
-
if (bridge._firebaseAuth) return bridge._firebaseAuth;
|
|
95
|
-
|
|
96
|
-
const firebaseConfig = bridge._manager.config.cloud?.config;
|
|
97
|
-
if (!firebaseConfig || !Object.keys(firebaseConfig).length) {
|
|
98
|
-
throw new Error('cloud.config is empty — cannot initialize auth.');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const { initializeApp, getApp } = bridge._firebase;
|
|
102
|
-
const { getAuth, initializeAuth } = bridge._firebaseModule;
|
|
103
|
-
|
|
104
|
-
let app;
|
|
105
|
-
try { app = getApp(FIREBASE_APP_NAME); }
|
|
106
|
-
catch (e) { app = initializeApp(firebaseConfig, FIREBASE_APP_NAME); }
|
|
107
|
-
|
|
108
|
-
// With a storage strategy, boot auth on OUR persistence (session survives
|
|
109
|
-
// restarts); without one, firebase's Node default (in-memory) applies.
|
|
110
|
-
if (strategy && initializeAuth) {
|
|
111
|
-
bridge._firebaseAuth = initializeAuth(app, {
|
|
112
|
-
persistence: [authPersistence.buildFirebasePersistence(strategy)],
|
|
113
|
-
});
|
|
114
|
-
} else {
|
|
115
|
-
bridge._firebaseAuth = getAuth(app);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// A TESTING run talks to the LOCAL stack, never real auth — the same move
|
|
119
|
-
// getApiUrl() makes when it maps testing to localhost, and the same one
|
|
120
|
-
// @omega.js/extension's background SW makes for its emulator runs. Only an
|
|
121
|
-
// OMEGA_ENVIRONMENT=testing run reaches here; dev and production are untouched.
|
|
122
|
-
if (bridge._manager.isTesting()) {
|
|
123
|
-
const { connectAuthEmulator } = bridge._firebaseModule;
|
|
124
|
-
const port = bridge._authEmulatorPort();
|
|
125
|
-
logger.log(`testing run — connecting auth to the emulator on :${port}`);
|
|
126
|
-
connectAuthEmulator(bridge._firebaseAuth, `http://localhost:${port}`, { disableWarnings: true });
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return bridge._firebaseAuth;
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
// The auth emulator's port, on the same chain getApiUrl() walks: the
|
|
133
|
-
// resolved-port env channel (N7), then the `dev.ports` map the bundle baked
|
|
134
|
-
// into OMEGA_BUILD_JSON
|
|
135
|
-
// ([#745](https://github.com/Omega-JS-Stack/omega/issues/745)). The classic
|
|
136
|
-
// 9099 used to sit under those two as a last resort; it is gone (#834),
|
|
137
|
-
// because nothing identity-checks what answers on it and a neighbouring
|
|
138
|
-
// project's emulator reads as an auth mystery rather than a port problem.
|
|
139
|
-
_authEmulatorPort() {
|
|
140
|
-
return requiredPort(bridge._manager, 'OMEGA_AUTH_PORT', 'auth');
|
|
141
|
-
},
|
|
142
|
-
|
|
143
|
-
_registerIpc() {
|
|
144
|
-
if (bridge._ipcRegistered) return;
|
|
145
|
-
const ipc = bridge._manager.ipc;
|
|
146
|
-
|
|
147
|
-
// Renderer asks main: "I'm at UID X (or null). Are we in sync?"
|
|
148
|
-
ipc.handle('desktop:auth:sync-request', async ({ contextUid }) => {
|
|
149
|
-
return bridge._handleSyncRequest(contextUid);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
// Renderer asks main to sign out.
|
|
153
|
-
ipc.handle('desktop:auth:sign-out', async () => {
|
|
154
|
-
return bridge._handleSignOut();
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
// Renderer asks main for the current user (uid + email + displayName, no token).
|
|
158
|
-
ipc.handle('desktop:auth:get-user', () => {
|
|
159
|
-
const u = bridge._firebaseAuth?.currentUser;
|
|
160
|
-
return u ? bridge._snapshotUser(u) : null;
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
// Renderer pushes its @omega.js/client account resolution (auth().listen() settled:
|
|
164
|
-
// Firestore account fetched, subscription resolved). Main can't run Firestore,
|
|
165
|
-
// so this is how main-side plan gates learn the REAL plan — BXM's "browser
|
|
166
|
-
// contexts resolve, authority caches" split. UID-guarded: a stale push from a
|
|
167
|
-
// renderer that hasn't synced yet is dropped.
|
|
168
|
-
ipc.handle('desktop:auth:account-resolved', ({ uid, resolved, roles } = {}) => {
|
|
169
|
-
const mainUid = bridge._firebaseAuth?.currentUser?.uid || null;
|
|
170
|
-
if (!uid || uid !== mainUid) {
|
|
171
|
-
return { accepted: false };
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const changed = JSON.stringify(resolved) !== JSON.stringify(bridge._resolvedPlan)
|
|
175
|
-
|| JSON.stringify(roles || null) !== JSON.stringify(bridge._resolvedRoles);
|
|
176
|
-
bridge._resolvedPlan = resolved || null;
|
|
177
|
-
bridge._resolvedRoles = roles || null;
|
|
178
|
-
|
|
179
|
-
if (changed) {
|
|
180
|
-
logger.log(`account resolved — plan=${resolved?.plan || '(none)'} active=${!!resolved?.active}`);
|
|
181
|
-
bridge._manager.ipc.broadcast('desktop:auth:plan-changed', { resolved: bridge._resolvedPlan, roles: bridge._resolvedRoles });
|
|
182
|
-
// Main-side subscribers see the same user snapshot again with plan now known.
|
|
183
|
-
const u = bridge._firebaseAuth?.currentUser;
|
|
184
|
-
bridge._stateSubs.forEach((fn) => {
|
|
185
|
-
try { fn(u ? bridge._snapshotUser(u) : null); } catch (e) { logger.error('onAuthChange subscriber threw:', e); }
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
return { accepted: true };
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
bridge._ipcRegistered = true;
|
|
192
|
-
},
|
|
193
|
-
|
|
194
|
-
_handleAuthStateChange(user) {
|
|
195
|
-
logger.log(`auth state → ${user ? user.email : 'signed out'}`);
|
|
196
|
-
|
|
197
|
-
// Sign-out (or a different user signing in) invalidates the cached resolution —
|
|
198
|
-
// renderers re-resolve and push fresh via desktop:auth:account-resolved.
|
|
199
|
-
if (!user) {
|
|
200
|
-
bridge._resolvedPlan = null;
|
|
201
|
-
bridge._resolvedRoles = null;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Notify any main-side subscribers (consumer code that called manager.omega.onAuthChange).
|
|
205
|
-
const snap = user ? bridge._snapshotUser(user) : null;
|
|
206
|
-
bridge._stateSubs.forEach((fn) => {
|
|
207
|
-
try { fn(snap); } catch (e) { logger.error('onAuthChange subscriber threw:', e); }
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
// Tell renderers about the change so they can update UI / refresh menu items.
|
|
211
|
-
bridge._manager.ipc.broadcast('desktop:auth:state-changed', snap);
|
|
212
|
-
|
|
213
|
-
// Attribute Sentry events to the signed-in user (or clear on sign-out). When
|
|
214
|
-
// sentry is disabled (no DSN, dev mode, etc.) setUser is a documented no-op.
|
|
215
|
-
bridge._manager.sentry.setUser(snap);
|
|
216
|
-
},
|
|
217
|
-
|
|
218
|
-
// BXM's syncAuth pattern, ported to Electron.
|
|
219
|
-
async _handleSyncRequest(contextUid) {
|
|
220
|
-
if (!bridge._firebaseAuth) {
|
|
221
|
-
return { needsSync: false, reason: 'firebase-not-loaded' };
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const bgUser = bridge._firebaseAuth.currentUser;
|
|
225
|
-
const bgUid = bgUser?.uid || null;
|
|
226
|
-
|
|
227
|
-
// Already in sync.
|
|
228
|
-
if (contextUid === bgUid) {
|
|
229
|
-
return { needsSync: false };
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Renderer signed in but main signed out → tell renderer to sign out.
|
|
233
|
-
if (!bgUser && contextUid) {
|
|
234
|
-
return { needsSync: true, signOut: true };
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Main signed in, renderer not (or different user) → fetch a fresh custom token + send.
|
|
238
|
-
try {
|
|
239
|
-
const token = await bridge._fetchCustomToken(bgUser);
|
|
240
|
-
return {
|
|
241
|
-
needsSync: true,
|
|
242
|
-
customToken: token,
|
|
243
|
-
user: bridge._snapshotUser(bgUser),
|
|
244
|
-
};
|
|
245
|
-
} catch (e) {
|
|
246
|
-
logger.error('sync-request: failed to fetch custom token:', e.message);
|
|
247
|
-
return { needsSync: false, error: e.message };
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
|
|
251
|
-
async _handleSignOut() {
|
|
252
|
-
try {
|
|
253
|
-
if (bridge._firebaseAuth?.currentUser) {
|
|
254
|
-
await bridge._firebaseModule.signOut(bridge._firebaseAuth);
|
|
255
|
-
}
|
|
256
|
-
bridge._manager.ipc.broadcast('desktop:auth:sign-out', {});
|
|
257
|
-
return { success: true };
|
|
258
|
-
} catch (e) {
|
|
259
|
-
logger.error('sign-out failed:', e.message);
|
|
260
|
-
return { success: false, error: e.message };
|
|
261
|
-
}
|
|
262
|
-
},
|
|
263
|
-
|
|
264
|
-
// Public API ──────────────────────────────────────────────────────────────────
|
|
265
|
-
|
|
266
|
-
// Called by lib/deep-link's auth/token built-in.
|
|
267
|
-
async handleAuthToken(token) {
|
|
268
|
-
if (!bridge._firebaseAuth) {
|
|
269
|
-
logger.warn('handleAuthToken called but firebase not loaded — ignoring.');
|
|
270
|
-
return { success: false, reason: 'firebase-not-loaded' };
|
|
271
|
-
}
|
|
272
|
-
if (!token) {
|
|
273
|
-
logger.warn('handleAuthToken called with no token — ignoring.');
|
|
274
|
-
return { success: false, reason: 'no-token' };
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
try {
|
|
278
|
-
const cred = await bridge._firebaseModule.signInWithCustomToken(bridge._firebaseAuth, token);
|
|
279
|
-
logger.log(`signed in: ${cred.user.email || cred.user.uid}`);
|
|
280
|
-
|
|
281
|
-
// Broadcast the token to renderers so they can sign in with the SAME token.
|
|
282
|
-
// Tokens expire in 1 hour and aren't stored.
|
|
283
|
-
bridge._manager.ipc.broadcast('desktop:auth:sign-in-with-token', { token });
|
|
284
|
-
|
|
285
|
-
return { success: true, user: bridge._snapshotUser(cred.user) };
|
|
286
|
-
} catch (e) {
|
|
287
|
-
logger.error('signInWithCustomToken failed:', e.message);
|
|
288
|
-
return { success: false, error: e.message };
|
|
289
|
-
}
|
|
290
|
-
},
|
|
291
|
-
|
|
292
|
-
// Subscribe to auth state changes on the main side (e.g. for menu/tray refresh).
|
|
293
|
-
onAuthChange(fn) {
|
|
294
|
-
bridge._stateSubs.add(fn);
|
|
295
|
-
return () => bridge._stateSubs.delete(fn);
|
|
296
|
-
},
|
|
297
|
-
|
|
298
|
-
// Snapshot of the current user (sync), or null.
|
|
299
|
-
getCurrentUser() {
|
|
300
|
-
const u = bridge._firebaseAuth?.currentUser;
|
|
301
|
-
return u ? bridge._snapshotUser(u) : null;
|
|
302
|
-
},
|
|
303
|
-
|
|
304
|
-
// The renderer-resolved subscription ({ plan, active, trialing, cancelling }) or null
|
|
305
|
-
// while no renderer has resolved yet. THE main-side plan source — consumer plan gates
|
|
306
|
-
// read this (@omega.js/client's resolveSubscription output, pushed via desktop:auth:account-resolved).
|
|
307
|
-
getResolvedPlan() {
|
|
308
|
-
return bridge._resolvedPlan;
|
|
309
|
-
},
|
|
310
|
-
|
|
311
|
-
// The renderer-resolved account roles ({ admin, betaTester, ... }) or null.
|
|
312
|
-
getResolvedRoles() {
|
|
313
|
-
return bridge._resolvedRoles;
|
|
314
|
-
},
|
|
315
|
-
|
|
316
|
-
// Fresh Firebase ID token for the signed-in user (async), or null when
|
|
317
|
-
// signed out / Firebase absent. For consumer main code calling
|
|
318
|
-
// authenticated backend routes (`Authorization: Bearer <token>`).
|
|
319
|
-
async getIdToken() {
|
|
320
|
-
const u = bridge._firebaseAuth?.currentUser;
|
|
321
|
-
return u ? u.getIdToken() : null;
|
|
322
|
-
},
|
|
323
|
-
|
|
324
|
-
// Force sign-out from main code.
|
|
325
|
-
async signOut() {
|
|
326
|
-
return bridge._handleSignOut();
|
|
327
|
-
},
|
|
328
|
-
|
|
329
|
-
// ─── Internals ────────────────────────────────────────────────────────────
|
|
330
|
-
|
|
331
|
-
_snapshotUser(user) {
|
|
332
|
-
return {
|
|
333
|
-
uid: user.uid,
|
|
334
|
-
email: user.email,
|
|
335
|
-
displayName: user.displayName,
|
|
336
|
-
photoURL: user.photoURL,
|
|
337
|
-
emailVerified: user.emailVerified,
|
|
338
|
-
};
|
|
339
|
-
},
|
|
340
|
-
|
|
341
|
-
// Fetch a fresh custom token for the currently-signed-in user via the shared
|
|
342
|
-
// @omega.js/client request layer. Mirrors BXM: POST <apiUrl>/omega/user/token —
|
|
343
|
-
// the route defaults uid to the authenticated caller and responds { token }
|
|
344
|
-
// at the top level.
|
|
345
|
-
async _fetchCustomToken(user) {
|
|
346
|
-
const { createRequest } = require('@omega.js/client/modules/request.js');
|
|
347
|
-
|
|
348
|
-
const request = createRequest({
|
|
349
|
-
getApiUrl: () => bridge._manager.getApiUrl(),
|
|
350
|
-
getIdToken: (force) => user.getIdToken(force),
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
const data = await request('/omega/user/token', { method: 'POST', body: {} });
|
|
354
|
-
|
|
355
|
-
const token = data?.token;
|
|
356
|
-
if (!token) {
|
|
357
|
-
throw new Error('@omega.js/backend response missing token.');
|
|
358
|
-
}
|
|
359
|
-
return token;
|
|
360
|
-
},
|
|
361
|
-
|
|
362
|
-
// Tear-down used by tests — wipes state but keeps registered IPC handlers
|
|
363
|
-
// (they're idempotent via `ipc.handle` duplicate-detection).
|
|
364
|
-
async _resetForTests() {
|
|
365
|
-
try {
|
|
366
|
-
if (bridge._firebaseAuth?.currentUser && bridge._firebaseModule?.signOut) {
|
|
367
|
-
await bridge._firebaseModule.signOut(bridge._firebaseAuth);
|
|
368
|
-
}
|
|
369
|
-
} catch (e) { /* ignore */ }
|
|
370
|
-
bridge._stateSubs.clear();
|
|
371
|
-
},
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
module.exports = bridge;
|
package/dist/lib/logger.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
// Shared devkit module — vendored into dist/vendor/devkit at prepare time by the
|
|
2
|
-
// preparePackage `after` hook. This shim keeps the framework's internal require
|
|
3
|
-
// paths stable while the implementation lives in @omega.js/devkit.
|
|
4
|
-
module.exports = require('../vendor/devkit/logger.js');
|