@omega.js/desktop 0.52.0 → 0.54.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 +53 -48
- 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-run.js +4 -1
- package/dist/cli.js +3 -3
- package/dist/commands/build.js +2 -2
- package/dist/commands/cdp/capture.js +2 -2
- package/dist/commands/cdp/client.js +1 -1
- 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/cdp.js +1 -1
- package/dist/commands/clean.js +4 -5
- package/dist/commands/deploy.js +4 -4
- package/dist/commands/dev.js +25 -0
- package/dist/commands/finalize-release.js +4 -4
- package/dist/commands/launch.js +2 -2
- package/dist/commands/lib/deploy-precheck.js +3 -3
- package/dist/commands/lib/ensure-target.js +18 -23
- package/dist/commands/lib/migrate.js +17 -0
- package/dist/commands/logs.js +1 -1
- package/dist/commands/package.js +2 -2
- package/dist/commands/publish.js +2 -2
- package/dist/commands/release.js +4 -4
- package/dist/commands/runner.js +11 -11
- package/dist/commands/sign-windows.js +5 -5
- package/dist/commands/test.js +8 -8
- package/dist/commands/update.js +7 -6
- package/dist/commands/validate-certs.js +4 -4
- package/dist/commands/version.js +3 -3
- package/dist/defaults/.github/workflows/build.yml +18 -18
- package/dist/defaults/_.gitignore +0 -2
- package/dist/defaults/_mas/README.md +3 -3
- package/dist/defaults/config/certs/README.md +1 -1
- package/dist/defaults/config/omega.json5 +43 -43
- package/dist/defaults/docs/README.md +3 -3
- package/dist/defaults/gulpfile.js +1 -1
- package/dist/defaults/hooks/build/post.js +2 -2
- package/dist/defaults/hooks/build/pre.js +2 -2
- package/dist/defaults/hooks/deploy/pre.js +1 -1
- package/dist/defaults/hooks/notarize/post.js +2 -2
- package/dist/defaults/hooks/release/post.js +2 -2
- package/dist/defaults/hooks/release/pre.js +2 -2
- 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/assets/scss/pages/about.scss +1 -1
- package/dist/defaults/src/assets/scss/pages/main.scss +1 -1
- package/dist/defaults/src/assets/scss/pages/settings.scss +1 -1
- package/dist/defaults/src/integrations/context-menu/index.js +13 -13
- package/dist/defaults/src/integrations/menu/index.js +8 -8
- package/dist/defaults/src/integrations/tray/index.js +12 -12
- package/dist/defaults/src/main.js +5 -7
- package/dist/defaults/src/preload.js +4 -6
- package/dist/defaults/test/README.md +5 -5
- package/dist/defaults/test/_init.js +1 -1
- package/dist/gulp/main.js +9 -10
- package/dist/gulp/tasks/audit.js +11 -14
- 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 +29 -29
- package/dist/lib/restart-manager/install.js +1 -1
- package/dist/lib/restart-manager/protocol.js +1 -1
- 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 +399 -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 +21 -8
- 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/build-workflow-jobs.test.js +2 -2
- package/dist/test/suites/build/cli.test.js +30 -2
- package/dist/test/suites/build/config-schema.test.js +5 -5
- package/dist/test/suites/build/defaults-em-dash.test.js +22 -0
- package/dist/test/suites/build/defaults-scaffold.test.js +21 -7
- package/dist/test/suites/build/deploy-direct.test.js +7 -5
- package/dist/test/suites/build/deploy-dispatch.test.js +2 -1
- package/dist/test/suites/build/deploy-hook.test.js +7 -5
- package/dist/test/suites/build/dev-verb.test.js +67 -0
- package/dist/test/suites/build/ensure-target.test.js +13 -5
- 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 +7 -7
- package/dist/test/suites/build/migrate.test.js +29 -0
- 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/project-scripts-deps.test.js +6 -10
- package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
- package/dist/test/suites/build/runner-env-write.test.js +73 -0
- package/dist/test/suites/build/runner.test.js +11 -10
- package/dist/test/suites/build/sentry.test.js +2 -2
- package/dist/test/suites/build/setup-scripts.test.js +27 -0
- 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 +15 -4
- package/dist/test/suites/build/verb-logs.test.js +20 -0
- 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} +28 -8
- package/dist/test/utils/extended-mode-warning.js +1 -1
- package/dist/utils/boot-harness.js +56 -0
- package/dist/utils/build-pipeline.js +4 -4
- package/dist/utils/mode-helpers.js +2 -15
- package/dist/utils/runner-env.js +13 -28
- 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/company.js +46 -14
- package/dist/vendor/config/defaults.js +30 -7
- package/dist/vendor/config/edit.js +25 -3
- package/dist/vendor/config/env-delivery.js +1 -1
- package/dist/vendor/config/env-schema.js +3 -6
- package/dist/vendor/config/env.js +34 -22
- package/dist/vendor/config/environment.js +11 -30
- package/dist/vendor/config/index.js +21 -28
- package/dist/vendor/config/load.js +16 -9
- package/dist/vendor/config/platforms.js +1 -1
- package/dist/vendor/config/repo.js +10 -27
- package/dist/vendor/config/schema-client.js +64 -0
- package/dist/vendor/config/schema-cloud.js +38 -0
- package/dist/vendor/config/schema-manager.js +118 -0
- package/dist/vendor/config/schema-overrides.js +68 -0
- package/dist/vendor/config/schema.js +104 -160
- package/dist/vendor/config/site-global.js +2 -3
- package/dist/vendor/config/validate.js +97 -78
- package/dist/vendor/config/winback.js +1 -1
- package/dist/vendor/devkit/actions-secrets.js +1 -1
- package/dist/vendor/devkit/agents-md.js +233 -0
- package/dist/vendor/devkit/attach-log-file.js +16 -2
- package/dist/vendor/devkit/build-json.js +1 -1
- package/dist/vendor/devkit/ci-workflows.js +30 -30
- package/dist/vendor/devkit/cli-router.js +16 -11
- package/dist/vendor/devkit/defaults-engine.js +15 -51
- package/dist/vendor/devkit/deploy-snapshot.js +44 -9
- package/dist/vendor/devkit/env-lines.js +183 -0
- package/dist/vendor/devkit/local.js +64 -10
- package/dist/vendor/devkit/lockfile.js +32 -13
- package/dist/vendor/devkit/logger.js +7 -2
- package/dist/vendor/devkit/merge-line-files.js +219 -177
- package/dist/vendor/devkit/omega-bin.js +208 -111
- package/dist/vendor/devkit/preludes/docs-sync.js +52 -0
- package/dist/vendor/devkit/preludes/index.js +1 -0
- package/dist/vendor/devkit/target-picker.js +45 -0
- package/dist/vendor/devkit/test/dashed-files.js +37 -0
- package/dist/vendor/devkit/test/run-verb-under-tee.js +71 -0
- package/dist/vendor/devkit/test/runner-core.js +6 -6
- package/dist/vendor/devkit/update.js +15 -15
- package/dist/vendor/devkit/verb-scripts.js +40 -0
- package/dist/vendor/devkit/verbs.js +170 -0
- 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/package.json +19 -26
- package/dist/commands/install.js +0 -37
- package/dist/defaults/AGENTS.md +0 -110
- package/dist/defaults/CLAUDE.md +0 -1
- 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/dist/vendor/config/env-retired.js +0 -137
- package/dist/vendor/config/retired-keys.js +0 -635
- package/docs/analytics.md +0 -140
- package/docs/app-state.md +0 -92
- package/docs/audit.md +0 -69
- package/docs/auto-updater.md +0 -243
- package/docs/boot-sequence.md +0 -39
- package/docs/build-system.md +0 -169
- package/docs/cdp-debugging.md +0 -169
- package/docs/client-bridge.md +0 -269
- package/docs/common-mistakes.md +0 -21
- package/docs/config-schema.md +0 -120
- package/docs/context-menu.md +0 -112
- package/docs/context.md +0 -81
- package/docs/css.md +0 -90
- package/docs/deep-link.md +0 -186
- package/docs/environment-detection.md +0 -112
- package/docs/fontawesome.md +0 -107
- package/docs/hooks.md +0 -89
- package/docs/icons.md +0 -79
- package/docs/index.md +0 -317
- package/docs/installer-options.md +0 -165
- package/docs/ipc.md +0 -61
- package/docs/lib-modules.md +0 -53
- package/docs/logging.md +0 -229
- package/docs/menu.md +0 -160
- package/docs/releasing.md +0 -239
- package/docs/remote-config.md +0 -118
- package/docs/remote-scripts.md +0 -144
- package/docs/restart-manager.md +0 -144
- package/docs/runner.md +0 -290
- package/docs/sentry.md +0 -97
- package/docs/shared/agent-docs.md +0 -89
- package/docs/shared/analytics.md +0 -612
- package/docs/shared/brands.md +0 -57
- package/docs/shared/breaking-changes.md +0 -851
- package/docs/shared/config.md +0 -1952
- package/docs/shared/deploys.md +0 -341
- package/docs/shared/icons.md +0 -219
- package/docs/shared/local-dev.md +0 -167
- package/docs/shared/logging.md +0 -205
- package/docs/shared/monitoring.md +0 -167
- package/docs/shared/publishing.md +0 -187
- package/docs/shared/rulings.md +0 -34
- package/docs/shared/testing.md +0 -147
- package/docs/shared/theming.md +0 -629
- package/docs/shared/translation.md +0 -333
- package/docs/shared/updates.md +0 -61
- package/docs/signing.md +0 -293
- package/docs/startup.md +0 -142
- package/docs/storage.md +0 -59
- package/docs/templating.md +0 -101
- package/docs/test-boot-layer.md +0 -157
- package/docs/test-framework.md +0 -362
- package/docs/themes.md +0 -149
- package/docs/tooltips.md +0 -99
- package/docs/tray.md +0 -164
- package/docs/usage.md +0 -58
- package/docs/verts.md +0 -62
- package/docs/windows.md +0 -149
package/docs/config-schema.md
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# Config schema
|
|
2
|
-
|
|
3
|
-
@omega.js/desktop validates `config/omega.json5` against the canonical OMEGA schema in **`@omega.js/config`** (vendored into `dist/vendor/config/` at prepare time; also exposed to consumers as `require('@omega.js/desktop/config')`). The shared schema covers the cross-framework sections (brand, cloud, analytics, payment, monitoring, connections, theme, targets); the desktop-specific refinements (app.category, the `platforms` shipping declaration, platforms.windows.signing.strategy, startup.mode, restartManager.*, …) live in the same package's `TARGET_SCHEMAS.desktop` and apply when validating with `{ target: 'desktop' }`. Validation always runs against the RESOLVED config: `targets.desktop` contents land at the top level (see the monorepo's `docs/shared/config.md` for the format).
|
|
4
|
-
|
|
5
|
-
Validation runs in two places:
|
|
6
|
-
|
|
7
|
-
1. **`Manager.initialize()` (boot)** — hard-fails the app at boot if any required field is missing or any present field is invalid. So a misconfigured app never reaches the "white window of confusion" phase — it tells you exactly which field is broken.
|
|
8
|
-
2. **`gulp audit` (build)**: same schema, plus build-pipeline-specific extras (file-existence for icons, an addressable releases repo in publish mode, etc.).
|
|
9
|
-
|
|
10
|
-
## Schema entry shape
|
|
11
|
-
|
|
12
|
-
```js
|
|
13
|
-
{
|
|
14
|
-
path: 'brand.id', // dot-path into the config
|
|
15
|
-
type: 'string' | 'boolean' | 'number' | 'array' | 'object',
|
|
16
|
-
required: true | false | (config) => bool,
|
|
17
|
-
match: /^[a-z][a-z0-9+\-.]*$/, // string-value regex
|
|
18
|
-
enum: ['normal', 'hidden'], // value-must-be-in-this-list
|
|
19
|
-
description: 'Used for the deep-link scheme + default appId.',
|
|
20
|
-
}
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## The `required` flag
|
|
24
|
-
|
|
25
|
-
@omega.js/desktop keeps validation simple: **`required` is either `true`, `false`, or a function**.
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
required: true // hard-fail if missing
|
|
29
|
-
required: false // OK to omit (but if present, match/enum/type still run)
|
|
30
|
-
required: (cfg) => bool // conditional — predicate gets the full config
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
The function form is for "this field is mandatory only when another part of config is set." Illustrative shape (no current entry uses it — every present-day field is `true` or `false`):
|
|
34
|
-
|
|
35
|
-
```js
|
|
36
|
-
{
|
|
37
|
-
path: 'analytics.providers.google.id',
|
|
38
|
-
required: (cfg) => Boolean(cfg?.analytics?.providers?.google?.secret), // id mandatory only when a secret is configured
|
|
39
|
-
match: /^G-[A-Z0-9]+$/,
|
|
40
|
-
}
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
This is identical strictness in dev and production. There's no separate `'publish-only'` tier — if a field truly matters only for builds, validate it inside `gulp/audit.js` (next to `fileMustExist` calls for icons, etc.) rather than the schema.
|
|
44
|
-
|
|
45
|
-
## How `match` / `enum` / `type` interact with absence
|
|
46
|
-
|
|
47
|
-
They **only run when the value is present**. A missing field with `required: false` is silent. A missing field with `required: true` fires the "missing" error and nothing else — so consumers don't see a confusing flood of "missing AND wrong type AND doesn't match" for the same field.
|
|
48
|
-
|
|
49
|
-
## Presence-driven feature flags (@omega.js/backend convention)
|
|
50
|
-
|
|
51
|
-
A non-empty credential value enables a feature — there is no separate `enabled: true/false` flag for credential-gated features:
|
|
52
|
-
|
|
53
|
-
| Feature | Enable signal | Disable signal |
|
|
54
|
-
|---|---|---|
|
|
55
|
-
| Sentry | `monitoring.providers.sentry.dsn = 'https://...'` | `monitoring.providers.sentry.dsn = ''` |
|
|
56
|
-
| GA4 analytics | `analytics.providers.google.id = 'G-XXXXX'` | `analytics.providers.google.id = ''` |
|
|
57
|
-
| Firebase Auth (renderer) | `cloud.config.projectId = '...'` (etc.) | empty `cloud.config` |
|
|
58
|
-
|
|
59
|
-
**Exceptions where an explicit `enabled` flag exists:** `remoteConfig.enabled`, `autoUpdate.enabled`, `releases.enabled`, `restartManager.enabled`, `startup.openAtLogin.enabled`. (`platforms.linux.snap.enabled` was one until [#867](https://github.com/Omega-JS-Stack/omega/issues/867): the snap is a declared FORMAT now, so its presence is the switch and `platforms.linux.formats.snap: false` is the off.) These toggle BEHAVIOR, not credentials: a fork can keep the brand's `repo.org` and still want releases off, for example.
|
|
60
|
-
|
|
61
|
-
## Adding a new field
|
|
62
|
-
|
|
63
|
-
When you add a new config knob anywhere in @omega.js/desktop:
|
|
64
|
-
|
|
65
|
-
1. Add an entry to `TARGET_SCHEMAS.desktop` in `@omega.js/config` (`packages/config/src/schema.js` in the Omega monorepo) — or to `SHARED_SCHEMA` if the field is genuinely cross-framework.
|
|
66
|
-
2. If it has a default, set it in [`src/defaults/config/omega.json5`](../src/defaults/config/omega.json5) (under `targets.desktop` for desktop-scoped fields).
|
|
67
|
-
3. That's it. No separate validation logic to add elsewhere — the schema entry is the validation.
|
|
68
|
-
|
|
69
|
-
## What's NOT in the schema
|
|
70
|
-
|
|
71
|
-
These checks live in [`gulp/tasks/audit.js`](../src/gulp/tasks/audit.js) instead, because they depend on build-pipeline state rather than the config shape:
|
|
72
|
-
|
|
73
|
-
- **`src/main.js` / `src/preload.js` existence** — the bundle task skips them with a warning but the schema doesn't know about consumer entry points.
|
|
74
|
-
- **`brand.images.icon` file existence** — only enforced when packaging (`isBuildMode()` / `isPublishMode()`); dev runs with the default Electron icon.
|
|
75
|
-
- **An addressable releases repo** (`repo.org` + `brand.id`), only enforced in publish mode.
|
|
76
|
-
|
|
77
|
-
These are kept in `audit.js` so the schema stays a pure description of the config shape, callable from any context without dragging in build state.
|
|
78
|
-
|
|
79
|
-
## Examples
|
|
80
|
-
|
|
81
|
-
Required field missing:
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
@omega.js/desktop: config validation failed — fix the following in config/omega.json5:
|
|
85
|
-
1. config.brand.id is required — URL-scheme-safe slug. Used as deep-link scheme + default appId. Must be lowercase, start with a letter, alnum/+/-/.
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
Field present but invalid:
|
|
89
|
-
|
|
90
|
-
```
|
|
91
|
-
1. config.startup.mode "tray-only" is not allowed — must be one of [normal, hidden]
|
|
92
|
-
2. config.brand.id "My App!" does not match expected pattern /^[a-z][a-z0-9+\-.]*$/ — URL-scheme-safe slug. Used as deep-link scheme + default appId. Must be lowercase, start with a letter, alnum/+/-/.
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
Errors are numbered so you can fix everything in one pass instead of fix-rebuild-fix-rebuild.
|
|
96
|
-
|
|
97
|
-
## Adding payment fields (@omega.js/backend-shaped)
|
|
98
|
-
|
|
99
|
-
@omega.js/desktop's schema mirrors [@omega.js/backend's `manager-config.example.json`](https://github.com/itw-creative-works/backend-manager) shape for payment so the same product catalog reads identically on backend, web, and desktop:
|
|
100
|
-
|
|
101
|
-
```js
|
|
102
|
-
{
|
|
103
|
-
payment: {
|
|
104
|
-
providers: {
|
|
105
|
-
stripe: { publishableKey: 'pk_live_...' }, // schema: match /^pk_(test|live)_/
|
|
106
|
-
paypal: { clientId: '...' },
|
|
107
|
-
},
|
|
108
|
-
products: [
|
|
109
|
-
{ id: 'basic', name: 'Basic', type: 'subscription', limits: { credits: 100 } },
|
|
110
|
-
],
|
|
111
|
-
},
|
|
112
|
-
}
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
The schema only enforces shape for the few well-defined publishable keys — the product catalog itself is freeform so @omega.js/backend can extend it without @omega.js/desktop caring.
|
|
116
|
-
|
|
117
|
-
## Source
|
|
118
|
-
|
|
119
|
-
- Schema definitions + validator engine: `@omega.js/config` (`packages/config/src/{schema,validate}.js` in the Omega monorepo; vendored copy at `dist/vendor/config/`)
|
|
120
|
-
- @omega.js/desktop integration tests: [`src/test/suites/build/validate-config.test.js`](../src/test/suites/build/validate-config.test.js)
|
package/docs/context-menu.md
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
# Context Menu (Right-Click)
|
|
2
|
-
|
|
3
|
-
File-based context menu. Unlike tray and application menu (called once at boot), the context-menu definition is called **every time the user right-clicks** — so it gets fresh `params` each time and can vary the menu by selection.
|
|
4
|
-
|
|
5
|
-
## Config
|
|
6
|
-
|
|
7
|
-
No config block. Path is conventional: `src/integrations/context-menu/index.js`. To opt out, call `manager.contextMenu.disable()` from your main entry — after that, right-click events are silently swallowed.
|
|
8
|
-
|
|
9
|
-
## Definition file
|
|
10
|
-
|
|
11
|
-
```js
|
|
12
|
-
// src/integrations/context-menu/index.js
|
|
13
|
-
module.exports = ({ manager, menu, params, webContents }) => {
|
|
14
|
-
// Easiest: start from @omega.js/desktop's defaults, then customize per event.
|
|
15
|
-
menu.useDefaults();
|
|
16
|
-
|
|
17
|
-
// Add a "Search Google" entry when text is selected:
|
|
18
|
-
if (params.selectionText) {
|
|
19
|
-
menu.insertAfter('copy', {
|
|
20
|
-
id: 'search-google',
|
|
21
|
-
label: `Search "${params.selectionText.slice(0, 20)}"`,
|
|
22
|
-
click: () => require('electron').shell.openExternal(
|
|
23
|
-
`https://google.com/search?q=${encodeURIComponent(params.selectionText)}`,
|
|
24
|
-
),
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Hide the dev-tools entries even in development:
|
|
29
|
-
menu.remove('toggle-devtools');
|
|
30
|
-
};
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Calling no `menu.*` methods (or `menu.clear()` after `useDefaults()` with nothing added) **suppresses the popup** entirely.
|
|
34
|
-
|
|
35
|
-
## Builder API (per event)
|
|
36
|
-
|
|
37
|
-
```js
|
|
38
|
-
menu.item(descriptor)
|
|
39
|
-
menu.separator()
|
|
40
|
-
menu.submenu(label, items)
|
|
41
|
-
menu.useDefaults() // populate with @omega.js/desktop's defaults based on params
|
|
42
|
-
menu.clear() // wipe items added so far this event
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Id-path API (per event)
|
|
46
|
-
|
|
47
|
-
Same shape across menu / tray / context-menu. Available **inside the definition fn** on the `menu` builder. Operates on the items being built for the current right-click event:
|
|
48
|
-
|
|
49
|
-
```js
|
|
50
|
-
.find(idPath)
|
|
51
|
-
.has(idPath)
|
|
52
|
-
.update(idPath, patch)
|
|
53
|
-
.remove(idPath)
|
|
54
|
-
.enable(idPath, bool = true)
|
|
55
|
-
.show(idPath, bool = true)
|
|
56
|
-
.hide(idPath)
|
|
57
|
-
.insertBefore(idPath, item)
|
|
58
|
-
.insertAfter(idPath, item)
|
|
59
|
-
.appendTo(idPath, item)
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Context-menu ids are **flat** — no `context/` prefix needed (the lib namespace is implicit). Submenus you build with `menu.submenu(...)` are addressable as `parent/child` paths via the resolver.
|
|
63
|
-
|
|
64
|
-
(Runtime-on-`manager.contextMenu` mutators don't apply here — items are rebuilt every event. Mutate inside the definition fn instead.)
|
|
65
|
-
|
|
66
|
-
## Default template ids
|
|
67
|
-
|
|
68
|
-
@omega.js/desktop's `useDefaults()` populates items based on `params`. Every default item carries an id you can target:
|
|
69
|
-
|
|
70
|
-
| ID | When it appears |
|
|
71
|
-
|---|---|
|
|
72
|
-
| `undo`, `redo` | `params.editFlags.canUndo` / `canRedo` |
|
|
73
|
-
| `cut`, `copy`, `paste`, `paste-and-match-style`, `select-all` | `params.isEditable` |
|
|
74
|
-
| `copy` | `params.selectionText` (read-only) |
|
|
75
|
-
| `open-link`, `copy-link` | `params.linkURL` |
|
|
76
|
-
| `reload` | always |
|
|
77
|
-
| `inspect`, `toggle-devtools` | `manager.isDevelopment()` only |
|
|
78
|
-
|
|
79
|
-
## Definition fn arguments
|
|
80
|
-
|
|
81
|
-
| Arg | Description |
|
|
82
|
-
|---|---|
|
|
83
|
-
| `manager` | The running @omega.js/desktop Manager |
|
|
84
|
-
| `menu` | Per-event builder + id-path API |
|
|
85
|
-
| `params` | Electron's [`ContextMenuParams`](https://www.electronjs.org/docs/latest/api/web-contents#event-context-menu) — `selectionText`, `isEditable`, `linkURL`, `srcURL`, `mediaType`, `editFlags`, `x`, `y`, etc. |
|
|
86
|
-
| `webContents` | The `webContents` that fired the event |
|
|
87
|
-
|
|
88
|
-
## Auto-attach
|
|
89
|
-
|
|
90
|
-
Every window created via `manager.windows.createNamed()` is automatically wired up with the context-menu listener. Idempotent per `webContents` (uses a `WeakSet`). For windows you create directly with `new BrowserWindow()`, call:
|
|
91
|
-
|
|
92
|
-
```js
|
|
93
|
-
manager.contextMenu.attach(win.webContents);
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Runtime API on `manager.contextMenu`
|
|
97
|
-
|
|
98
|
-
```js
|
|
99
|
-
manager.contextMenu.define(fn) // replace the definition at runtime
|
|
100
|
-
manager.contextMenu.disable() // ignore future right-click events (idempotent)
|
|
101
|
-
manager.contextMenu.attach(webContents) // manual attach
|
|
102
|
-
manager.contextMenu.buildItems(params, wc) // run the definition without popping a menu (useful for tests)
|
|
103
|
-
manager.contextMenu.hasCustomDefinition() // false → using the built-in default fn
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
## Default fn
|
|
107
|
-
|
|
108
|
-
Without a consumer file, @omega.js/desktop uses a built-in fallback that just calls `useDefaults()` — sensible undo/redo/cut/copy/paste/link/reload/inspect baseline. Same behavior as the default scaffold.
|
|
109
|
-
|
|
110
|
-
## Default scaffold
|
|
111
|
-
|
|
112
|
-
The scaffold every verb runs ships `src/integrations/context-menu/index.js` calling `menu.useDefaults()` plus commented-out examples covering insertAfter, remove, hide, enable, and building from scratch.
|
package/docs/context.md
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
# Context
|
|
2
|
-
|
|
3
|
-
Runtime info block. Mirrors @omega.js/backend's `assistant.request.{geolocation,client}` shape so @omega.js/desktop apps + sister projects (@omega.js/backend, UJM, @omega.js/client) all reference the same property paths when reading user info.
|
|
4
|
-
|
|
5
|
-
Populated asynchronously during `manager.initialize()`.
|
|
6
|
-
|
|
7
|
-
## Shape
|
|
8
|
-
|
|
9
|
-
```js
|
|
10
|
-
manager.context.geolocation = {
|
|
11
|
-
ip: '203.0.113.42', // async-fetched via ipify
|
|
12
|
-
country: null, // future enhancement
|
|
13
|
-
region: null,
|
|
14
|
-
city: null,
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
manager.context.client = {
|
|
18
|
-
userAgent: 'Mozilla/5.0 ...', // app.userAgentFallback
|
|
19
|
-
locale: 'en-US', // app.getLocale()
|
|
20
|
-
platform: 'darwin', // os.platform()
|
|
21
|
-
arch: 'arm64', // os.arch()
|
|
22
|
-
mobile: false, // always false on @omega.js/desktop (desktop framework)
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
manager.context.session = {
|
|
26
|
-
id: '<uuid>', // fresh per launch (crypto.randomUUID)
|
|
27
|
-
startTime: '2026-05-08T...', // ISO at boot
|
|
28
|
-
deviceId: '<uuid or MAC>', // stable per-machine
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
manager.context.app = {
|
|
32
|
-
version: '1.2.3', // manager.getVersion()
|
|
33
|
-
environment: 'production', // manager.getEnvironment()
|
|
34
|
-
isPackaged: true, // app.isPackaged
|
|
35
|
-
};
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Device ID resolution
|
|
39
|
-
|
|
40
|
-
The walk itself is the shared one — `@omega.js/analytics`' `deriveDeviceId({ get, set, seed })`, the same call `@omega.js/client` makes on a page ([#396](https://github.com/Omega-JS-Stack/omega/issues/396)). What this module supplies is desktop's own world: electron-store, and the MAC as the seed. Order:
|
|
41
|
-
|
|
42
|
-
1. **Storage** — already persisted from a prior boot. Wins so we're stable across NIC swaps / VPN changes.
|
|
43
|
-
2. **First non-internal MAC** from `os.networkInterfaces()`, the injected seed. Stable on a stable rig, and it hands a reinstalled app the id it had before its storage was wiped.
|
|
44
|
-
3. **A generated UUID** — the shared derivation's floor. Persisted on first launch.
|
|
45
|
-
|
|
46
|
-
Once resolved on first launch it never changes. This is the input to `analytics._clientId = uuidv5(deviceId, projectIdNamespace)`, and it is desktop's alone: a browser on the same machine derives its own id from its own localStorage.
|
|
47
|
-
|
|
48
|
-
## Geolocation
|
|
49
|
-
|
|
50
|
-
`geolocation.ip` is fetched in the background via `https://api.ipify.org?format=json`. Cached to `storage.context.geolocation` so the next launch has last-known-good values even if offline. The `country/region/city` fields are reserved for a future enrichment provider.
|
|
51
|
-
|
|
52
|
-
Failure mode: a failed ipify fetch leaves the previous cached value untouched. The app keeps working with last-known-good.
|
|
53
|
-
|
|
54
|
-
## API
|
|
55
|
-
|
|
56
|
-
```js
|
|
57
|
-
manager.context.geolocation.ip // direct read
|
|
58
|
-
manager.context.session.deviceId // direct read
|
|
59
|
-
const snap = manager.context.toJSON(); // structured-cloneable snapshot
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Renderer:
|
|
63
|
-
|
|
64
|
-
```js
|
|
65
|
-
const snap = await window.desktop.context.get();
|
|
66
|
-
console.log(snap.session.deviceId);
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
## Why the @omega.js/backend shape
|
|
70
|
-
|
|
71
|
-
Sister projects (@omega.js/backend, @omega.js/client, UJM) all reference paths like `assistant.request.geolocation.country` and `assistant.request.client.userAgent`. @omega.js/desktop matches the leaf names so consumer code can write logic that works across all four runtimes:
|
|
72
|
-
|
|
73
|
-
```js
|
|
74
|
-
const country = manager.context.geolocation.country
|
|
75
|
-
|| assistant.request.geolocation.country // @omega.js/backend
|
|
76
|
-
|| omega.context.geolocation.country;
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## Tests
|
|
80
|
-
|
|
81
|
-
- `src/test/suites/main/context.test.js` — session shape, deviceId stability across re-init, the injected seed + persistence of the shared derivation, client info, IPC handler, JSON-roundtrippability.
|
package/docs/css.md
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
# CSS Architecture
|
|
2
|
-
|
|
3
|
-
@omega.js/desktop styles are SCSS, compiled by the pipeline's `sass` task into per-window bundles on top of a shared base. Bootstrap 5 (via @omega.js/desktop's classy theme) is the foundation — consumers restyle Bootstrap, they don't replace it.
|
|
4
|
-
|
|
5
|
-
## Main entry
|
|
6
|
-
|
|
7
|
-
`<consumer>/src/assets/scss/main.scss` — loaded by EVERY window. It configures the theme via `@use ... with (...)`:
|
|
8
|
-
|
|
9
|
-
```scss
|
|
10
|
-
// Generated from `brand.color` by the sass task (#912).
|
|
11
|
-
@use 'brand';
|
|
12
|
-
|
|
13
|
-
@use 'omega-desktop' as * with (
|
|
14
|
-
$primary: brand.$primary,
|
|
15
|
-
$dark: #1a1a2e,
|
|
16
|
-
$classy-bg-dark: #0f0f1a,
|
|
17
|
-
$classy-bg-dark-secondary: #161628,
|
|
18
|
-
$classy-bg-dark-tertiary: #1e1e38,
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
// The runtime --omega-accent ramp, after the framework import.
|
|
22
|
-
@include brand.ramp;
|
|
23
|
-
|
|
24
|
-
// Custom global styles below
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Compiles to `dist/assets/css/main.bundle.css` (Bootstrap + classy theme + your globals).
|
|
28
|
-
|
|
29
|
-
## Per-window styles
|
|
30
|
-
|
|
31
|
-
`src/assets/scss/pages/<window>.scss` → `dist/assets/css/components/<window>.bundle.css`, loaded ONLY on that window's page. One file per window (`main.scss`, `settings.scss`, …) — page-specific chrome lives here, shared styles live in the main entry.
|
|
32
|
-
|
|
33
|
-
## Theme integration
|
|
34
|
-
|
|
35
|
-
The `@use 'omega-desktop'` entry pulls in Bootstrap 5 + @omega.js/desktop's classy theme. Appearance (`system`/`light`/`dark`) defaults from `config.theme.appearance` and is applied + kept live on `<html data-bs-theme>` by `manager.theme` (OS-following, runtime-switchable, persisted override, see [themes.md](themes.md)). Theme variables (`$primary`, `$dark`, `$classy-bg-*`, typography, borders) are overridable via the `with (...)` block, and `$primary` arrives from `brand.color` through the generated `dist/assets/scss/_brand.scss` unless a literal replaces `brand.$primary` ([#912](https://github.com/Omega-JS-Stack/omega/issues/912)). See [themes.md](themes.md) for the full variable reference.
|
|
36
|
-
|
|
37
|
-
## Icon presentation
|
|
38
|
-
|
|
39
|
-
Icon CSS is ONE sheet for every omega target, vendored from @omega.js/web at prepare (package.json `omega.vendorAssets` → `dist/assets/css/core/_fontawesome.scss`) and loaded by the `omega-desktop` entry. It ships the square glyph-centered box every rendered `<i>` gets, the `fa-2xs`…`fa-6xl` size scale, and the `fa-spin` / `fa-bounce` / `fa-beat` utilities (each parked under `prefers-reduced-motion`). Nothing to import and nothing to hand-fix. See [shared/icons.md](shared/icons.md).
|
|
40
|
-
|
|
41
|
-
## App shell
|
|
42
|
-
|
|
43
|
-
Dashboard/admin windows use the `.omega-shell` layout — a sidebar + topbar + main grid with a collapsible desktop rail and a mobile drawer. Two layers ship, both vendored from @omega.js/web at prepare: the MECHANICS (`dist/assets/css/shell/_index.scss` — the grid, region geometry, states, and the `--omega-shell-*` tokens, loaded by the `omega-desktop` entry before the theme) and the theme's SKIN (`dist/assets/themes/<theme-id>/css/layout/_shell.scss`, layered over it). Nothing to import — `@use 'omega-desktop'` gets both.
|
|
44
|
-
|
|
45
|
-
Emit this markup in the window's HTML:
|
|
46
|
-
|
|
47
|
-
```html
|
|
48
|
-
<div class="omega-shell" data-omega-shell>
|
|
49
|
-
<aside class="omega-shell__sidebar" id="app-sidebar">
|
|
50
|
-
<!-- pinned head (brand, selector) sits here, outside the scroll region -->
|
|
51
|
-
<div class="omega-shell__sidebar-scroll">
|
|
52
|
-
<!-- nav scrolls HERE (the rail itself clips nothing, so popovers can
|
|
53
|
-
escape); text that should hide in the collapsed rail wears
|
|
54
|
-
.omega-shell__label -->
|
|
55
|
-
</div>
|
|
56
|
-
</aside>
|
|
57
|
-
|
|
58
|
-
<header class="omega-shell__topbar">
|
|
59
|
-
<div class="omega-shell__topbar-start">
|
|
60
|
-
<button data-shell-toggle="drawer" aria-expanded="false" aria-controls="app-sidebar">☰</button>
|
|
61
|
-
<button data-shell-toggle="collapse" aria-expanded="true" aria-controls="app-sidebar">⇤</button>
|
|
62
|
-
</div>
|
|
63
|
-
<div class="omega-shell__topbar-end"><!-- account menu, actions --></div>
|
|
64
|
-
</header>
|
|
65
|
-
|
|
66
|
-
<main class="omega-shell__main"><!-- page content --></main>
|
|
67
|
-
|
|
68
|
-
<div class="omega-shell__scrim" data-shell-dismiss></div>
|
|
69
|
-
</div>
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Wire the behavior from a renderer component (`src/assets/js/components/<window>/index.js`) — `__main_assets__` is the build alias for @omega.js/desktop's vendored core assets:
|
|
73
|
-
|
|
74
|
-
```js
|
|
75
|
-
import appShell from '__main_assets__/js/core/app-shell.js';
|
|
76
|
-
|
|
77
|
-
appShell();
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
The module is delegated and declarative: `[data-shell-toggle="collapse"]` toggles the rail, `[data-shell-toggle="drawer"]` toggles the mobile drawer, `[data-shell-dismiss]` (and Escape) closes it. It stamps the state on the container — `data-shell-collapsed="true"` (persisted under the `shell.collapsed` storage key) and `data-shell-open="true"` — which is what the CSS keys off; the API is also registered at `omega._library.appShell`. Add `.omega-shell--locked` when `main` should never scroll (the page manages its own interior scroll).
|
|
81
|
-
|
|
82
|
-
## Bootstrap-first convention
|
|
83
|
-
|
|
84
|
-
NEVER create custom classes for things Bootstrap already provides — use `btn`, `card`, `form-*`, `d-flex`, `gap-*`, `rounded-*`, `bg-body-*`, `text-*` natively, and use `bg-body` variants (not `bg-light`/`bg-dark`) so dark mode adapts. Theme SCSS overrides how Bootstrap components LOOK; custom CSS is only for genuinely novel components with no Bootstrap equivalent. Same rule in BXM and UJM.
|
|
85
|
-
|
|
86
|
-
## See also
|
|
87
|
-
|
|
88
|
-
- [themes.md](themes.md) — theme variables, appearance modes
|
|
89
|
-
- [build-system.md](build-system.md) — where the `sass` task runs in the pipeline
|
|
90
|
-
- [templating.md](templating.md) — the page template that loads the bundles
|
package/docs/deep-link.md
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
# Deep Links
|
|
2
|
-
|
|
3
|
-
Cross-platform deep-link handling that's simple to use and hard to get wrong. @omega.js/desktop owns all the OS plumbing (single-instance lock, scheme registration, argv parsing, second-instance routing, focus-on-warm-start) and gives you one unified event API regardless of how the link arrived.
|
|
4
|
-
|
|
5
|
-
## Config
|
|
6
|
-
|
|
7
|
-
```jsonc
|
|
8
|
-
"deepLinks": {
|
|
9
|
-
"schemes": ["myapp"] // urls like myapp://...
|
|
10
|
-
}
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
@omega.js/desktop registers each scheme with the OS via `app.setAsDefaultProtocolClient` so the system routes matching URLs to your app. Registration is **production-only** — dev/test runs never claim OS-wide protocol handlers for unpackaged Electron binaries. In dev, exercise your handlers with `manager.deepLink.dispatch(url)` instead.
|
|
14
|
-
|
|
15
|
-
## How it works (so you don't have to think about it)
|
|
16
|
-
|
|
17
|
-
| Platform | Cold-start (app not running) | Warm-start (app already running) |
|
|
18
|
-
|---|---|---|
|
|
19
|
-
| **macOS** | `app.on('open-url')` — queued before `whenReady`, drained after | `app.on('open-url')` |
|
|
20
|
-
| **Windows** | URL appended to `process.argv`; @omega.js/desktop extracts it | OS forwards argv to the existing instance via `app.on('second-instance')`; @omega.js/desktop reads the duplicate's real argv from that event's `additionalData` |
|
|
21
|
-
| **Linux** | Same as Windows | Same as Windows |
|
|
22
|
-
|
|
23
|
-
@omega.js/desktop handles all of these and dispatches them through the same `manager.deepLink.on()` event registry. Your code looks identical regardless of platform or cold/warm start. Single-instance lock is acquired automatically (via `lib/protocol.js`); duplicate launches exit cleanly and forward their argv to the original instance.
|
|
24
|
-
|
|
25
|
-
## Public API
|
|
26
|
-
|
|
27
|
-
```js
|
|
28
|
-
manager.deepLink.on(pattern, handler) // register a handler. Returns unsubscribe fn.
|
|
29
|
-
manager.deepLink.off(pattern, handler)
|
|
30
|
-
manager.deepLink.dispatch(url) // manually fire (testing, custom triggers)
|
|
31
|
-
manager.deepLink.getColdStartUrl() // the URL the app was launched with, or null
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Patterns
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
'auth/token' // exact match
|
|
38
|
-
'user/profile/:id' // named param → ctx.params.id
|
|
39
|
-
'org/:slug/repo/:repo' // multiple params
|
|
40
|
-
'*' // wildcard catch-all (only fires when no concrete handler matched)
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Handler signature
|
|
44
|
-
|
|
45
|
-
```js
|
|
46
|
-
manager.deepLink.on('user/profile/:id', (ctx) => {
|
|
47
|
-
ctx.url // 'myapp://user/profile/42?ref=tray'
|
|
48
|
-
ctx.scheme // 'myapp'
|
|
49
|
-
ctx.route // 'user/profile/42'
|
|
50
|
-
ctx.pattern // 'user/profile/:id'
|
|
51
|
-
ctx.params // { id: '42' }
|
|
52
|
-
ctx.query // { ref: 'tray' }
|
|
53
|
-
ctx.source // 'cold-start' | 'warm-start' | 'manual'
|
|
54
|
-
ctx.argv // process.argv (cold) or the duplicate's real argv (warm, from additionalData)
|
|
55
|
-
ctx.cwd // working directory (the duplicate's on warm-start)
|
|
56
|
-
ctx.handled // mutable: set true to suppress remaining handlers (including built-ins)
|
|
57
|
-
});
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Built-in routes
|
|
61
|
-
|
|
62
|
-
@omega.js/desktop ships with handlers for common patterns. They run AFTER consumer handlers, so you can shadow any of them by registering your own handler at the same pattern.
|
|
63
|
-
|
|
64
|
-
| Route | Default behavior |
|
|
65
|
-
|---|---|
|
|
66
|
-
| `auth/token` | Calls `manager.omega.handleAuthToken(query.authToken)` — the receiving end of the `manager.openAuthFlow()` sign-in round-trip. MODERN shape only (`?authToken=`, what the website's token page sends); legacy-app formats (`?token=`, `?payload=`) are UJM's concern and are ignored. In production the URL arrives via the OS scheme; in dev/test `lib/auth-flow.js`'s loopback listener dispatches the same URL manually (the scheme isn't OS-registered in dev — protocol.js registers only in production, and macOS can't runtime-register unlisted schemes at all) |
|
|
67
|
-
| `app/show` | `manager.windows.show(query.window || 'main')` |
|
|
68
|
-
| `app/quit` | `app.quit()` |
|
|
69
|
-
|
|
70
|
-
### Overriding a built-in
|
|
71
|
-
|
|
72
|
-
```js
|
|
73
|
-
// Replace the built-in app/show with custom logic.
|
|
74
|
-
manager.deepLink.on('app/show', (ctx) => {
|
|
75
|
-
if (ctx.query.window === 'admin' && !manager.appState.isAdminUser()) {
|
|
76
|
-
showError('not authorized');
|
|
77
|
-
ctx.handled = true; // suppress built-in
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
// Otherwise let the built-in run normally.
|
|
81
|
-
});
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
## Resolution order
|
|
85
|
-
|
|
86
|
-
For each incoming URL, @omega.js/desktop walks handlers in this order:
|
|
87
|
-
|
|
88
|
-
1. **Consumer concrete handlers** (any non-wildcard pattern you registered with `.on()`)
|
|
89
|
-
2. **Built-in concrete handlers** (`auth/token`, `app/show`, `app/quit`)
|
|
90
|
-
3. **Wildcard handlers** (`'*'`) — only if NO concrete handler matched
|
|
91
|
-
|
|
92
|
-
Setting `ctx.handled = true` in any handler stops the cascade. Within a single tier, handlers fire in registration order. Errors in a handler are caught and logged — they don't stop subsequent handlers.
|
|
93
|
-
|
|
94
|
-
## Common patterns
|
|
95
|
-
|
|
96
|
-
### Route to a window + send IPC
|
|
97
|
-
|
|
98
|
-
```js
|
|
99
|
-
manager.deepLink.on('user/profile/:id', (ctx) => {
|
|
100
|
-
manager.windows.show('main');
|
|
101
|
-
manager.windows.get('main').webContents.send('navigate', {
|
|
102
|
-
to: `/profile/${ctx.params.id}`,
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Catch-all logger
|
|
108
|
-
|
|
109
|
-
```js
|
|
110
|
-
manager.deepLink.on('*', (ctx) => {
|
|
111
|
-
manager.logger.warn(`Unrouted deep link: ${ctx.url}`);
|
|
112
|
-
});
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### Cold-start branching
|
|
116
|
-
|
|
117
|
-
```js
|
|
118
|
-
const coldUrl = manager.deepLink.getColdStartUrl();
|
|
119
|
-
if (coldUrl) {
|
|
120
|
-
manager.logger.log(`Launched from deep link: ${coldUrl}`);
|
|
121
|
-
// appState.launchedFromDeepLink() is also set automatically
|
|
122
|
-
}
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
### Manually dispatching (e.g. from a tray click)
|
|
126
|
-
|
|
127
|
-
```js
|
|
128
|
-
tray.item({
|
|
129
|
-
label: 'Open Profile',
|
|
130
|
-
click: () => manager.deepLink.dispatch('myapp://user/profile/me'),
|
|
131
|
-
});
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## Boot queueing
|
|
135
|
-
|
|
136
|
-
Every dispatch is held until `manager.initialize()` completes (main.js calls `deepLink.markManagerReady()` as its last step). A cold-start `auth/token` link — the OS launching the app from the sign-in round trip — therefore never fires before client-bridge has Firebase up; it queues and drains the moment the manager is ready. Warm-start dispatches on a running app pass straight through.
|
|
137
|
-
|
|
138
|
-
## Single-instance behavior
|
|
139
|
-
|
|
140
|
-
@omega.js/desktop acquires the OS-level single-instance lock during `protocol.initialize()` (boot step 5, before deep-link inits). If another copy of the app is already running:
|
|
141
|
-
|
|
142
|
-
1. The new instance loses the lock.
|
|
143
|
-
2. The OS forwards its argv to the original instance.
|
|
144
|
-
3. The new instance's `Manager.initialize()` returns early (after `protocol.hasSingleInstanceLock() === false`).
|
|
145
|
-
4. The original instance's `app.on('second-instance')` fires with the Chromium-processed argv as its second argument AND the duplicate's real argv as its fourth, `additionalData` (@omega.js/desktop passes `{ argv, cwd }` to `app.requestSingleInstanceLock()` for you).
|
|
146
|
-
5. @omega.js/desktop extracts the deep-link URL from that argv and dispatches normally — but as `source: 'warm-start'`.
|
|
147
|
-
6. @omega.js/desktop also focuses the existing main window automatically (consumer can override by registering a route handler that does its own thing).
|
|
148
|
-
|
|
149
|
-
Reading the duplicate's own flags (a CLI-shaped app, a `--open <file>` handler) means reading that fourth argument:
|
|
150
|
-
|
|
151
|
-
```js
|
|
152
|
-
app.on('second-instance', (event, argv, cwd, additionalData) => additionalData.argv);
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
Never parse the event's own `argv` for flags: Chromium re-serializes it (switches first, Chromium's own switches spliced in, the values detached at the end), so a `--message two` launch arrives with the value detached from the flag.
|
|
156
|
-
|
|
157
|
-
## Linking with `appState`
|
|
158
|
-
|
|
159
|
-
When a deep link is detected at cold-start, @omega.js/desktop calls `manager.appState.setLaunchedFromDeepLink(true)`. This means:
|
|
160
|
-
|
|
161
|
-
```js
|
|
162
|
-
if (manager.appState.launchedFromDeepLink()) {
|
|
163
|
-
// user clicked a link to launch the app — handle differently than a tray click or login launch
|
|
164
|
-
}
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
Combine with `appState.isFirstLaunch()` to detect "first launch via deep link" (e.g. from an onboarding flow on your website).
|
|
168
|
-
|
|
169
|
-
## Testing
|
|
170
|
-
|
|
171
|
-
The dispatch pipeline is unit-testable without actually triggering an OS event:
|
|
172
|
-
|
|
173
|
-
```js
|
|
174
|
-
manager.deepLink.dispatch('myapp://auth/token?token=test');
|
|
175
|
-
// Fires source='manual'. Handlers run synchronously.
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
See `src/test/suites/main/deep-link.test.js` for the full coverage.
|
|
179
|
-
|
|
180
|
-
## Implementation notes
|
|
181
|
-
|
|
182
|
-
- `lib/protocol.js` owns the single-instance lock + scheme registration; `lib/deep-link.js` owns the dispatch pipeline. They're separate modules but tightly coupled.
|
|
183
|
-
- OS scheme registration is gated on `manager.isProduction()` (in `lib/protocol.js`) — unpackaged dev/test binaries are never registered as system protocol handlers (unconditional registration also intermittently triggered macOS Launch Services `-600` dialogs during test runs).
|
|
184
|
-
- On Windows/Linux, scheme registration uses `app.setAsDefaultProtocolClient(scheme, process.execPath, [process.cwd()])` so `app.exe scheme://...` style invocations route argv correctly.
|
|
185
|
-
- macOS open-url events that arrive before `whenReady` are queued internally and drained on `deepLink.initialize()`.
|
|
186
|
-
- Argv extraction walks backward from the end of argv (where the URL typically sits) and matches against registered schemes.
|