@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.
Files changed (345) hide show
  1. package/README.md +53 -48
  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-run.js +4 -1
  26. package/dist/cli.js +3 -3
  27. package/dist/commands/build.js +2 -2
  28. package/dist/commands/cdp/capture.js +2 -2
  29. package/dist/commands/cdp/client.js +1 -1
  30. package/dist/commands/cdp/quit.js +2 -2
  31. package/dist/commands/cdp/relaunch.js +2 -2
  32. package/dist/commands/cdp/theme.js +1 -1
  33. package/dist/commands/cdp.js +1 -1
  34. package/dist/commands/clean.js +4 -5
  35. package/dist/commands/deploy.js +4 -4
  36. package/dist/commands/dev.js +25 -0
  37. package/dist/commands/finalize-release.js +4 -4
  38. package/dist/commands/launch.js +2 -2
  39. package/dist/commands/lib/deploy-precheck.js +3 -3
  40. package/dist/commands/lib/ensure-target.js +18 -23
  41. package/dist/commands/lib/migrate.js +17 -0
  42. package/dist/commands/logs.js +1 -1
  43. package/dist/commands/package.js +2 -2
  44. package/dist/commands/publish.js +2 -2
  45. package/dist/commands/release.js +4 -4
  46. package/dist/commands/runner.js +11 -11
  47. package/dist/commands/sign-windows.js +5 -5
  48. package/dist/commands/test.js +8 -8
  49. package/dist/commands/update.js +7 -6
  50. package/dist/commands/validate-certs.js +4 -4
  51. package/dist/commands/version.js +3 -3
  52. package/dist/defaults/.github/workflows/build.yml +18 -18
  53. package/dist/defaults/_.gitignore +0 -2
  54. package/dist/defaults/_mas/README.md +3 -3
  55. package/dist/defaults/config/certs/README.md +1 -1
  56. package/dist/defaults/config/omega.json5 +43 -43
  57. package/dist/defaults/docs/README.md +3 -3
  58. package/dist/defaults/gulpfile.js +1 -1
  59. package/dist/defaults/hooks/build/post.js +2 -2
  60. package/dist/defaults/hooks/build/pre.js +2 -2
  61. package/dist/defaults/hooks/deploy/pre.js +1 -1
  62. package/dist/defaults/hooks/notarize/post.js +2 -2
  63. package/dist/defaults/hooks/release/post.js +2 -2
  64. package/dist/defaults/hooks/release/pre.js +2 -2
  65. package/dist/defaults/src/assets/js/components/about/index.js +3 -5
  66. package/dist/defaults/src/assets/js/components/main/index.js +3 -5
  67. package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
  68. package/dist/defaults/src/assets/scss/pages/about.scss +1 -1
  69. package/dist/defaults/src/assets/scss/pages/main.scss +1 -1
  70. package/dist/defaults/src/assets/scss/pages/settings.scss +1 -1
  71. package/dist/defaults/src/integrations/context-menu/index.js +13 -13
  72. package/dist/defaults/src/integrations/menu/index.js +8 -8
  73. package/dist/defaults/src/integrations/tray/index.js +12 -12
  74. package/dist/defaults/src/main.js +5 -7
  75. package/dist/defaults/src/preload.js +4 -6
  76. package/dist/defaults/test/README.md +5 -5
  77. package/dist/defaults/test/_init.js +1 -1
  78. package/dist/gulp/main.js +9 -10
  79. package/dist/gulp/tasks/audit.js +11 -14
  80. package/dist/gulp/tasks/build-config.js +8 -8
  81. package/dist/gulp/tasks/bundle.js +16 -16
  82. package/dist/gulp/tasks/defaults.js +3 -3
  83. package/dist/gulp/tasks/distribute.js +2 -2
  84. package/dist/gulp/tasks/html.js +9 -9
  85. package/dist/gulp/tasks/package-quick.js +3 -3
  86. package/dist/gulp/tasks/package.js +3 -3
  87. package/dist/gulp/tasks/release.js +3 -3
  88. package/dist/gulp/tasks/sass.js +6 -6
  89. package/dist/gulp/tasks/serve.js +4 -4
  90. package/dist/hooks/notarize-artifacts.js +1 -1
  91. package/dist/hooks/notarize.js +1 -1
  92. package/dist/index.js +5 -8
  93. package/dist/lib/_environment-mixin.js +50 -0
  94. package/dist/lib/_lifecycle-mixin.js +45 -0
  95. package/dist/lib/analytics.js +33 -35
  96. package/dist/lib/app-state.js +14 -14
  97. package/dist/lib/auth-flow.js +18 -18
  98. package/dist/lib/auth-persistence.js +12 -12
  99. package/dist/lib/auth.js +421 -0
  100. package/dist/lib/auto-updater.js +49 -49
  101. package/dist/lib/context-menu.js +13 -13
  102. package/dist/lib/context.js +19 -19
  103. package/dist/lib/deep-link.js +34 -34
  104. package/dist/lib/fontawesome.js +5 -5
  105. package/dist/lib/ipc.js +4 -4
  106. package/dist/lib/menu.js +25 -25
  107. package/dist/lib/protocol.js +5 -5
  108. package/dist/lib/remote-config.js +22 -22
  109. package/dist/lib/remote-scripts.js +21 -21
  110. package/dist/lib/restart-manager/index.js +29 -29
  111. package/dist/lib/restart-manager/install.js +1 -1
  112. package/dist/lib/restart-manager/protocol.js +1 -1
  113. package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
  114. package/dist/lib/sign-helpers/sign-events.js +1 -1
  115. package/dist/lib/startup.js +18 -13
  116. package/dist/lib/storage.js +10 -10
  117. package/dist/lib/templating.js +16 -16
  118. package/dist/lib/theme.js +10 -10
  119. package/dist/lib/tray.js +27 -27
  120. package/dist/lib/usage.js +11 -11
  121. package/dist/lib/window-manager.js +26 -26
  122. package/dist/main.js +399 -483
  123. package/dist/preload.js +236 -176
  124. package/dist/renderer.js +417 -391
  125. package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
  126. package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
  127. package/dist/test/fixtures/consumer-app/src/main.js +5 -7
  128. package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
  129. package/dist/test/harness/boot-entry.js +22 -20
  130. package/dist/test/harness/main-entry.js +31 -30
  131. package/dist/test/harness/renderer-entry.js +5 -5
  132. package/dist/test/harness/renderer-preload.js +137 -141
  133. package/dist/test/index.js +10 -10
  134. package/dist/test/runner.js +2 -2
  135. package/dist/test/runners/boot.js +7 -6
  136. package/dist/test/runners/electron.js +3 -2
  137. package/dist/test/runners/render-event.js +2 -2
  138. package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
  139. package/dist/test/suites/boot/restart-manager.test.js +2 -2
  140. package/dist/test/suites/boot/storage-bundled.test.js +5 -5
  141. package/dist/test/suites/boot/theme.test.js +13 -13
  142. package/dist/test/suites/build/audit.test.js +21 -8
  143. package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
  144. package/dist/test/suites/build/boot-fixture.test.js +2 -2
  145. package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
  146. package/dist/test/suites/build/brand-scss.test.js +1 -1
  147. package/dist/test/suites/build/build-json-bake.test.js +1 -1
  148. package/dist/test/suites/build/build-workflow-jobs.test.js +2 -2
  149. package/dist/test/suites/build/cli.test.js +30 -2
  150. package/dist/test/suites/build/config-schema.test.js +5 -5
  151. package/dist/test/suites/build/defaults-em-dash.test.js +22 -0
  152. package/dist/test/suites/build/defaults-scaffold.test.js +21 -7
  153. package/dist/test/suites/build/deploy-direct.test.js +7 -5
  154. package/dist/test/suites/build/deploy-dispatch.test.js +2 -1
  155. package/dist/test/suites/build/deploy-hook.test.js +7 -5
  156. package/dist/test/suites/build/dev-verb.test.js +67 -0
  157. package/dist/test/suites/build/ensure-target.test.js +13 -5
  158. package/dist/test/suites/build/env-delivery.test.js +2 -2
  159. package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
  160. package/dist/test/suites/build/exports.test.js +9 -8
  161. package/dist/test/suites/build/get-config.test.js +4 -4
  162. package/dist/test/suites/build/manifest-deps.test.js +1 -1
  163. package/dist/test/suites/build/merge-line-files.test.js +7 -7
  164. package/dist/test/suites/build/migrate.test.js +29 -0
  165. package/dist/test/suites/build/omega-shell.test.js +34 -2
  166. package/dist/test/suites/build/omega.test.js +350 -0
  167. package/dist/test/suites/build/project-scripts-deps.test.js +6 -10
  168. package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
  169. package/dist/test/suites/build/runner-env-write.test.js +73 -0
  170. package/dist/test/suites/build/runner.test.js +11 -10
  171. package/dist/test/suites/build/sentry.test.js +2 -2
  172. package/dist/test/suites/build/setup-scripts.test.js +27 -0
  173. package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
  174. package/dist/test/suites/build/templating.test.js +3 -3
  175. package/dist/test/suites/build/test-stealth.test.js +7 -9
  176. package/dist/test/suites/build/url-helpers.test.js +55 -56
  177. package/dist/test/suites/build/validate-config.test.js +15 -4
  178. package/dist/test/suites/build/verb-logs.test.js +20 -0
  179. package/dist/test/suites/build/wave5-pins.test.js +2 -2
  180. package/dist/test/suites/main/analytics.test.js +59 -59
  181. package/dist/test/suites/main/app-state.test.js +66 -66
  182. package/dist/test/suites/main/auth-flow.test.js +41 -41
  183. package/dist/test/suites/main/auth-persistence.test.js +54 -43
  184. package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
  185. package/dist/test/suites/main/auth.test.js +336 -0
  186. package/dist/test/suites/main/auto-updater.test.js +134 -134
  187. package/dist/test/suites/main/boot-sequence.test.js +37 -49
  188. package/dist/test/suites/main/context-menu.test.js +51 -50
  189. package/dist/test/suites/main/context.test.js +25 -25
  190. package/dist/test/suites/main/deep-link.test.js +74 -74
  191. package/dist/test/suites/main/fontawesome.test.js +27 -27
  192. package/dist/test/suites/main/ipc.test.js +35 -35
  193. package/dist/test/suites/main/menu.test.js +101 -100
  194. package/dist/test/suites/main/protocol.test.js +19 -19
  195. package/dist/test/suites/main/remote-config.test.js +63 -63
  196. package/dist/test/suites/main/remote-scripts.test.js +103 -103
  197. package/dist/test/suites/main/request.test.js +71 -0
  198. package/dist/test/suites/main/restart-manager.test.js +33 -33
  199. package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
  200. package/dist/test/suites/main/startup.test.js +26 -26
  201. package/dist/test/suites/main/stealth-window.test.js +1 -1
  202. package/dist/test/suites/main/storage.test.js +25 -25
  203. package/dist/test/suites/main/theme.test.js +34 -34
  204. package/dist/test/suites/main/tray.test.js +79 -79
  205. package/dist/test/suites/main/url-helpers.test.js +133 -133
  206. package/dist/test/suites/main/usage.test.js +25 -25
  207. package/dist/test/suites/main/window-bounds.test.js +27 -27
  208. package/dist/test/suites/main/window-manager.test.js +44 -44
  209. package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
  210. package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
  211. package/dist/test/suites/renderer/round-trip.test.js +3 -3
  212. package/dist/test/suites/renderer/tooltips.test.js +15 -15
  213. package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +28 -8
  214. package/dist/test/utils/extended-mode-warning.js +1 -1
  215. package/dist/utils/boot-harness.js +56 -0
  216. package/dist/utils/build-pipeline.js +4 -4
  217. package/dist/utils/mode-helpers.js +2 -15
  218. package/dist/utils/runner-env.js +13 -28
  219. package/dist/utils/ship-keys.js +3 -3
  220. package/dist/utils/signing-status.js +51 -0
  221. package/dist/utils/test-events.js +7 -0
  222. package/dist/utils/test-stealth.js +6 -6
  223. package/dist/utils/url-helpers.js +52 -42
  224. package/dist/utils/user-agent.js +44 -0
  225. package/dist/vendor/account/engine.js +3 -3
  226. package/dist/vendor/account/index.js +14 -45
  227. package/dist/vendor/account/resolve-account.js +44 -0
  228. package/dist/vendor/account/schema.js +1 -1
  229. package/dist/vendor/account/user.js +99 -0
  230. package/dist/vendor/config/client-config.js +1 -1
  231. package/dist/vendor/config/company.js +46 -14
  232. package/dist/vendor/config/defaults.js +30 -7
  233. package/dist/vendor/config/edit.js +25 -3
  234. package/dist/vendor/config/env-delivery.js +1 -1
  235. package/dist/vendor/config/env-schema.js +3 -6
  236. package/dist/vendor/config/env.js +34 -22
  237. package/dist/vendor/config/environment.js +11 -30
  238. package/dist/vendor/config/index.js +21 -28
  239. package/dist/vendor/config/load.js +16 -9
  240. package/dist/vendor/config/platforms.js +1 -1
  241. package/dist/vendor/config/repo.js +10 -27
  242. package/dist/vendor/config/schema-client.js +64 -0
  243. package/dist/vendor/config/schema-cloud.js +38 -0
  244. package/dist/vendor/config/schema-manager.js +118 -0
  245. package/dist/vendor/config/schema-overrides.js +68 -0
  246. package/dist/vendor/config/schema.js +104 -160
  247. package/dist/vendor/config/site-global.js +2 -3
  248. package/dist/vendor/config/validate.js +97 -78
  249. package/dist/vendor/config/winback.js +1 -1
  250. package/dist/vendor/devkit/actions-secrets.js +1 -1
  251. package/dist/vendor/devkit/agents-md.js +233 -0
  252. package/dist/vendor/devkit/attach-log-file.js +16 -2
  253. package/dist/vendor/devkit/build-json.js +1 -1
  254. package/dist/vendor/devkit/ci-workflows.js +30 -30
  255. package/dist/vendor/devkit/cli-router.js +16 -11
  256. package/dist/vendor/devkit/defaults-engine.js +15 -51
  257. package/dist/vendor/devkit/deploy-snapshot.js +44 -9
  258. package/dist/vendor/devkit/env-lines.js +183 -0
  259. package/dist/vendor/devkit/local.js +64 -10
  260. package/dist/vendor/devkit/lockfile.js +32 -13
  261. package/dist/vendor/devkit/logger.js +7 -2
  262. package/dist/vendor/devkit/merge-line-files.js +219 -177
  263. package/dist/vendor/devkit/omega-bin.js +208 -111
  264. package/dist/vendor/devkit/preludes/docs-sync.js +52 -0
  265. package/dist/vendor/devkit/preludes/index.js +1 -0
  266. package/dist/vendor/devkit/target-picker.js +45 -0
  267. package/dist/vendor/devkit/test/dashed-files.js +37 -0
  268. package/dist/vendor/devkit/test/run-verb-under-tee.js +71 -0
  269. package/dist/vendor/devkit/test/runner-core.js +6 -6
  270. package/dist/vendor/devkit/update.js +15 -15
  271. package/dist/vendor/devkit/verb-scripts.js +40 -0
  272. package/dist/vendor/devkit/verbs.js +170 -0
  273. package/dist/vendor/monitoring/env.js +2 -2
  274. package/dist/vendor/monitoring/index.js +1 -1
  275. package/dist/vendor/monitoring/main.js +1 -1
  276. package/dist/vendor/monitoring/preload.js +1 -1
  277. package/dist/vendor/monitoring/renderer.js +1 -1
  278. package/package.json +19 -26
  279. package/dist/commands/install.js +0 -37
  280. package/dist/defaults/AGENTS.md +0 -110
  281. package/dist/defaults/CLAUDE.md +0 -1
  282. package/dist/lib/client-bridge.js +0 -374
  283. package/dist/lib/logger.js +0 -4
  284. package/dist/test/suites/build/manager.test.js +0 -213
  285. package/dist/test/suites/main/client-bridge.test.js +0 -262
  286. package/dist/vendor/config/env-retired.js +0 -137
  287. package/dist/vendor/config/retired-keys.js +0 -635
  288. package/docs/analytics.md +0 -140
  289. package/docs/app-state.md +0 -92
  290. package/docs/audit.md +0 -69
  291. package/docs/auto-updater.md +0 -243
  292. package/docs/boot-sequence.md +0 -39
  293. package/docs/build-system.md +0 -169
  294. package/docs/cdp-debugging.md +0 -169
  295. package/docs/client-bridge.md +0 -269
  296. package/docs/common-mistakes.md +0 -21
  297. package/docs/config-schema.md +0 -120
  298. package/docs/context-menu.md +0 -112
  299. package/docs/context.md +0 -81
  300. package/docs/css.md +0 -90
  301. package/docs/deep-link.md +0 -186
  302. package/docs/environment-detection.md +0 -112
  303. package/docs/fontawesome.md +0 -107
  304. package/docs/hooks.md +0 -89
  305. package/docs/icons.md +0 -79
  306. package/docs/index.md +0 -317
  307. package/docs/installer-options.md +0 -165
  308. package/docs/ipc.md +0 -61
  309. package/docs/lib-modules.md +0 -53
  310. package/docs/logging.md +0 -229
  311. package/docs/menu.md +0 -160
  312. package/docs/releasing.md +0 -239
  313. package/docs/remote-config.md +0 -118
  314. package/docs/remote-scripts.md +0 -144
  315. package/docs/restart-manager.md +0 -144
  316. package/docs/runner.md +0 -290
  317. package/docs/sentry.md +0 -97
  318. package/docs/shared/agent-docs.md +0 -89
  319. package/docs/shared/analytics.md +0 -612
  320. package/docs/shared/brands.md +0 -57
  321. package/docs/shared/breaking-changes.md +0 -851
  322. package/docs/shared/config.md +0 -1952
  323. package/docs/shared/deploys.md +0 -341
  324. package/docs/shared/icons.md +0 -219
  325. package/docs/shared/local-dev.md +0 -167
  326. package/docs/shared/logging.md +0 -205
  327. package/docs/shared/monitoring.md +0 -167
  328. package/docs/shared/publishing.md +0 -187
  329. package/docs/shared/rulings.md +0 -34
  330. package/docs/shared/testing.md +0 -147
  331. package/docs/shared/theming.md +0 -629
  332. package/docs/shared/translation.md +0 -333
  333. package/docs/shared/updates.md +0 -61
  334. package/docs/signing.md +0 -293
  335. package/docs/startup.md +0 -142
  336. package/docs/storage.md +0 -59
  337. package/docs/templating.md +0 -101
  338. package/docs/test-boot-layer.md +0 -157
  339. package/docs/test-framework.md +0 -362
  340. package/docs/themes.md +0 -149
  341. package/docs/tooltips.md +0 -99
  342. package/docs/tray.md +0 -164
  343. package/docs/usage.md +0 -58
  344. package/docs/verts.md +0 -62
  345. package/docs/windows.md +0 -149
@@ -1,112 +0,0 @@
1
- # Environment Detection
2
-
3
- `getEnvironment()` returns exactly ONE of three mutually-exclusive, exhaustive values:
4
-
5
- ```javascript
6
- Manager.getEnvironment() // 'development' | 'testing' | 'production'
7
-
8
- Manager.isDevelopment() // true ONLY in development
9
- Manager.isTesting() // true ONLY in testing
10
- Manager.isProduction() // true ONLY in production
11
- ```
12
-
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
-
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()`).
16
-
17
- ```javascript
18
- manager.getEnvironment() // same answer in main / renderer / preload / build
19
- Manager.isTesting() // static form, for build-time scripts
20
- ```
21
-
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
-
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.
25
-
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
-
28
- ## Available helpers
29
-
30
- | Helper | Returns |
31
- |---|---|
32
- | `getEnvironment()` | `'development' \| 'testing' \| 'production'`: the one reader of the one input; throws when it is absent. |
33
- | `isDevelopment()` | `true` ONLY in development, and NOT testing. Derives from `getEnvironment()`. |
34
- | `isTesting()` | `true` ONLY in testing. Derives from `getEnvironment()`. |
35
- | `isProduction()` | `true` ONLY in production. A **real positive check**, NOT `!isDevelopment()`. |
36
-
37
- ## Gating side effects — use the INTENTIONAL check
38
-
39
- Because there are three environments, never gate a side effect on a two-value assumption. State what you mean:
40
-
41
- ```javascript
42
- // Production-only (skip OS side effects / real telemetry in dev AND testing):
43
- if (isProduction()) { /* do the real thing */ }
44
- if (!isProduction()) { /* skip / use the safe local behavior */ }
45
-
46
- // Local-or-test (anything that should run in BOTH dev and testing):
47
- if (isDevelopment() || isTesting()) { /* localhost URL, isolate userData, suppress login items */ }
48
- ```
49
-
50
- **Avoid** `if (!isDevelopment())` or `if (env !== 'development')` to gate production behavior — those wrongly include `testing` as production and leak real side effects (login items, telemetry, auto-update) during test runs. This is the bug class that motivated the 3-value model. (A genuinely dev-only feature like live-reload is the exception: `env !== 'development'` correctly skips it in both testing and production.)
51
-
52
- ## URL helpers
53
-
54
- ```javascript
55
- Manager.getApiUrl() // the app's API URL — the SSOT for calling the backend
56
- ```
57
-
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
-
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.
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).
63
-
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
-
66
- | Helper | Env channel | Baked channel | Neither |
67
- |---|---|---|---|
68
- | `getApiUrl()` | `OMEGA_HTTPS_PORT`, else `OMEGA_HOSTING_PORT` | `dev.ports.https`, else `dev.ports.hosting` | throws |
69
- | `getFunctionsUrl()` | `OMEGA_FUNCTIONS_PORT` | `dev.ports.functions` | throws |
70
- | `getWebsiteUrl()` | `OMEGA_WEBSITE_PORT`, composed as `https://localhost:<port>` | `dev.origin` (the whole origin) first, else `dev.ports.website` | throws |
71
-
72
- The classics still reach these helpers, from the ONE place they are defined: the bundle task bakes `CLASSIC_PORTS` and `CLASSIC_DEV_ORIGIN` (`@omega.js/config`) as the FLOOR of the `dev` map, with the live stack's resolved numbers over them, so a dev artifact always carries a complete map. A read that finds none names the fact it wanted and the build step that writes it. A production build bakes no `dev` at all, which is correct: a packaged app has no local stack to reach.
73
-
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
-
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)).
77
-
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
-
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.
81
-
82
- ## Where they live
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.
85
-
86
- ## How detection works
87
-
88
- `getEnvironment()` reads ONE input, and there is no precedence ladder under it
89
- ([#817](https://github.com/Omega-JS-Stack/omega/issues/817)):
90
-
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)).
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
-
95
- The lanes above supply that input, and the whole table of who names what lives in
96
- [docs/shared/config.md](../../../docs/shared/config.md).
97
-
98
- ## Adding a new helper
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.
101
-
102
- ## Why this matters
103
-
104
- **One signal, used everywhere.** The test runners spawn their children naming `OMEGA_ENVIRONMENT=testing`; every piece of code that calls `isTesting()` (framework or consumer) then sees `true`, no need to invent a per-module env var.
105
-
106
- **Sub-modules check the same signal.** When framework code (an auto-update poll, a restart-manager registration) needs to skip side effects in tests, it checks `isTesting()` — the same answer the consumer's own code gets. No drift.
107
-
108
- **`is*()` can never disagree with `getEnvironment()`.** Because the checks derive from the single resolver instead of reading raw signals, there is exactly one definition of "what environment is this," and a wrong-but-confident gate is structurally impossible. Since #817 that holds ACROSS frameworks too: the resolver is one shared module, so @omega.js/desktop and @omega.js/extension can no longer answer differently from the same inputs.
109
-
110
- ## See also
111
-
112
- - [test-framework.md](test-framework.md): `OMEGA_ENVIRONMENT=testing` is named automatically by the test runners; extended mode (`--extended` / `TEST_EXTENDED_MODE`) gates real external APIs.
@@ -1,107 +0,0 @@
1
- # FontAwesome
2
-
3
- @omega.js/desktop serves the **brand's best available Font Awesome set** —
4
- Pro when the brand supplies one (see below), otherwise the **Free set**
5
- (solid + regular + brands, SVG) straight from its
6
- `@fortawesome/fontawesome-free` npm dependency — every consumer gets 2,600+
7
- icons with **zero setup**, fully offline, no icon font, no CDN, and nothing
8
- vendored inside the framework package.
9
-
10
- ```html
11
- <button class="btn btn-primary">
12
- <i class="fa-solid fa-rocket me-2"></i>Launch
13
- </button>
14
- ```
15
-
16
- That's it. Any `<i>` element carrying `fa-*` classes — in static HTML or
17
- inserted dynamically at any time — gets the real SVG injected inline by the
18
- renderer bootstrap. No `initialize()` options, no imports.
19
-
20
- ## One icon mechanism, every surface (C4 cp108)
21
-
22
- Icon SEMANTICS — valid names/styles, candidate lookup order (requested style,
23
- then the brands fallback), the injected root attributes, and alias mapping —
24
- live in **`@omega.js/client/modules/icon-core.js`**, the SAME module
25
- @omega.js/web's build-time inlining pass uses. Desktop and web can never
26
- drift on how an icon name resolves or what the served SVG looks like.
27
-
28
- ## How it works
29
-
30
- - **Assets** — resolved through the root chain (cp111), best-first:
31
- `OMEGA_FONTAWESOME_ROOT` download dir → `@fortawesome/fontawesome-pro`
32
- when the brand installed it → `@fortawesome/fontawesome-free` (a declared
33
- runtime dependency, always last so a partial brand set never loses icons
34
- the free set has). Each root holds `svgs/<style>/*.svg` plus
35
- `metadata/icon-families.json` for aliases (`search` → `magnifying-glass`).
36
- Declared dependencies ride into packaged apps automatically (fs reads
37
- through the asar transparently).
38
- - **Main lib** (`lib/fontawesome.js`) — `manager.fontawesome.get(name, style)`
39
- resolves an icon to its SVG string (`null` for unknown names — never
40
- throws). Lookups are slug-sanitized via icon-core (the IPC channel can
41
- never read outside the icon directories) and cached per app run. Serves
42
- renderers over `desktop:fontawesome:get`.
43
- - **Preload bridge** — `window.desktop.fontawesome.get(name, style)` →
44
- `Promise<svg | null>`.
45
- - **Renderer auto-render** (`renderer.js _wireFontAwesome`) — a thin
46
- wrapper over **@omega.js/client's shared `icon-renderer`** (C4 cp112, the
47
- same module web pages run): scan + MutationObserver for insertions AND
48
- class changes (`el.className = 'fa-solid fa-stop'` re-renders in place;
49
- dropping the classes clears the SVG), FA's family × weight class parsing
50
- (`fa-sharp fa-light` → `sharp-light`; Pro markup without a Pro set stays
51
- empty — never a wrong-style fallback), caching, and the
52
- `data-omega-fa="<style>/<name>"` marker. Desktop supplies only the
53
- transport: IPC to main's icon server.
54
- The SVG is injected as a child of the `<i>`, sized `1em`/`currentColor` — it
55
- inherits text color and scales with font-size (bump it via `font-size` or a
56
- `fs-*` utility). Served SVGs also carry `overflow="visible"` (FA-kit parity:
57
- `.svg-inline--fa { overflow: visible }`) — FA 7 glyphs may draw OUTSIDE
58
- their viewBox (fa-lock's shackle peaks at y=-32 in a `0 0 384 512` box) and
59
- the SVG-root default of `overflow: hidden` clips them flat.
60
-
61
- ## Minimal surfaces
62
-
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:
66
-
67
- ```js
68
- new (require('@omega.js/desktop/renderer'))().enableFontAwesome();
69
- ```
70
-
71
- ## Supplying Font Awesome Pro (C4 cp111)
72
-
73
- Pro is brand-supplied, never redistributed by the framework. The two
74
- routes (FA npm token, or an `OMEGA_FONTAWESOME_ROOT` download dir), the
75
- chain semantics, and the style/family model are documented once at the
76
- repo hub: **[docs/shared/icons.md](../../../docs/shared/icons.md)**. Desktop-specific
77
- note: a packaged brand target declares `@fortawesome/fontawesome-pro` as its
78
- own **prod dependency** so the set ships inside the asar.
79
-
80
- ## Notes
81
-
82
- - **The icon CSS is not desktop's.** The box, the size scale and the
83
- `fa-spin`/`fa-bounce`/`fa-beat` utilities ride ONE sheet vendored from
84
- @omega.js/web at prepare (see [css.md](css.md#icon-presentation)). Fix icon
85
- presentation there, never here.
86
- - **Unknown names render nothing** — the `<i>` stays empty (marked
87
- `data-omega-fa`). If you need a fallback, resolve through
88
- `window.desktop.fontawesome.get()` and swap yourself.
89
- - **Free set = solid + regular + brands.** Pro styles (light/duotone/sharp)
90
- need a supplied Pro set (above); otherwise
91
- `manager.fontawesome.get(name, 'duotone')` returns `null`.
92
- - **Updating the set** — bump the `@fortawesome/fontawesome-free` dependency
93
- (or reinstall/refresh the brand's Pro supply).
94
-
95
- ## Testing
96
-
97
- - `src/test/suites/main/fontawesome.test.js` — resolution, aliases (via the
98
- metadata map), sanitization (traversal attempts), caching, IPC round-trip,
99
- the `overflow="visible"` serve attribute, and the cp111 root chain
100
- (`OMEGA_FONTAWESOME_ROOT` wins, free set falls through for icons and
101
- metadata the brand set lacks).
102
- - `src/test/suites/renderer/fontawesome.test.js` — the real-DOM proof of
103
- the SHARED icon-renderer: inserted `<i>` elements get SVGs on the live
104
- DOM, class changes re-render in place and class removal clears (cp112),
105
- modifier classes are never mistaken for names, Pro family/weight classes
106
- compose (Pro-adaptive assertions), unknown names stay empty, injected
107
- SVGs compute `overflow: visible` (out-of-viewBox glyphs must not clip).
package/docs/hooks.md DELETED
@@ -1,89 +0,0 @@
1
- # Lifecycle Hooks
2
-
3
- Consumers can inject custom logic at well-defined points without forking @omega.js/desktop's gulp tasks. All hooks are **purely additive extension points** — @omega.js/desktop's core logic always runs first, the hook is called after (or before, depending on the lifecycle point), and a hook throwing only logs a warning, never breaks the build.
4
-
5
- ## How hooks work
6
-
7
- 1. @omega.js/desktop scaffolds empty hook files into `<consumer>/hooks/**/*.js` on every verb (`ensureTarget()`).
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.
10
- 4. **Failure semantics:**
11
- - File missing entirely → logged informationally (`hook "<name>" not present at ... — skipping.`), build continues.
12
- - File exists but fails to load (syntax error, etc.) → **throws**, build fails.
13
- - File exists but doesn't export a function → **throws**, build fails.
14
- - File loads + invokes the function and the function throws → **throws**, build fails.
15
-
16
- In other words: a hook that doesn't exist is fine (you'll see one log line), but a hook that's broken in any way fails loudly. You should never silently ship a malformed hook to production.
17
-
18
- ## Hooks reference
19
-
20
- | Hook file | When it runs | `ctx` shape |
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' }` |
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
-
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.
30
-
31
- ## Why this design
32
-
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
- - **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.
36
-
37
- ## Examples
38
-
39
- ### Slack notification on release
40
-
41
- ```js
42
- // hooks/release/post.js
43
- module.exports = async ({ manager, projectRoot }) => {
44
- const pkg = require(`${projectRoot}/package.json`);
45
- const url = process.env.SLACK_WEBHOOK_URL;
46
- if (!url) return;
47
- await fetch(url, {
48
- method: 'POST',
49
- headers: { 'content-type': 'application/json' },
50
- body: JSON.stringify({ text: `🚀 ${pkg.name} v${pkg.version} released` }),
51
- });
52
- };
53
- ```
54
-
55
- ### Generate changelog before build
56
-
57
- ```js
58
- // hooks/build/pre.js
59
- const { execSync } = require('child_process');
60
- const fs = require('fs');
61
- const path = require('path');
62
-
63
- module.exports = async ({ projectRoot }) => {
64
- const log = execSync('git log --oneline -n 20', { cwd: projectRoot });
65
- fs.writeFileSync(path.join(projectRoot, 'CHANGELOG_LATEST.txt'), log);
66
- };
67
- ```
68
-
69
- ### Custom post-notarize archive
70
-
71
- ```js
72
- // hooks/notarize/post.js
73
- const fs = require('fs');
74
- const path = require('path');
75
-
76
- module.exports = async (context) => {
77
- const { appOutDir, packager } = context;
78
- const appName = packager.appInfo.productFilename;
79
- const appPath = path.join(appOutDir, `${appName}.app`);
80
- // e.g. archive a copy somewhere off the build path
81
- fs.cpSync(appPath, `/tmp/omega-archive/${appName}-${Date.now()}.app`, { recursive: true });
82
- };
83
- ```
84
-
85
- ## Tests
86
-
87
- - `src/test/suites/build/run-consumer-hook.test.js` — silent skip, invocation with args, error swallowing.
88
- - `src/test/suites/build/deploy-hook.test.js`: `omega deploy` runs `hooks/deploy/pre.js` after the scaffold and before the precheck; a dry run skips it.
89
- - `src/test/suites/build/build-config.test.js` — `injectAfterSign` always points at @omega.js/desktop's notarize.
package/docs/icons.md DELETED
@@ -1,79 +0,0 @@
1
- # Icons
2
-
3
- Convention-only. No config block — drop PNGs at known paths and @omega.js/desktop finds them.
4
-
5
- ## Layout
6
-
7
- ```
8
- config/icons/
9
- global/ ← used by any platform with no platform-specific override
10
- icon.png
11
- tray.png
12
- mac/ ← macOS overrides (beats global)
13
- icon.png
14
- tray.png ← 32×32 native; @omega.js/desktop renames to trayTemplate.png in dist
15
- dmg.png ← 1080×760 DMG installer background
16
- windows/ ← Windows overrides
17
- icon.png
18
- tray.png ← optional; falls back to icon.png
19
- linux/ ← Linux overrides
20
- icon.png
21
- tray.png
22
- ```
23
-
24
- ## Resolution chain (per slot, per platform)
25
-
26
- Most specific wins:
27
-
28
- 1. `<projectRoot>/config/icons/<platform>/<file>` — platform-specific override
29
- 2. `<projectRoot>/config/icons/global/<file>` — universal fallback shared by all platforms
30
- 3. `<projectRoot>/config/icons/windows/<file>` — Linux-only extra step (legacy compat — Linux apps historically reuse Windows assets)
31
- 4. `<@omega.js/desktop>/dist/config/icons/<platform>/<file>` — @omega.js/desktop bundled default
32
- 5. `<@omega.js/desktop>/dist/config/icons/windows/<file>` — Linux-only extra step at the bundled level
33
-
34
- Inside the runtime tray lookup (`lib/tray.js`), tray-slot misses fall back to the app icon (`icon.png`) instead of returning null.
35
-
36
- ## Sizes — ship @2x native only
37
-
38
- Retina slots (macOS tray, macOS dmg) take ONE source file at the native (@2x) size. @omega.js/desktop downscales the @1x sibling at build time via `sharp` and writes both into `dist/`. Consumers never ship `<name>@2x.png` files.
39
-
40
- | Slot | Native size | @omega.js/desktop emits |
41
- |---|---|---|
42
- | `mac/tray.png` | 32×32 | `trayTemplate.png` (16×16) + `trayTemplate@2x.png` (32×32) |
43
- | `mac/dmg.png` | 1080×760 | `dmg.png` (540×380) + `dmg@2x.png` (1080×760) |
44
- | `mac/icon.png` | 1024×1024 | `icon.png` (unchanged; electron-builder converts to `.icns`) |
45
- | `windows/icon.png` | 1024×1024 | `icon.png` (unchanged; electron-builder converts to `.ico`) |
46
- | `linux/icon.png` | 1024×1024 | `icon.png` (unchanged) |
47
-
48
- ## Why `trayTemplate.png` on disk
49
-
50
- macOS reads the literal filename of the tray icon and treats any `*Template.png` as a "template image" — pure-black with alpha, automatically inverted in dark mode. Consumers ship `tray.png` (clearer naming, matches Windows/Linux); @omega.js/desktop owns the `Template` suffix when writing to `dist/`.
51
-
52
- If you set a custom path via `tray.icon(path)` in your `src/integrations/tray/index.js`, YOU are responsible for the runtime filename containing `Template` — @omega.js/desktop only owns the convention path.
53
-
54
- ## Two common scenarios
55
-
56
- **One icon for everything:**
57
-
58
- ```
59
- config/icons/global/icon.png # mac + win + linux
60
- config/icons/global/tray.png # mac + win + linux
61
- ```
62
-
63
- **Mac-specific + shared Win/Linux:**
64
-
65
- ```
66
- config/icons/global/icon.png # win + linux use this
67
- config/icons/mac/icon.png # mac override
68
- config/icons/mac/tray.png # mac-specific tray (will become trayTemplate.png in dist)
69
- config/icons/mac/dmg.png # mac-only by definition
70
- ```
71
-
72
- ## Source files
73
-
74
- - `src/lib/sign-helpers/resolve-icons.js` — the resolver itself; called from `gulp/build-config.js`.
75
- - `src/lib/tray.js#_defaultIconPath` — runtime tray lookup (same convention waterfall, but checks `dist/` first since the build already resolved).
76
-
77
- ## Bundled defaults
78
-
79
- @omega.js/desktop ships its own `icon.png`, `tray.png`, `dmg.png` for each platform in `<@omega.js/desktop>/src/defaults/config/icons/<platform>/`. These are the final fallback when neither the consumer nor a global file provides anything — so a freshly scaffolded project produces a buildable app with the generic @omega.js/desktop icon out of the box.