@omega.js/desktop 0.51.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.
Files changed (289) hide show
  1. package/README.md +18 -13
  2. package/dist/assets/css/core/_initialize.scss +1 -1
  3. package/dist/assets/js/core/app-shell.js +14 -15
  4. package/dist/assets/themes/_template/_theme.js +6 -6
  5. package/dist/assets/themes/base/_includes/global/sections/account.html +4 -4
  6. package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +5 -5
  7. package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +3 -3
  8. package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +1 -1
  9. package/dist/assets/themes/base/_layouts/frontend/pages/blog/tags/tag.html +1 -1
  10. package/dist/assets/themes/base/_layouts/frontend/pages/payment/confirmation.html +1 -1
  11. package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.js +2 -3
  12. package/dist/assets/themes/base/_sections/verts/unit/section.html +1 -1
  13. package/dist/assets/themes/base/_sections/verts/unit/section.js +3 -4
  14. package/dist/assets/themes/base/_theme.js +4 -3
  15. package/dist/assets/themes/bootstrap/_theme.js +2 -2
  16. package/dist/assets/themes/bootstrap/overrides/_links.scss +1 -1
  17. package/dist/assets/themes/classy/_theme.js +8 -6
  18. package/dist/assets/themes/classy/css/marketing/_sections.scss +1 -2
  19. package/dist/assets/themes/classy/js/hero-demo-form.js +3 -2
  20. package/dist/assets/themes/neobrutalism/_theme.js +5 -5
  21. package/dist/assets/themes/neobrutalism/js/pages/test/libraries/layers/index.js +1 -1
  22. package/dist/assets/themes/newsflash/_theme.js +6 -6
  23. package/dist/assets/themes/newsflash/js/pages/test/libraries/layers/index.js +1 -1
  24. package/dist/build.js +87 -111
  25. package/dist/cli.js +1 -1
  26. package/dist/commands/build.js +2 -2
  27. package/dist/commands/cdp/capture.js +2 -2
  28. package/dist/commands/cdp/quit.js +2 -2
  29. package/dist/commands/cdp/relaunch.js +2 -2
  30. package/dist/commands/cdp/theme.js +1 -1
  31. package/dist/commands/clean.js +2 -2
  32. package/dist/commands/deploy.js +4 -4
  33. package/dist/commands/finalize-release.js +4 -4
  34. package/dist/commands/install.js +3 -3
  35. package/dist/commands/launch.js +2 -2
  36. package/dist/commands/lib/deploy-precheck.js +3 -3
  37. package/dist/commands/lib/ensure-target.js +6 -6
  38. package/dist/commands/package.js +2 -2
  39. package/dist/commands/publish.js +2 -2
  40. package/dist/commands/release.js +3 -3
  41. package/dist/commands/runner.js +145 -48
  42. package/dist/commands/sign-windows.js +5 -5
  43. package/dist/commands/test.js +4 -4
  44. package/dist/commands/update.js +2 -2
  45. package/dist/commands/validate-certs.js +4 -4
  46. package/dist/commands/version.js +3 -3
  47. package/dist/defaults/.github/workflows/build.yml +2 -0
  48. package/dist/defaults/AGENTS.md +17 -8
  49. package/dist/defaults/config/omega.json5 +7 -7
  50. package/dist/defaults/hooks/build/post.js +1 -1
  51. package/dist/defaults/hooks/build/pre.js +1 -1
  52. package/dist/defaults/hooks/deploy/pre.js +1 -1
  53. package/dist/defaults/hooks/release/post.js +1 -1
  54. package/dist/defaults/hooks/release/pre.js +1 -1
  55. package/dist/defaults/src/assets/js/components/about/index.js +3 -5
  56. package/dist/defaults/src/assets/js/components/main/index.js +3 -5
  57. package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
  58. package/dist/defaults/src/integrations/context-menu/index.js +2 -2
  59. package/dist/defaults/src/integrations/menu/index.js +3 -3
  60. package/dist/defaults/src/integrations/tray/index.js +3 -3
  61. package/dist/defaults/src/main.js +3 -5
  62. package/dist/defaults/src/preload.js +3 -5
  63. package/dist/defaults/test/README.md +2 -2
  64. package/dist/gulp/main.js +9 -10
  65. package/dist/gulp/tasks/audit.js +7 -7
  66. package/dist/gulp/tasks/build-config.js +8 -8
  67. package/dist/gulp/tasks/bundle.js +16 -16
  68. package/dist/gulp/tasks/defaults.js +3 -3
  69. package/dist/gulp/tasks/distribute.js +2 -2
  70. package/dist/gulp/tasks/html.js +9 -9
  71. package/dist/gulp/tasks/package-quick.js +3 -3
  72. package/dist/gulp/tasks/package.js +3 -3
  73. package/dist/gulp/tasks/release.js +3 -3
  74. package/dist/gulp/tasks/sass.js +6 -6
  75. package/dist/gulp/tasks/serve.js +4 -4
  76. package/dist/hooks/notarize-artifacts.js +1 -1
  77. package/dist/hooks/notarize.js +1 -1
  78. package/dist/index.js +5 -8
  79. package/dist/lib/_environment-mixin.js +50 -0
  80. package/dist/lib/_lifecycle-mixin.js +45 -0
  81. package/dist/lib/analytics.js +33 -35
  82. package/dist/lib/app-state.js +14 -14
  83. package/dist/lib/auth-flow.js +18 -18
  84. package/dist/lib/auth-persistence.js +12 -12
  85. package/dist/lib/auth.js +421 -0
  86. package/dist/lib/auto-updater.js +49 -49
  87. package/dist/lib/context-menu.js +13 -13
  88. package/dist/lib/context.js +19 -19
  89. package/dist/lib/deep-link.js +34 -34
  90. package/dist/lib/fontawesome.js +5 -5
  91. package/dist/lib/ipc.js +4 -4
  92. package/dist/lib/menu.js +25 -25
  93. package/dist/lib/protocol.js +5 -5
  94. package/dist/lib/remote-config.js +22 -22
  95. package/dist/lib/remote-scripts.js +21 -21
  96. package/dist/lib/restart-manager/index.js +28 -28
  97. package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
  98. package/dist/lib/sign-helpers/sign-events.js +1 -1
  99. package/dist/lib/startup.js +18 -13
  100. package/dist/lib/storage.js +10 -10
  101. package/dist/lib/templating.js +16 -16
  102. package/dist/lib/theme.js +10 -10
  103. package/dist/lib/tray.js +27 -27
  104. package/dist/lib/usage.js +11 -11
  105. package/dist/lib/window-manager.js +26 -26
  106. package/dist/main.js +398 -483
  107. package/dist/preload.js +236 -176
  108. package/dist/renderer.js +417 -391
  109. package/dist/runner/job-started.js +1 -1
  110. package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
  111. package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
  112. package/dist/test/fixtures/consumer-app/src/main.js +5 -7
  113. package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
  114. package/dist/test/harness/boot-entry.js +22 -20
  115. package/dist/test/harness/main-entry.js +31 -30
  116. package/dist/test/harness/renderer-entry.js +5 -5
  117. package/dist/test/harness/renderer-preload.js +137 -141
  118. package/dist/test/index.js +10 -10
  119. package/dist/test/runner.js +2 -2
  120. package/dist/test/runners/boot.js +7 -6
  121. package/dist/test/runners/electron.js +3 -2
  122. package/dist/test/runners/render-event.js +2 -2
  123. package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
  124. package/dist/test/suites/boot/restart-manager.test.js +2 -2
  125. package/dist/test/suites/boot/storage-bundled.test.js +5 -5
  126. package/dist/test/suites/boot/theme.test.js +13 -13
  127. package/dist/test/suites/build/audit.test.js +1 -1
  128. package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
  129. package/dist/test/suites/build/boot-fixture.test.js +2 -2
  130. package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
  131. package/dist/test/suites/build/brand-scss.test.js +1 -1
  132. package/dist/test/suites/build/build-json-bake.test.js +1 -1
  133. package/dist/test/suites/build/cli.test.js +2 -2
  134. package/dist/test/suites/build/config-schema.test.js +5 -5
  135. package/dist/test/suites/build/defaults-scaffold.test.js +2 -2
  136. package/dist/test/suites/build/deploy-hook.test.js +3 -3
  137. package/dist/test/suites/build/ensure-target.test.js +2 -2
  138. package/dist/test/suites/build/env-delivery.test.js +2 -2
  139. package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
  140. package/dist/test/suites/build/exports.test.js +9 -8
  141. package/dist/test/suites/build/get-config.test.js +4 -4
  142. package/dist/test/suites/build/manifest-deps.test.js +1 -1
  143. package/dist/test/suites/build/merge-line-files.test.js +1 -1
  144. package/dist/test/suites/build/omega-shell.test.js +34 -2
  145. package/dist/test/suites/build/omega.test.js +350 -0
  146. package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
  147. package/dist/test/suites/build/runner.test.js +612 -5
  148. package/dist/test/suites/build/sentry.test.js +2 -2
  149. package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
  150. package/dist/test/suites/build/templating.test.js +3 -3
  151. package/dist/test/suites/build/test-stealth.test.js +7 -9
  152. package/dist/test/suites/build/url-helpers.test.js +55 -56
  153. package/dist/test/suites/build/validate-config.test.js +2 -2
  154. package/dist/test/suites/build/wave5-pins.test.js +2 -2
  155. package/dist/test/suites/main/analytics.test.js +59 -59
  156. package/dist/test/suites/main/app-state.test.js +66 -66
  157. package/dist/test/suites/main/auth-flow.test.js +41 -41
  158. package/dist/test/suites/main/auth-persistence.test.js +54 -43
  159. package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
  160. package/dist/test/suites/main/auth.test.js +336 -0
  161. package/dist/test/suites/main/auto-updater.test.js +134 -134
  162. package/dist/test/suites/main/boot-sequence.test.js +37 -49
  163. package/dist/test/suites/main/context-menu.test.js +51 -50
  164. package/dist/test/suites/main/context.test.js +25 -25
  165. package/dist/test/suites/main/deep-link.test.js +74 -74
  166. package/dist/test/suites/main/fontawesome.test.js +27 -27
  167. package/dist/test/suites/main/ipc.test.js +35 -35
  168. package/dist/test/suites/main/menu.test.js +101 -100
  169. package/dist/test/suites/main/protocol.test.js +19 -19
  170. package/dist/test/suites/main/remote-config.test.js +63 -63
  171. package/dist/test/suites/main/remote-scripts.test.js +103 -103
  172. package/dist/test/suites/main/request.test.js +71 -0
  173. package/dist/test/suites/main/restart-manager.test.js +33 -33
  174. package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
  175. package/dist/test/suites/main/startup.test.js +26 -26
  176. package/dist/test/suites/main/stealth-window.test.js +1 -1
  177. package/dist/test/suites/main/storage.test.js +25 -25
  178. package/dist/test/suites/main/theme.test.js +34 -34
  179. package/dist/test/suites/main/tray.test.js +79 -79
  180. package/dist/test/suites/main/url-helpers.test.js +133 -133
  181. package/dist/test/suites/main/usage.test.js +25 -25
  182. package/dist/test/suites/main/window-bounds.test.js +27 -27
  183. package/dist/test/suites/main/window-manager.test.js +44 -44
  184. package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
  185. package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
  186. package/dist/test/suites/renderer/round-trip.test.js +3 -3
  187. package/dist/test/suites/renderer/tooltips.test.js +15 -15
  188. package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +27 -7
  189. package/dist/test/utils/extended-mode-warning.js +1 -1
  190. package/dist/utils/boot-harness.js +56 -0
  191. package/dist/utils/mode-helpers.js +2 -15
  192. package/dist/utils/ship-keys.js +3 -3
  193. package/dist/utils/signing-status.js +51 -0
  194. package/dist/utils/test-events.js +7 -0
  195. package/dist/utils/test-stealth.js +6 -6
  196. package/dist/utils/url-helpers.js +52 -42
  197. package/dist/utils/user-agent.js +44 -0
  198. package/dist/vendor/account/engine.js +3 -3
  199. package/dist/vendor/account/index.js +14 -45
  200. package/dist/vendor/account/resolve-account.js +44 -0
  201. package/dist/vendor/account/schema.js +1 -1
  202. package/dist/vendor/account/user.js +99 -0
  203. package/dist/vendor/config/client-config.js +1 -1
  204. package/dist/vendor/config/environment.js +11 -30
  205. package/dist/vendor/config/index.js +13 -12
  206. package/dist/vendor/config/load.js +1 -2
  207. package/dist/vendor/config/platforms.js +1 -1
  208. package/dist/vendor/config/repo.js +24 -0
  209. package/dist/vendor/config/retired-keys.js +2 -2
  210. package/dist/vendor/config/schema.js +5 -8
  211. package/dist/vendor/config/site-global.js +2 -3
  212. package/dist/vendor/config/validate.js +1 -2
  213. package/dist/vendor/config/winback.js +1 -1
  214. package/dist/vendor/devkit/actions-secrets.js +1 -1
  215. package/dist/vendor/devkit/attach-log-file.js +1 -1
  216. package/dist/vendor/devkit/brand-version.js +162 -1
  217. package/dist/vendor/devkit/build-json.js +1 -1
  218. package/dist/vendor/devkit/cli-router.js +3 -4
  219. package/dist/vendor/devkit/defaults-engine.js +9 -11
  220. package/dist/vendor/devkit/deploy.js +64 -4
  221. package/dist/vendor/devkit/git-remote.js +78 -1
  222. package/dist/vendor/devkit/local.js +53 -3
  223. package/dist/vendor/devkit/lockfile.js +127 -0
  224. package/dist/vendor/devkit/merge-line-files.js +2 -3
  225. package/dist/vendor/devkit/pack-local.js +4 -7
  226. package/dist/vendor/devkit/preludes/origin-heal.js +35 -49
  227. package/dist/vendor/devkit/target-secrets.js +34 -45
  228. package/dist/vendor/devkit/test/runner-core.js +6 -6
  229. package/dist/vendor/monitoring/env.js +2 -2
  230. package/dist/vendor/monitoring/index.js +1 -1
  231. package/dist/vendor/monitoring/main.js +1 -1
  232. package/dist/vendor/monitoring/preload.js +1 -1
  233. package/dist/vendor/monitoring/renderer.js +1 -1
  234. package/docs/analytics.md +8 -8
  235. package/docs/app-state.md +19 -19
  236. package/docs/audit.md +4 -4
  237. package/docs/{client-bridge.md → auth.md} +88 -73
  238. package/docs/auto-updater.md +8 -8
  239. package/docs/boot-sequence.md +11 -6
  240. package/docs/build-system.md +1 -1
  241. package/docs/cdp-debugging.md +1 -1
  242. package/docs/common-mistakes.md +7 -7
  243. package/docs/config-schema.md +1 -1
  244. package/docs/context-menu.md +13 -13
  245. package/docs/context.md +11 -11
  246. package/docs/css.md +3 -9
  247. package/docs/deep-link.md +25 -25
  248. package/docs/environment-detection.md +16 -16
  249. package/docs/fontawesome.md +7 -5
  250. package/docs/hooks.md +8 -8
  251. package/docs/index.md +39 -28
  252. package/docs/ipc.md +10 -10
  253. package/docs/lib-modules.md +9 -9
  254. package/docs/logging.md +12 -14
  255. package/docs/menu.md +18 -18
  256. package/docs/releasing.md +4 -2
  257. package/docs/remote-config.md +9 -9
  258. package/docs/remote-scripts.md +12 -12
  259. package/docs/restart-manager.md +8 -8
  260. package/docs/runner.md +12 -10
  261. package/docs/sentry.md +4 -4
  262. package/docs/shared/analytics.md +1 -1
  263. package/docs/shared/brands.md +1 -1
  264. package/docs/shared/breaking-changes.md +79 -13
  265. package/docs/shared/config.md +24 -21
  266. package/docs/shared/deploys.md +30 -7
  267. package/docs/shared/local-dev.md +5 -3
  268. package/docs/shared/logging.md +1 -1
  269. package/docs/shared/monitoring.md +5 -5
  270. package/docs/shared/testing.md +2 -2
  271. package/docs/shared/theming.md +1 -1
  272. package/docs/shared/translation.md +19 -10
  273. package/docs/signing.md +1 -1
  274. package/docs/startup.md +16 -16
  275. package/docs/storage.md +11 -11
  276. package/docs/templating.md +3 -3
  277. package/docs/test-boot-layer.md +12 -12
  278. package/docs/test-framework.md +17 -17
  279. package/docs/themes.md +7 -7
  280. package/docs/tooltips.md +2 -2
  281. package/docs/tray.md +31 -31
  282. package/docs/usage.md +7 -7
  283. package/docs/verts.md +1 -1
  284. package/docs/windows.md +22 -22
  285. package/package.json +3 -4
  286. package/dist/lib/client-bridge.js +0 -374
  287. package/dist/lib/logger.js +0 -4
  288. package/dist/test/suites/build/manager.test.js +0 -213
  289. package/dist/test/suites/main/client-bridge.test.js +0 -262
package/docs/context.md CHANGED
@@ -2,19 +2,19 @@
2
2
 
3
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
4
 
5
- Populated asynchronously during `manager.initialize()`.
5
+ Populated asynchronously during `omega.initialize()`.
6
6
 
7
7
  ## Shape
8
8
 
9
9
  ```js
10
- manager.context.geolocation = {
10
+ omega.context.geolocation = {
11
11
  ip: '203.0.113.42', // async-fetched via ipify
12
12
  country: null, // future enhancement
13
13
  region: null,
14
14
  city: null,
15
15
  };
16
16
 
17
- manager.context.client = {
17
+ omega.context.client = {
18
18
  userAgent: 'Mozilla/5.0 ...', // app.userAgentFallback
19
19
  locale: 'en-US', // app.getLocale()
20
20
  platform: 'darwin', // os.platform()
@@ -22,15 +22,15 @@ manager.context.client = {
22
22
  mobile: false, // always false on @omega.js/desktop (desktop framework)
23
23
  };
24
24
 
25
- manager.context.session = {
25
+ omega.context.session = {
26
26
  id: '<uuid>', // fresh per launch (crypto.randomUUID)
27
27
  startTime: '2026-05-08T...', // ISO at boot
28
28
  deviceId: '<uuid or MAC>', // stable per-machine
29
29
  };
30
30
 
31
- manager.context.app = {
32
- version: '1.2.3', // manager.getVersion()
33
- environment: 'production', // manager.getEnvironment()
31
+ omega.context.app = {
32
+ version: '1.2.3', // omega.getVersion()
33
+ environment: 'production', // omega.getEnvironment()
34
34
  isPackaged: true, // app.isPackaged
35
35
  };
36
36
  ```
@@ -54,9 +54,9 @@ Failure mode: a failed ipify fetch leaves the previous cached value untouched. T
54
54
  ## API
55
55
 
56
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
57
+ omega.context.geolocation.ip // direct read
58
+ omega.context.session.deviceId // direct read
59
+ const snap = omega.context.toJSON(); // structured-cloneable snapshot
60
60
  ```
61
61
 
62
62
  Renderer:
@@ -71,7 +71,7 @@ console.log(snap.session.deviceId);
71
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
72
 
73
73
  ```js
74
- const country = manager.context.geolocation.country
74
+ const country = omega.context.geolocation.country
75
75
  || assistant.request.geolocation.country // @omega.js/backend
76
76
  || omega.context.geolocation.country;
77
77
  ```
package/docs/css.md CHANGED
@@ -32,7 +32,7 @@ Compiles to `dist/assets/css/main.bundle.css` (Bootstrap + classy theme + your g
32
32
 
33
33
  ## Theme integration
34
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.
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 `omega.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
36
 
37
37
  ## Icon presentation
38
38
 
@@ -69,15 +69,9 @@ Emit this markup in the window's HTML:
69
69
  </div>
70
70
  ```
71
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:
72
+ The renderer instance wires the behavior during `omega.initialize()` (the vendored `__main_assets__/js/core/app-shell.js`, the same module @omega.js/web runs), so a view that renders the markup needs no script of its own. The API is `omega.shell` (`isCollapsed`, `isOpen`, `setCollapsed`, `setOpen`, `toggleCollapsed`, `toggleOpen`).
73
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).
74
+ 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. Add `.omega-shell--locked` when `main` should never scroll (the page manages its own interior scroll).
81
75
 
82
76
  ## Bootstrap-first convention
83
77
 
package/docs/deep-link.md CHANGED
@@ -10,7 +10,7 @@ Cross-platform deep-link handling that's simple to use and hard to get wrong. @o
10
10
  }
11
11
  ```
12
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.
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 `omega.deepLink.dispatch(url)` instead.
14
14
 
15
15
  ## How it works (so you don't have to think about it)
16
16
 
@@ -20,15 +20,15 @@ Cross-platform deep-link handling that's simple to use and hard to get wrong. @o
20
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
21
  | **Linux** | Same as Windows | Same as Windows |
22
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.
23
+ @omega.js/desktop handles all of these and dispatches them through the same `omega.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
24
 
25
25
  ## Public API
26
26
 
27
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
28
+ omega.deepLink.on(pattern, handler) // register a handler. Returns unsubscribe fn.
29
+ omega.deepLink.off(pattern, handler)
30
+ omega.deepLink.dispatch(url) // manually fire (testing, custom triggers)
31
+ omega.deepLink.getColdStartUrl() // the URL the app was launched with, or null
32
32
  ```
33
33
 
34
34
  ## Patterns
@@ -43,7 +43,7 @@ manager.deepLink.getColdStartUrl() // the URL the app was launched with, o
43
43
  ## Handler signature
44
44
 
45
45
  ```js
46
- manager.deepLink.on('user/profile/:id', (ctx) => {
46
+ omega.deepLink.on('user/profile/:id', (ctx) => {
47
47
  ctx.url // 'myapp://user/profile/42?ref=tray'
48
48
  ctx.scheme // 'myapp'
49
49
  ctx.route // 'user/profile/42'
@@ -63,16 +63,16 @@ manager.deepLink.on('user/profile/:id', (ctx) => {
63
63
 
64
64
  | Route | Default behavior |
65
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')` |
66
+ | `auth/token` | Calls `omega.auth.handleToken(query.authToken)`: the receiving end of the `omega.openAuthFlow()` sign-in round-trip. MODERN shape only (`?authToken=`, what the website's token page sends); other formats (`?token=`, `?payload=`) 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` | `omega.windows.show(query.window || 'main')` |
68
68
  | `app/quit` | `app.quit()` |
69
69
 
70
70
  ### Overriding a built-in
71
71
 
72
72
  ```js
73
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()) {
74
+ omega.deepLink.on('app/show', (ctx) => {
75
+ if (ctx.query.window === 'admin' && !omega.appState.isAdminUser()) {
76
76
  showError('not authorized');
77
77
  ctx.handled = true; // suppress built-in
78
78
  return;
@@ -96,9 +96,9 @@ Setting `ctx.handled = true` in any handler stops the cascade. Within a single t
96
96
  ### Route to a window + send IPC
97
97
 
98
98
  ```js
99
- manager.deepLink.on('user/profile/:id', (ctx) => {
100
- manager.windows.show('main');
101
- manager.windows.get('main').webContents.send('navigate', {
99
+ omega.deepLink.on('user/profile/:id', (ctx) => {
100
+ omega.windows.show('main');
101
+ omega.windows.get('main').webContents.send('navigate', {
102
102
  to: `/profile/${ctx.params.id}`,
103
103
  });
104
104
  });
@@ -107,17 +107,17 @@ manager.deepLink.on('user/profile/:id', (ctx) => {
107
107
  ### Catch-all logger
108
108
 
109
109
  ```js
110
- manager.deepLink.on('*', (ctx) => {
111
- manager.logger.warn(`Unrouted deep link: ${ctx.url}`);
110
+ omega.deepLink.on('*', (ctx) => {
111
+ omega.logger.warn(`Unrouted deep link: ${ctx.url}`);
112
112
  });
113
113
  ```
114
114
 
115
115
  ### Cold-start branching
116
116
 
117
117
  ```js
118
- const coldUrl = manager.deepLink.getColdStartUrl();
118
+ const coldUrl = omega.deepLink.getColdStartUrl();
119
119
  if (coldUrl) {
120
- manager.logger.log(`Launched from deep link: ${coldUrl}`);
120
+ omega.logger.log(`Launched from deep link: ${coldUrl}`);
121
121
  // appState.launchedFromDeepLink() is also set automatically
122
122
  }
123
123
  ```
@@ -127,13 +127,13 @@ if (coldUrl) {
127
127
  ```js
128
128
  tray.item({
129
129
  label: 'Open Profile',
130
- click: () => manager.deepLink.dispatch('myapp://user/profile/me'),
130
+ click: () => omega.deepLink.dispatch('myapp://user/profile/me'),
131
131
  });
132
132
  ```
133
133
 
134
134
  ## Boot queueing
135
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.
136
+ Every dispatch is held until `omega.initialize()` completes (main.js calls `deepLink.markOmegaReady()` 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 `omega.auth` has Firebase up; it queues and drains the moment the instance is ready. Warm-start dispatches on a running app pass straight through.
137
137
 
138
138
  ## Single-instance behavior
139
139
 
@@ -141,7 +141,7 @@ Every dispatch is held until `manager.initialize()` completes (main.js calls `de
141
141
 
142
142
  1. The new instance loses the lock.
143
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`).
144
+ 3. The new instance's `omega.initialize()` halts (after `protocol.hasSingleInstanceLock() === false`): the duplicate quits and its promise never settles.
145
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
146
  5. @omega.js/desktop extracts the deep-link URL from that argv and dispatches normally — but as `source: 'warm-start'`.
147
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).
@@ -156,10 +156,10 @@ Never parse the event's own `argv` for flags: Chromium re-serializes it (switche
156
156
 
157
157
  ## Linking with `appState`
158
158
 
159
- When a deep link is detected at cold-start, @omega.js/desktop calls `manager.appState.setLaunchedFromDeepLink(true)`. This means:
159
+ When a deep link is detected at cold-start, @omega.js/desktop calls `omega.appState.setLaunchedFromDeepLink(true)`. This means:
160
160
 
161
161
  ```js
162
- if (manager.appState.launchedFromDeepLink()) {
162
+ if (omega.appState.launchedFromDeepLink()) {
163
163
  // user clicked a link to launch the app — handle differently than a tray click or login launch
164
164
  }
165
165
  ```
@@ -171,7 +171,7 @@ Combine with `appState.isFirstLaunch()` to detect "first launch via deep link" (
171
171
  The dispatch pipeline is unit-testable without actually triggering an OS event:
172
172
 
173
173
  ```js
174
- manager.deepLink.dispatch('myapp://auth/token?token=test');
174
+ omega.deepLink.dispatch('myapp://auth/token?token=test');
175
175
  // Fires source='manual'. Handlers run synchronously.
176
176
  ```
177
177
 
@@ -180,7 +180,7 @@ See `src/test/suites/main/deep-link.test.js` for the full coverage.
180
180
  ## Implementation notes
181
181
 
182
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).
183
+ - OS scheme registration is gated on `omega.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
184
  - On Windows/Linux, scheme registration uses `app.setAsDefaultProtocolClient(scheme, process.execPath, [process.cwd()])` so `app.exe scheme://...` style invocations route argv correctly.
185
185
  - macOS open-url events that arrive before `whenReady` are queued internally and drained on `deepLink.initialize()`.
186
186
  - Argv extraction walks backward from the end of argv (where the URL typically sits) and matches against registered schemes.
@@ -3,25 +3,25 @@
3
3
  `getEnvironment()` returns exactly ONE of three mutually-exclusive, exhaustive values:
4
4
 
5
5
  ```javascript
6
- Manager.getEnvironment() // 'development' | 'testing' | 'production'
6
+ omega.getEnvironment() // 'development' | 'testing' | 'production'
7
7
 
8
- Manager.isDevelopment() // true ONLY in development
9
- Manager.isTesting() // true ONLY in testing
10
- Manager.isProduction() // true ONLY in production
8
+ omega.isDevelopment() // true ONLY in development
9
+ omega.isTesting() // true ONLY in testing
10
+ omega.isProduction() // true ONLY in production
11
11
  ```
12
12
 
13
13
  **ONE input, and no default** ([#817](https://github.com/Omega-JS-Stack/omega/issues/817)). `getEnvironment()` reads the `OMEGA_ENVIRONMENT` variable in Node, and the baked `OMEGA_BUILD_JSON.config.environment` in a renderer (which has no `process.env`). Nothing else is consulted: the `app.isPackaged`, `config.em.environment`, `OMEGA_BUILD_MODE` and `NODE_ENV` sniffs are gone, and a context with neither input **throws**, naming the variable. The old default here was `production`, so a plain `npm start` bundled itself as a production artifact while @omega.js/extension's copy of the same function answered `development` from the same inputs.
14
14
 
15
- **One implementation, shared with every sibling framework.** The four calls are `@omega.js/config`'s [environment.js](../../config/src/environment.js), the module @omega.js/extension, @omega.js/web, @omega.js/backend and @omega.js/client all answer from. @omega.js/desktop has four Manager entry points (main / renderer / preload / build); [src/utils/mode-helpers.js](../src/utils/mode-helpers.js) re-exports the shared four beside desktop's own `getVersion()` and mixes them into each via `attachTo(Manager)`, available as both prototype methods (`manager.isTesting()`) and statics (`Manager.isTesting()`).
15
+ **One implementation, shared with every sibling framework.** The four calls are `@omega.js/config`'s [environment.js](../../config/src/environment.js), the module @omega.js/extension, @omega.js/web, @omega.js/backend and @omega.js/client all answer from. @omega.js/desktop has four entry points (main / renderer / preload / build); [src/utils/mode-helpers.js](../src/utils/mode-helpers.js) re-exports the shared four beside desktop's own `getVersion()`. The build module exports them as plain functions, and every process's `omega` carries them as methods.
16
16
 
17
17
  ```javascript
18
- manager.getEnvironment() // same answer in main / renderer / preload / build
19
- Manager.isTesting() // static form, for build-time scripts
18
+ omega.getEnvironment() // same answer in main / renderer / preload
19
+ require('@omega.js/desktop/build').isTesting() // the build module, for build-time scripts
20
20
  ```
21
21
 
22
22
  **Who sets the input.** [src/build.js](../src/build.js) names it at LOAD, from the lane: `OMEGA_BUILD_MODE` (which `omega build` / `package` / `publish` / `release` and the boot runner's staged build all set) is `production` and WINS over an inherited value, so a production build spawned from a test run still bakes production; otherwise a lane that already named one keeps it (the test runners spawn their children naming `testing`), and a bare dev boot is `development`. The electron app that lane spawns inherits the variable. A PACKAGED app has no parent lane, so [src/main.js](../src/main.js) names it from the word the build baked into the artifact: that is a FALLBACK for the context with no input, never an override ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)). A process that already carries `OMEGA_ENVIRONMENT` keeps it, which is why a test lane that boots a production artifact still answers `testing` inside it.
23
23
 
24
- **The renderer gets the running word too.** A page has no `process`, so its Manager reads input 2, the baked `config.environment`, which is the word the BUILD was for. Those agree everywhere except a lane that boots a production artifact, so the preload (a Node context, it has the variable) exposes it on `window.desktop.environment` and [src/renderer.js](../src/renderer.js) applies it over the baked word at `initialize()`. Same precedence, one context removed: the running environment first, the bake second. No second signal exists.
24
+ **The renderer gets the running word too.** A page has no `process`, so its `omega` reads input 2, the baked `config.environment`, which is the word the BUILD was for. Those agree everywhere except a lane that boots a production artifact, so the preload (a Node context, it has the variable) exposes it on `window.desktop.environment` and [src/renderer.js](../src/renderer.js) applies it over the baked word at `initialize()`. Same precedence, one context removed: the running environment first, the bake second. No second signal exists.
25
25
 
26
26
  **The three checks are mutually exclusive**: exactly one is true. `isDevelopment()` is **false** during testing, and `isProduction()` is a real positive check (it is NOT `!isDevelopment()`).
27
27
 
@@ -52,14 +52,14 @@ if (isDevelopment() || isTesting()) { /* localhost URL, isolate userData, suppre
52
52
  ## URL helpers
53
53
 
54
54
  ```javascript
55
- Manager.getApiUrl() // the app's API URL — the SSOT for calling the backend
55
+ omega.getApiUrl() // the app's API URL: the SSOT for calling the backend
56
56
  ```
57
57
 
58
58
  `getApiUrl()` / `getFunctionsUrl()` / `getWebsiteUrl()` resolve to **local** URLs (from the baked dev map, whose floor is the classic hosting / functions / website numbers) in development OR testing, and to production (`https://api.<brand.url host>` etc.) otherwise. They route through `this.getEnvironment()`, so they're correct everywhere without an argument: call them directly. Pass an explicit `env` arg (`getApiUrl('production')`) only to force a specific environment regardless of the current one, rarely needed, and mainly used by tests to pin a specific environment's mapping.
59
59
 
60
- `getAuthUrl()` builds the **sign-in URL that round-trips an auth token back to the app**: `<site>/signin?authReturnUrl=<site>/token?authReturnUrl=<brand.id>://auth/token`, where `<site>` is `getWebsiteUrl()` (same env split). The UJM website's `/signin` page logs the user in (or bounces straight through if already signed in), its `/token` page mints a Firebase custom token via the backend, and the final redirect (`?authToken=<token>` — the ONE shape; legacy-app formats live in UJM, not @omega.js/desktop) deep-links the token into the app's built-in `auth/token` route → `omega.handleAuthToken()` → `signInWithCustomToken`. Use it for EVERY "Sign in" affordance an app exposes — never link the bare `/signin` page, which strands the login in the browser. Requires `brand.id` (the deep-link scheme) in config; throws when missing. The optional second arg `getAuthUrl(env, returnUrl)` overrides the chain's final hop — that's how `lib/auth-flow.js` swaps in its dev loopback return.
60
+ `getAuthUrl()` builds the **sign-in URL that round-trips an auth token back to the app**: `<site>/signin?authReturnUrl=<site>/token?authReturnUrl=<brand.id>://auth/token`, where `<site>` is `getWebsiteUrl()` (same env split). The website's `/signin` page logs the user in (or bounces straight through if already signed in), its `/token` page mints a Firebase custom token via the backend, and the final redirect (`?authToken=<token>`, the ONE shape) deep-links the token into the app's built-in `auth/token` route → `omega.auth.handleToken()` → `signInWithCustomToken`. Use it for EVERY "Sign in" affordance an app exposes; never link the bare `/signin` page, which strands the login in the browser. Requires `brand.id` (the deep-link scheme) in config; throws when missing. The optional second arg `getAuthUrl(env, returnUrl)` overrides the chain's final hop: that's how `lib/auth-flow.js` swaps in its dev loopback return.
61
61
 
62
- **Apps should launch the flow through `manager.openAuthFlow()` (main process), not by opening `getAuthUrl()` themselves**: production opens `getAuthUrl()` externally as-is (the OS routes the custom scheme back), while dev/test — where the scheme is NOT OS-registered (protocol.js registers only in production, and macOS can't runtime-register schemes missing from the bundle's Info.plist) — swap the final hop for a one-shot, nonce-checked loopback HTTP listener (RFC 8252 §7.3) that feeds the token into the SAME deep-link pipeline. Sign-in always happens in the user's REAL default browser (their existing session/SSO), never an embedded window. Requires @omega.js/client ≥ 4.3.4 on the website (`isValidRedirectUrl` accepts loopback hosts while the SITE runs in dev). See [src/lib/auth-flow.js](../src/lib/auth-flow.js).
62
+ **Apps should launch the flow through `omega.openAuthFlow()` (main process), not by opening `getAuthUrl()` themselves**: production opens `getAuthUrl()` externally as-is (the OS routes the custom scheme back), while dev/test, where the scheme is NOT OS-registered (protocol.js registers only in production, and macOS can't runtime-register schemes missing from the bundle's Info.plist), swap the final hop for a one-shot, nonce-checked loopback HTTP listener (RFC 8252 §7.3) that feeds the token into the SAME deep-link pipeline. Sign-in always happens in the user's REAL default browser (their existing session/SSO), never an embedded window. Requires @omega.js/client ≥ 4.3.4 on the website (`isValidRedirectUrl` accepts loopback hosts while the SITE runs in dev). See [src/lib/auth-flow.js](../src/lib/auth-flow.js).
63
63
 
64
64
  All three local helpers resolve from whichever channel the process has: the `OMEGA_*_PORT` env vars (the CLI that booted the stack publishes them), then the `dev` map the bundle baked into `OMEGA_BUILD_JSON` (a packaged main process has no parent env, so a bumped emulator port reaches it only this way, [#745](https://github.com/Omega-JS-Stack/omega/issues/745)). There is no third step: the classic numbers used to be hand-typed under them, and they are gone ([#834](https://github.com/Omega-JS-Stack/omega/issues/834)).
65
65
 
@@ -73,15 +73,15 @@ The classics still reach these helpers, from the ONE place they are defined: the
73
73
 
74
74
  The first two rows are port chains: each cell names a port, and the helper builds the URL around it. The website row is an ORIGIN chain ([#747](https://github.com/Omega-JS-Stack/omega/issues/747)): the baked `dev.origin` the live website published carries scheme, host AND port, so it is the complete fact and outranks the port cell; only when it is absent does a port compose an origin, over **https**, because `omega dev` fronts its public port with the mkcert proxy by default and a port number alone can never say the scheme. Whenever the website published an origin, that is the same answer `@omega.js/client`'s `getDevWebsiteOrigin()` gives every other surface ([#262](https://github.com/Omega-JS-Stack/omega/issues/262)), and `getAuthUrl()` inherits it by construction.
75
75
 
76
- A resolved `OMEGA_HTTPS_PORT` (or a baked `dev.ports.https`) means `omega serve`'s mkcert proxy is up, so the api URL is https. That is the same chain @omega.js/extension's `getApiUrl()` walks, and the same one client-bridge uses for the auth emulator port (`OMEGA_AUTH_PORT` → `dev.ports.auth` → throw, [client-bridge.md](client-bridge.md)).
76
+ A resolved `OMEGA_HTTPS_PORT` (or a baked `dev.ports.https`) means `omega serve`'s mkcert proxy is up, so the api URL is https. That is the same chain @omega.js/extension's `getApiUrl()` walks, and the same one `omega.auth` uses for the auth emulator port (`OMEGA_AUTH_PORT` → `dev.ports.auth` → throw, [auth.md](auth.md)).
77
77
 
78
78
  Resolving local in test mode is required because tests hit the local emulator — without it, the app (and tests calling `getApiUrl()`) would leak to the live production server.
79
79
 
80
- > The URL helpers live in [src/utils/url-helpers.js](../src/utils/url-helpers.js) and depend on `this.getEnvironment()` (from mode-helpers.js) being mixed in — both `attachTo` calls run at the bottom of every Manager entry point.
80
+ > The URL helpers live in [src/utils/url-helpers.js](../src/utils/url-helpers.js) as plain functions of the instance (`getApiUrl(omega, environment)`), reading its `getEnvironment()`; each process class calls them from its own methods.
81
81
 
82
82
  ## Where they live
83
83
 
84
- Source: [src/utils/mode-helpers.js](../src/utils/mode-helpers.js) for `getEnvironment()` + `is*()` + `getVersion()`; [src/utils/url-helpers.js](../src/utils/url-helpers.js) for the URL builders. Each module exposes the functions plus an `attachTo(Manager)` mixin. Attached at the bottom of all four Manager files: [main.js](../src/main.js), [renderer.js](../src/renderer.js), [preload.js](../src/preload.js), [build.js](../src/build.js) — mode-helpers first (so `getEnvironment` exists), then url-helpers.
84
+ Source: [src/utils/mode-helpers.js](../src/utils/mode-helpers.js) for `getEnvironment()` + `is*()` + `getVersion()`; [src/utils/url-helpers.js](../src/utils/url-helpers.js) for the URL builders. Both modules export plain functions. [build.js](../src/build.js) exports the mode helpers as they are; the three process classes, [main.js](../src/main.js) (the methods mixed in from [lib/_environment-mixin.js](../src/lib/_environment-mixin.js)), [preload.js](../src/preload.js) and [renderer.js](../src/renderer.js), call them from their own methods (the renderer takes the environment four and `getApiUrl()` / `getFunctionsUrl()` from @omega.js/client's base class it extends).
85
85
 
86
86
  ## How detection works
87
87
 
@@ -89,7 +89,7 @@ Source: [src/utils/mode-helpers.js](../src/utils/mode-helpers.js) for `getEnviro
89
89
  ([#817](https://github.com/Omega-JS-Stack/omega/issues/817)):
90
90
 
91
91
  1. **`process.env.OMEGA_ENVIRONMENT`**, wherever this context has a `process` (main, preload, build-time Node).
92
- 2. **The baked `config.environment`** off the Manager the call is made on, for a renderer, which has none. It is the build fact every OMEGA surface spells the same way ([#896](https://github.com/Omega-JS-Stack/omega/issues/896)). The preload hands the running word across to the renderer when the two differ, so this step answers the artifact's own build only when no lane named one ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)).
92
+ 2. **The baked `config.environment`** off the `omega` the call is made on, for a renderer, which has none. It is the build fact every OMEGA surface spells the same way ([#896](https://github.com/Omega-JS-Stack/omega/issues/896)). The preload hands the running word across to the renderer when the two differ, so this step answers the artifact's own build only when no lane named one ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)).
93
93
  3. **Neither** is a loud error naming `OMEGA_ENVIRONMENT`. There is no default, because the four framework copies this replaced each had one and they disagreed.
94
94
 
95
95
  The lanes above supply that input, and the whole table of who names what lives in
@@ -97,7 +97,7 @@ The lanes above supply that input, and the whole table of who names what lives i
97
97
 
98
98
  ## Adding a new helper
99
99
 
100
- Write the function in a `src/utils/<topic>-helpers.js` module, expose `attachTo(Manager)`, then call `attachTo` at the bottom of all four Manager files. Don't define helpers on individual Manager prototypes — that path leads to duplicated semantics (the old `getEnvironment` collision between main.js and build.js). For anything environment-derived, derive from `getEnvironment()` rather than reading `process.env` / `app.*` directly, so there is one source of truth and no chance of drift.
100
+ Write the function in a `src/utils/<topic>-helpers.js` module, export it from [build.js](../src/build.js), and call it from a method on each process class that needs it. Don't define a helper's logic inside one process class: that path leads to duplicated semantics. For anything environment-derived, derive from `getEnvironment()` rather than reading `process.env` / `app.*` directly, so there is one source of truth and no chance of drift.
101
101
 
102
102
  ## Why this matters
103
103
 
@@ -35,7 +35,7 @@ drift on how an icon name resolves or what the served SVG looks like.
35
35
  `metadata/icon-families.json` for aliases (`search` → `magnifying-glass`).
36
36
  Declared dependencies ride into packaged apps automatically (fs reads
37
37
  through the asar transparently).
38
- - **Main lib** (`lib/fontawesome.js`) — `manager.fontawesome.get(name, style)`
38
+ - **Main lib** (`lib/fontawesome.js`): `omega.fontawesome.get(name, style)`
39
39
  resolves an icon to its SVG string (`null` for unknown names — never
40
40
  throws). Lookups are slug-sanitized via icon-core (the IPC channel can
41
41
  never read outside the icon directories) and cached per app run. Serves
@@ -61,11 +61,13 @@ drift on how an icon name resolves or what the served SVG looks like.
61
61
  ## Minimal surfaces
62
62
 
63
63
  The auto-render is wired by `initialize()`. A renderer that deliberately skips
64
- the full init (no @omega.js/client / auth — e.g. a lightweight popover overlay) can
65
- enable JUST the icon pipeline:
64
+ `initialize()` (e.g. a lightweight popover overlay with no auth) can enable JUST
65
+ the icon pipeline on the same instance:
66
66
 
67
67
  ```js
68
- new (require('@omega.js/desktop/renderer'))().enableFontAwesome();
68
+ import omega from '@omega.js/desktop/renderer';
69
+
70
+ omega.enableFontAwesome();
69
71
  ```
70
72
 
71
73
  ## Supplying Font Awesome Pro (C4 cp111)
@@ -88,7 +90,7 @@ own **prod dependency** so the set ships inside the asar.
88
90
  `window.desktop.fontawesome.get()` and swap yourself.
89
91
  - **Free set = solid + regular + brands.** Pro styles (light/duotone/sharp)
90
92
  need a supplied Pro set (above); otherwise
91
- `manager.fontawesome.get(name, 'duotone')` returns `null`.
93
+ `omega.fontawesome.get(name, 'duotone')` returns `null`.
92
94
  - **Updating the set** — bump the `@fortawesome/fontawesome-free` dependency
93
95
  (or reinstall/refresh the brand's Pro supply).
94
96
 
package/docs/hooks.md CHANGED
@@ -6,7 +6,7 @@ Consumers can inject custom logic at well-defined points without forking @omega.
6
6
 
7
7
  1. @omega.js/desktop scaffolds empty hook files into `<consumer>/hooks/**/*.js` on every verb (`ensureTarget()`).
8
8
  2. At each lifecycle point, @omega.js/desktop checks for the file. If it exists, @omega.js/desktop loads + invokes it. If not, no-op.
9
- 3. The hook signature is `async (ctx) => { ... }`. Whatever it returns is awaited but ignored.
9
+ 3. The hook signature is `async (ctx) => { ... }`, with `ctx` the ONE hook-argument shape every OMEGA framework passes, `{ build, projectRoot, mode }`: `build` is the build module (`require('@omega.js/desktop/build')`, one plain object of functions: `getConfig()`, `getPackage()`, `getRootPath()`, ...). Whatever it returns is awaited but ignored.
10
10
  4. **Failure semantics:**
11
11
  - File missing entirely → logged informationally (`hook "<name>" not present at ... — skipping.`), build continues.
12
12
  - File exists but fails to load (syntax error, etc.) → **throws**, build fails.
@@ -19,11 +19,11 @@ Consumers can inject custom logic at well-defined points without forking @omega.
19
19
 
20
20
  | Hook file | When it runs | `ctx` shape |
21
21
  |---|---|---|
22
- | `hooks/build/pre.js` | Before the build pipeline runs (`defaults` → `distribute` → `bundle` ...) | `{ manager, projectRoot, mode }` |
23
- | `hooks/build/post.js` | After the build pipeline finishes, before `electron-builder` packages anything | `{ manager, projectRoot, mode }` |
24
- | `hooks/release/pre.js` | Before `electron-builder build --publish always` | `{ manager, projectRoot, mode }` |
25
- | `hooks/release/post.js` | After the release publishes | `{ manager, projectRoot, mode }` |
26
- | `hooks/deploy/pre.js` | Inside `omega deploy`, after the local scaffold and before the network precheck, on both lanes (the dispatch and `--direct`); a dry run skips it, because a hook may act on the world ([#900](https://github.com/Omega-JS-Stack/omega/issues/900): the playground's prunes its release family down to the newest, so two releases stay live; the VERSION comes from `omega bump` at the brand root, [#869](https://github.com/Omega-JS-Stack/omega/issues/869), never from a hook) | `{ manager, projectRoot, mode: 'production' }` |
22
+ | `hooks/build/pre.js` | Before the build pipeline runs (`defaults` → `distribute` → `bundle` ...) | `{ build, projectRoot, mode }` |
23
+ | `hooks/build/post.js` | After the build pipeline finishes, before `electron-builder` packages anything | `{ build, projectRoot, mode }` |
24
+ | `hooks/release/pre.js` | Before `electron-builder build --publish always` | `{ build, projectRoot, mode }` |
25
+ | `hooks/release/post.js` | After the release publishes | `{ build, projectRoot, mode }` |
26
+ | `hooks/deploy/pre.js` | Inside `omega deploy`, after the local scaffold and before the network precheck, on both lanes (the dispatch and `--direct`); a dry run skips it, because a hook may act on the world ([#900](https://github.com/Omega-JS-Stack/omega/issues/900): the playground's prunes its release family down to the newest, so two releases stay live; the VERSION comes from `omega bump` at the brand root, [#869](https://github.com/Omega-JS-Stack/omega/issues/869), never from a hook) | `{ build, projectRoot, mode: 'production' }` |
27
27
  | `hooks/notarize/post.js` | After @omega.js/desktop's built-in macOS notarization completes (extension only — @omega.js/desktop's notarize is the real entrypoint) | electron-builder afterSign context |
28
28
 
29
29
  `mode` is `'production'` when `OMEGA_BUILD_MODE=true`, else `'development'`. A deploy hook always reads `'production'`: the verb runs outside a build, and what it is about to publish is a release.
@@ -32,7 +32,7 @@ Consumers can inject custom logic at well-defined points without forking @omega.
32
32
 
33
33
  - **Notarize specifically:** the consumer's `hooks/notarize/post.js` is **never** the electron-builder afterSign entrypoint. @omega.js/desktop's `gulp/build-config` injects `afterSign:` pointing at @omega.js/desktop's real notarize implementation (resolved via `require.resolve('@omega.js/desktop/hooks/notarize')`). @omega.js/desktop's real notarize calls into the consumer's `hooks/notarize/post.js` as a final post-step. So the consumer can never accidentally break notarization by editing the file — the file can be empty, malformed, or missing entirely and the app still notarizes correctly.
34
34
  - **Why no `hooks/notarize/pre.js`?** electron-builder's `afterSign` hook is the only signing-related extension point we control. Anything that would belong in a "pre-notarize" step belongs either in `hooks/release/pre.js` (whole-release-level prep, runs before the gulp release task), or in electron-builder's own `afterPack` / `afterAllArtifactBuild` configuration (per-artifact mutation). If you have a real use case that doesn't fit either, file an issue.
35
- - **Build/release hooks:** standard before/after lifecycle pattern. Same shape as Ultimate Jekyll Manager's hook system.
35
+ - **Build/release hooks:** standard before/after lifecycle pattern, the same `ctx` @omega.js/extension hands its hooks.
36
36
 
37
37
  ## Examples
38
38
 
@@ -40,7 +40,7 @@ Consumers can inject custom logic at well-defined points without forking @omega.
40
40
 
41
41
  ```js
42
42
  // hooks/release/post.js
43
- module.exports = async ({ manager, projectRoot }) => {
43
+ module.exports = async ({ build, projectRoot }) => {
44
44
  const pkg = require(`${projectRoot}/package.json`);
45
45
  const url = process.env.SLACK_WEBHOOK_URL;
46
46
  if (!url) return;