@omega.js/desktop 0.52.0 → 0.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/README.md +17 -12
  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 +11 -11
  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/AGENTS.md +17 -8
  48. package/dist/defaults/config/omega.json5 +7 -7
  49. package/dist/defaults/hooks/build/post.js +1 -1
  50. package/dist/defaults/hooks/build/pre.js +1 -1
  51. package/dist/defaults/hooks/deploy/pre.js +1 -1
  52. package/dist/defaults/hooks/release/post.js +1 -1
  53. package/dist/defaults/hooks/release/pre.js +1 -1
  54. package/dist/defaults/src/assets/js/components/about/index.js +3 -5
  55. package/dist/defaults/src/assets/js/components/main/index.js +3 -5
  56. package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
  57. package/dist/defaults/src/integrations/context-menu/index.js +2 -2
  58. package/dist/defaults/src/integrations/menu/index.js +3 -3
  59. package/dist/defaults/src/integrations/tray/index.js +3 -3
  60. package/dist/defaults/src/main.js +3 -5
  61. package/dist/defaults/src/preload.js +3 -5
  62. package/dist/defaults/test/README.md +2 -2
  63. package/dist/gulp/main.js +9 -10
  64. package/dist/gulp/tasks/audit.js +7 -7
  65. package/dist/gulp/tasks/build-config.js +8 -8
  66. package/dist/gulp/tasks/bundle.js +16 -16
  67. package/dist/gulp/tasks/defaults.js +3 -3
  68. package/dist/gulp/tasks/distribute.js +2 -2
  69. package/dist/gulp/tasks/html.js +9 -9
  70. package/dist/gulp/tasks/package-quick.js +3 -3
  71. package/dist/gulp/tasks/package.js +3 -3
  72. package/dist/gulp/tasks/release.js +3 -3
  73. package/dist/gulp/tasks/sass.js +6 -6
  74. package/dist/gulp/tasks/serve.js +4 -4
  75. package/dist/hooks/notarize-artifacts.js +1 -1
  76. package/dist/hooks/notarize.js +1 -1
  77. package/dist/index.js +5 -8
  78. package/dist/lib/_environment-mixin.js +50 -0
  79. package/dist/lib/_lifecycle-mixin.js +45 -0
  80. package/dist/lib/analytics.js +33 -35
  81. package/dist/lib/app-state.js +14 -14
  82. package/dist/lib/auth-flow.js +18 -18
  83. package/dist/lib/auth-persistence.js +12 -12
  84. package/dist/lib/auth.js +421 -0
  85. package/dist/lib/auto-updater.js +49 -49
  86. package/dist/lib/context-menu.js +13 -13
  87. package/dist/lib/context.js +19 -19
  88. package/dist/lib/deep-link.js +34 -34
  89. package/dist/lib/fontawesome.js +5 -5
  90. package/dist/lib/ipc.js +4 -4
  91. package/dist/lib/menu.js +25 -25
  92. package/dist/lib/protocol.js +5 -5
  93. package/dist/lib/remote-config.js +22 -22
  94. package/dist/lib/remote-scripts.js +21 -21
  95. package/dist/lib/restart-manager/index.js +28 -28
  96. package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
  97. package/dist/lib/sign-helpers/sign-events.js +1 -1
  98. package/dist/lib/startup.js +18 -13
  99. package/dist/lib/storage.js +10 -10
  100. package/dist/lib/templating.js +16 -16
  101. package/dist/lib/theme.js +10 -10
  102. package/dist/lib/tray.js +27 -27
  103. package/dist/lib/usage.js +11 -11
  104. package/dist/lib/window-manager.js +26 -26
  105. package/dist/main.js +398 -483
  106. package/dist/preload.js +236 -176
  107. package/dist/renderer.js +417 -391
  108. package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
  109. package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
  110. package/dist/test/fixtures/consumer-app/src/main.js +5 -7
  111. package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
  112. package/dist/test/harness/boot-entry.js +22 -20
  113. package/dist/test/harness/main-entry.js +31 -30
  114. package/dist/test/harness/renderer-entry.js +5 -5
  115. package/dist/test/harness/renderer-preload.js +137 -141
  116. package/dist/test/index.js +10 -10
  117. package/dist/test/runner.js +2 -2
  118. package/dist/test/runners/boot.js +7 -6
  119. package/dist/test/runners/electron.js +3 -2
  120. package/dist/test/runners/render-event.js +2 -2
  121. package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
  122. package/dist/test/suites/boot/restart-manager.test.js +2 -2
  123. package/dist/test/suites/boot/storage-bundled.test.js +5 -5
  124. package/dist/test/suites/boot/theme.test.js +13 -13
  125. package/dist/test/suites/build/audit.test.js +1 -1
  126. package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
  127. package/dist/test/suites/build/boot-fixture.test.js +2 -2
  128. package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
  129. package/dist/test/suites/build/brand-scss.test.js +1 -1
  130. package/dist/test/suites/build/build-json-bake.test.js +1 -1
  131. package/dist/test/suites/build/cli.test.js +2 -2
  132. package/dist/test/suites/build/config-schema.test.js +5 -5
  133. package/dist/test/suites/build/defaults-scaffold.test.js +2 -2
  134. package/dist/test/suites/build/deploy-hook.test.js +3 -3
  135. package/dist/test/suites/build/ensure-target.test.js +2 -2
  136. package/dist/test/suites/build/env-delivery.test.js +2 -2
  137. package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
  138. package/dist/test/suites/build/exports.test.js +9 -8
  139. package/dist/test/suites/build/get-config.test.js +4 -4
  140. package/dist/test/suites/build/manifest-deps.test.js +1 -1
  141. package/dist/test/suites/build/merge-line-files.test.js +1 -1
  142. package/dist/test/suites/build/omega-shell.test.js +34 -2
  143. package/dist/test/suites/build/omega.test.js +350 -0
  144. package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
  145. package/dist/test/suites/build/runner.test.js +2 -2
  146. package/dist/test/suites/build/sentry.test.js +2 -2
  147. package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
  148. package/dist/test/suites/build/templating.test.js +3 -3
  149. package/dist/test/suites/build/test-stealth.test.js +7 -9
  150. package/dist/test/suites/build/url-helpers.test.js +55 -56
  151. package/dist/test/suites/build/validate-config.test.js +2 -2
  152. package/dist/test/suites/build/wave5-pins.test.js +2 -2
  153. package/dist/test/suites/main/analytics.test.js +59 -59
  154. package/dist/test/suites/main/app-state.test.js +66 -66
  155. package/dist/test/suites/main/auth-flow.test.js +41 -41
  156. package/dist/test/suites/main/auth-persistence.test.js +54 -43
  157. package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
  158. package/dist/test/suites/main/auth.test.js +336 -0
  159. package/dist/test/suites/main/auto-updater.test.js +134 -134
  160. package/dist/test/suites/main/boot-sequence.test.js +37 -49
  161. package/dist/test/suites/main/context-menu.test.js +51 -50
  162. package/dist/test/suites/main/context.test.js +25 -25
  163. package/dist/test/suites/main/deep-link.test.js +74 -74
  164. package/dist/test/suites/main/fontawesome.test.js +27 -27
  165. package/dist/test/suites/main/ipc.test.js +35 -35
  166. package/dist/test/suites/main/menu.test.js +101 -100
  167. package/dist/test/suites/main/protocol.test.js +19 -19
  168. package/dist/test/suites/main/remote-config.test.js +63 -63
  169. package/dist/test/suites/main/remote-scripts.test.js +103 -103
  170. package/dist/test/suites/main/request.test.js +71 -0
  171. package/dist/test/suites/main/restart-manager.test.js +33 -33
  172. package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
  173. package/dist/test/suites/main/startup.test.js +26 -26
  174. package/dist/test/suites/main/stealth-window.test.js +1 -1
  175. package/dist/test/suites/main/storage.test.js +25 -25
  176. package/dist/test/suites/main/theme.test.js +34 -34
  177. package/dist/test/suites/main/tray.test.js +79 -79
  178. package/dist/test/suites/main/url-helpers.test.js +133 -133
  179. package/dist/test/suites/main/usage.test.js +25 -25
  180. package/dist/test/suites/main/window-bounds.test.js +27 -27
  181. package/dist/test/suites/main/window-manager.test.js +44 -44
  182. package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
  183. package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
  184. package/dist/test/suites/renderer/round-trip.test.js +3 -3
  185. package/dist/test/suites/renderer/tooltips.test.js +15 -15
  186. package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +27 -7
  187. package/dist/test/utils/extended-mode-warning.js +1 -1
  188. package/dist/utils/boot-harness.js +56 -0
  189. package/dist/utils/mode-helpers.js +2 -15
  190. package/dist/utils/ship-keys.js +3 -3
  191. package/dist/utils/signing-status.js +51 -0
  192. package/dist/utils/test-events.js +7 -0
  193. package/dist/utils/test-stealth.js +6 -6
  194. package/dist/utils/url-helpers.js +52 -42
  195. package/dist/utils/user-agent.js +44 -0
  196. package/dist/vendor/account/engine.js +3 -3
  197. package/dist/vendor/account/index.js +14 -45
  198. package/dist/vendor/account/resolve-account.js +44 -0
  199. package/dist/vendor/account/schema.js +1 -1
  200. package/dist/vendor/account/user.js +99 -0
  201. package/dist/vendor/config/client-config.js +1 -1
  202. package/dist/vendor/config/environment.js +11 -30
  203. package/dist/vendor/config/index.js +8 -11
  204. package/dist/vendor/config/load.js +1 -2
  205. package/dist/vendor/config/platforms.js +1 -1
  206. package/dist/vendor/config/retired-keys.js +2 -2
  207. package/dist/vendor/config/schema.js +5 -8
  208. package/dist/vendor/config/site-global.js +2 -3
  209. package/dist/vendor/config/validate.js +1 -2
  210. package/dist/vendor/config/winback.js +1 -1
  211. package/dist/vendor/devkit/actions-secrets.js +1 -1
  212. package/dist/vendor/devkit/attach-log-file.js +1 -1
  213. package/dist/vendor/devkit/build-json.js +1 -1
  214. package/dist/vendor/devkit/cli-router.js +3 -4
  215. package/dist/vendor/devkit/defaults-engine.js +9 -11
  216. package/dist/vendor/devkit/local.js +2 -0
  217. package/dist/vendor/devkit/merge-line-files.js +2 -3
  218. package/dist/vendor/devkit/test/runner-core.js +6 -6
  219. package/dist/vendor/monitoring/env.js +2 -2
  220. package/dist/vendor/monitoring/index.js +1 -1
  221. package/dist/vendor/monitoring/main.js +1 -1
  222. package/dist/vendor/monitoring/preload.js +1 -1
  223. package/dist/vendor/monitoring/renderer.js +1 -1
  224. package/docs/analytics.md +8 -8
  225. package/docs/app-state.md +19 -19
  226. package/docs/audit.md +4 -4
  227. package/docs/{client-bridge.md → auth.md} +88 -73
  228. package/docs/auto-updater.md +8 -8
  229. package/docs/boot-sequence.md +11 -6
  230. package/docs/build-system.md +1 -1
  231. package/docs/cdp-debugging.md +1 -1
  232. package/docs/common-mistakes.md +7 -7
  233. package/docs/config-schema.md +1 -1
  234. package/docs/context-menu.md +13 -13
  235. package/docs/context.md +11 -11
  236. package/docs/css.md +3 -9
  237. package/docs/deep-link.md +25 -25
  238. package/docs/environment-detection.md +16 -16
  239. package/docs/fontawesome.md +7 -5
  240. package/docs/hooks.md +8 -8
  241. package/docs/index.md +38 -27
  242. package/docs/ipc.md +10 -10
  243. package/docs/lib-modules.md +9 -9
  244. package/docs/logging.md +12 -14
  245. package/docs/menu.md +18 -18
  246. package/docs/remote-config.md +9 -9
  247. package/docs/remote-scripts.md +12 -12
  248. package/docs/restart-manager.md +8 -8
  249. package/docs/sentry.md +4 -4
  250. package/docs/shared/analytics.md +1 -1
  251. package/docs/shared/breaking-changes.md +79 -13
  252. package/docs/shared/config.md +17 -21
  253. package/docs/shared/logging.md +1 -1
  254. package/docs/shared/monitoring.md +5 -5
  255. package/docs/shared/testing.md +2 -2
  256. package/docs/shared/theming.md +1 -1
  257. package/docs/shared/translation.md +19 -10
  258. package/docs/startup.md +16 -16
  259. package/docs/storage.md +11 -11
  260. package/docs/templating.md +3 -3
  261. package/docs/test-boot-layer.md +12 -12
  262. package/docs/test-framework.md +17 -17
  263. package/docs/themes.md +7 -7
  264. package/docs/tooltips.md +2 -2
  265. package/docs/tray.md +31 -31
  266. package/docs/usage.md +7 -7
  267. package/docs/verts.md +1 -1
  268. package/docs/windows.md +22 -22
  269. package/package.json +3 -4
  270. package/dist/lib/client-bridge.js +0 -374
  271. package/dist/lib/logger.js +0 -4
  272. package/dist/test/suites/build/manager.test.js +0 -213
  273. package/dist/test/suites/main/client-bridge.test.js +0 -262
@@ -4,9 +4,9 @@
4
4
  // inserted after boot), title changes update the live instance, and removal
5
5
  // disposes it. Real DOM, real Bootstrap — the tip element actually renders.
6
6
  //
7
- // The harness wires the renderer Manager in the PRELOAD world (contextIsolation
7
+ // The harness wires the renderer instance in the PRELOAD world (contextIsolation
8
8
  // — see harness/renderer-preload.js), so instance-level assertions and the
9
- // show trigger go through the `window.__emTestTooltip` probe (page-world
9
+ // show trigger go through the `window.__omegaTestTooltip` probe (page-world
10
10
  // synthetic mouse events can't reach preload-world listeners). Real
11
11
  // hover-in-one-world behavior + `window.bootstrap` page exposure are covered
12
12
  // by consumer boot suites.
@@ -25,10 +25,10 @@ module.exports = defineCases({
25
25
  {
26
26
  name: 'the Bootstrap bundle loads — Tooltip is available',
27
27
  run: (ctx) => {
28
- if (!window.__emTestTooltip.available()) {
29
- throw new Error(`Bootstrap bundle failed to load: ${window.__emTestTooltip.error() || '(no require error — wiring bailed earlier)'}`);
28
+ if (!window.__omegaTestTooltip.available()) {
29
+ throw new Error(`Bootstrap bundle failed to load: ${window.__omegaTestTooltip.error() || '(no require error, wiring bailed earlier)'}`);
30
30
  }
31
- ctx.expect(window.__emTestTooltip.available()).toBe(true);
31
+ ctx.expect(window.__omegaTestTooltip.available()).toBe(true);
32
32
  },
33
33
  },
34
34
  {
@@ -51,9 +51,9 @@ module.exports = defineCases({
51
51
  document.body.appendChild(el);
52
52
 
53
53
  // The auto-init observer creates the instance without any consumer code.
54
- await until(() => window.__emTestTooltip.hasInstance('tt-show'));
54
+ await until(() => window.__omegaTestTooltip.hasInstance('tt-show'));
55
55
 
56
- const shown = window.__emTestTooltip.showDirect('tt-show');
56
+ const shown = window.__omegaTestTooltip.showDirect('tt-show');
57
57
  ctx.expect(shown).toBe(true);
58
58
  await until(() => document.querySelector('.tooltip .tooltip-inner'));
59
59
  ctx.expect(document.querySelector('.tooltip .tooltip-inner').textContent).toBe('Hello from @omega.js/desktop');
@@ -80,13 +80,13 @@ module.exports = defineCases({
80
80
  el.setAttribute('data-bs-toggle', 'tooltip');
81
81
  el.setAttribute('data-bs-title', 'before');
82
82
  document.body.appendChild(el);
83
- await until(() => window.__emTestTooltip.hasInstance('tt-retitle'));
83
+ await until(() => window.__omegaTestTooltip.hasInstance('tt-retitle'));
84
84
 
85
85
  el.setAttribute('data-bs-title', 'after');
86
86
  // The observer applies setContent asynchronously (mutation microtask) —
87
87
  // give it a beat, then show and assert the rendered text.
88
88
  await new Promise((r) => setTimeout(r, 100));
89
- ctx.expect(window.__emTestTooltip.showDirect('tt-retitle')).toBe(true);
89
+ ctx.expect(window.__omegaTestTooltip.showDirect('tt-retitle')).toBe(true);
90
90
  await until(() => document.querySelector('.tooltip .tooltip-inner'));
91
91
  ctx.expect(document.querySelector('.tooltip .tooltip-inner').textContent).toBe('after');
92
92
 
@@ -118,7 +118,7 @@ module.exports = defineCases({
118
118
  el.setAttribute('title', 'plain title');
119
119
  document.body.appendChild(el);
120
120
 
121
- await until(() => window.__emTestTooltip.hasInstance('tt-title-only'));
121
+ await until(() => window.__omegaTestTooltip.hasInstance('tt-title-only'));
122
122
 
123
123
  // The loop starved macrotasks — a timer firing IS the proof the
124
124
  // main thread survived the mutation settling.
@@ -129,8 +129,8 @@ module.exports = defineCases({
129
129
  // instance alive, and the tip renders the original text.
130
130
  ctx.expect(el.hasAttribute('title')).toBe(false);
131
131
  ctx.expect(el.getAttribute('data-bs-original-title')).toBe('plain title');
132
- ctx.expect(window.__emTestTooltip.hasInstance('tt-title-only')).toBe(true);
133
- ctx.expect(window.__emTestTooltip.showDirect('tt-title-only')).toBe(true);
132
+ ctx.expect(window.__omegaTestTooltip.hasInstance('tt-title-only')).toBe(true);
133
+ ctx.expect(window.__omegaTestTooltip.showDirect('tt-title-only')).toBe(true);
134
134
  await until(() => document.querySelector('.tooltip .tooltip-inner'));
135
135
  ctx.expect(document.querySelector('.tooltip .tooltip-inner').textContent).toBe('plain title');
136
136
 
@@ -155,11 +155,11 @@ module.exports = defineCases({
155
155
  el.setAttribute('data-bs-toggle', 'tooltip');
156
156
  el.setAttribute('data-bs-title', 'bye');
157
157
  document.body.appendChild(el);
158
- await until(() => window.__emTestTooltip.hasInstance('tt-dispose'));
158
+ await until(() => window.__omegaTestTooltip.hasInstance('tt-dispose'));
159
159
 
160
160
  el.remove();
161
- await until(() => !window.__emTestTooltip.hasInstance('tt-dispose'));
162
- ctx.expect(window.__emTestTooltip.hasInstance('tt-dispose')).toBe(false);
161
+ await until(() => !window.__omegaTestTooltip.hasInstance('tt-dispose'));
162
+ ctx.expect(window.__omegaTestTooltip.hasInstance('tt-dispose')).toBe(false);
163
163
  },
164
164
  },
165
165
  ],
@@ -1,5 +1,6 @@
1
- // Renderer-layer suite — asserts the `window.desktop` surface exposed by preload is shaped
2
- // correctly and that the storage proxy round-trips through IPC into the main store.
1
+ // Renderer-layer suite: asserts the `window.desktop` surface exposed by preload is shaped
2
+ // correctly, that the renderer instance carries it as `omega.desktop`, and that the
3
+ // storage proxy round-trips through IPC into the main store.
3
4
  //
4
5
  // Runs inside a hidden BrowserWindow spawned by the test harness. The renderer harness
5
6
  // reconstructs each `run` function via `new Function('ctx', body)` so the function bodies
@@ -10,7 +11,7 @@ const defineCases = require('../../../vendor/devkit/test/define-cases.js');
10
11
  module.exports = defineCases({
11
12
  type: 'suite',
12
13
  layer: 'renderer',
13
- description: 'window.desktop surface + storage proxy roundtrip',
14
+ description: 'window.desktop surface + omega.desktop + storage proxy roundtrip',
14
15
  tests: [
15
16
  {
16
17
  name: 'window.desktop is exposed and is an object',
@@ -19,6 +20,25 @@ module.exports = defineCases({
19
20
  ctx.expect(window.desktop).toBeTruthy();
20
21
  },
21
22
  },
23
+ {
24
+ // The preload global keeps its name and its shape: everything that
25
+ // crosses to the main process, under main's names
26
+ name: 'window.desktop carries the bridge namespaces, unchanged',
27
+ run: (ctx) => {
28
+ ctx.expect(Object.keys(window.desktop).sort()).toEqual(['analytics', 'autoUpdater', 'context', 'fontawesome', 'ipc', 'logger', 'remoteConfig', 'storage', 'theme', 'usage']);
29
+ },
30
+ },
31
+ {
32
+ // The renderer instance puts the SAME object under `omega.desktop`;
33
+ // `omega.storage` stays the client's page store, the app store is
34
+ // `omega.desktop.storage`
35
+ name: 'the renderer instance\'s omega.desktop IS the preload bridge',
36
+ run: (ctx) => {
37
+ ctx.expect(window.__omegaTestInstance.desktopIsBridge()).toBe(true);
38
+ ctx.expect(window.__omegaTestInstance.desktopKeys()).toEqual(Object.keys(window.desktop).sort());
39
+ ctx.expect(window.__omegaTestInstance.storageIsPageStore()).toBe(true);
40
+ },
41
+ },
22
42
  {
23
43
  name: 'window.desktop.ipc has invoke / on / send',
24
44
  run: (ctx) => {
@@ -32,7 +52,7 @@ module.exports = defineCases({
32
52
  // object across the contextBridge) — docs/ipc.md promises an unsubscribe fn.
33
53
  name: 'ipc.on returns an unsubscribe function (docs contract)',
34
54
  run: (ctx) => {
35
- const off = window.desktop.ipc.on('em-test:noop-channel', () => {});
55
+ const off = window.desktop.ipc.on('omega-test:noop-channel', () => {});
36
56
  ctx.expect(typeof off).toBe('function');
37
57
  off(); // must not throw
38
58
  },
@@ -66,7 +86,7 @@ module.exports = defineCases({
66
86
  {
67
87
  name: 'storage.set + storage.get round-trips through IPC',
68
88
  run: async (ctx) => {
69
- const key = '__em_renderer_test_value';
89
+ const key = '__omega_renderer_test_value';
70
90
  await window.desktop.storage.set(key, { hello: 'world', n: 42 });
71
91
  const value = await window.desktop.storage.get(key);
72
92
  ctx.expect(value).toEqual({ hello: 'world', n: 42 });
@@ -76,7 +96,7 @@ module.exports = defineCases({
76
96
  {
77
97
  name: 'storage.has reports correctly',
78
98
  run: async (ctx) => {
79
- const key = '__em_renderer_has_test';
99
+ const key = '__omega_renderer_has_test';
80
100
  await window.desktop.storage.set(key, 'x');
81
101
  const yes = await window.desktop.storage.has(key);
82
102
  ctx.expect(yes).toBe(true);
@@ -88,7 +108,7 @@ module.exports = defineCases({
88
108
  {
89
109
  name: 'storage.delete removes the key',
90
110
  run: async (ctx) => {
91
- const key = '__em_renderer_delete_test';
111
+ const key = '__omega_renderer_delete_test';
92
112
  await window.desktop.storage.set(key, 'gone');
93
113
  await window.desktop.storage.delete(key);
94
114
  const value = await window.desktop.storage.get(key, 'fallback');
@@ -1,6 +1,6 @@
1
1
  // TEST_EXTENDED_MODE warning — SSOT for consistent messaging.
2
2
  //
3
- // The headline + shape live in @omega.js/devkit (mirrored across @omega.js/backend/BXM/UJM); these
3
+ // The headline + shape live in @omega.js/devkit (shared by every framework); these
4
4
  // detail lines describe @omega.js/desktop's blast radius. Used by the test command (printed to
5
5
  // console + teed to logs/test.log).
6
6
  const { makeExtendedModeWarning } = require('../../vendor/devkit/test/extended-mode-warning.js');
@@ -0,0 +1,56 @@
1
+ // boot-harness: hands the booted main-process instance to the boot test lane's
2
+ // harness. The runner sets OMEGA_TEST_BOOT=1 + OMEGA_TEST_BOOT_HARNESS=<absolute path>
3
+ // + OMEGA_TEST_BOOT_SPEC=<path> before spawning electron; the harness emits
4
+ // __OMEGA_TEST__ JSON lines on stdout (parsed by test/runners/boot.js) then
5
+ // app.exit()s.
6
+ //
7
+ // A runtime env-var path, never a static `require('./test/harness/...')`:
8
+ // @omega.js/desktop is bundled into the consumer's bundle, and a static require would
9
+ // either get inlined (bundling test code into production) or dead-code-eliminated.
10
+ // An env-var path stays external and can only resolve when the runner sets it.
11
+
12
+ const { TEST_EVENT_PREFIX } = require('./test-events.js');
13
+
14
+ /**
15
+ * Start the boot harness against `omega` when this process is a boot test run.
16
+ * @param {object} omega - the initialized main-process instance.
17
+ */
18
+ function startBootHarness(omega) {
19
+ // Only a boot test run carries the flag; every other boot returns here
20
+ if (process.env.OMEGA_TEST_BOOT !== '1') {
21
+ return;
22
+ }
23
+
24
+ global.__omega_instance = omega;
25
+ const harnessPath = process.env.OMEGA_TEST_BOOT_HARNESS;
26
+
27
+ if (!harnessPath) {
28
+ fail('OMEGA_TEST_BOOT=1 but OMEGA_TEST_BOOT_HARNESS not set');
29
+ return;
30
+ }
31
+
32
+ // Defer the harness so the consumer's `omega.initialize().then(() => { ... })`
33
+ // callback gets a chance to run first. @omega.js/desktop doesn't auto-create any
34
+ // windows; the consumer's main.js does it inside .then(). Run synchronously and
35
+ // that callback hasn't fired yet, so `omega.windows.get('main')` would be null.
36
+ // setImmediate flushes the microtask queue (where promise callbacks live)
37
+ // before the boot harness inspects state.
38
+ setImmediate(() => {
39
+ try {
40
+ // A variable specifier, so the bundler leaves the call alone and it
41
+ // resolves at RUNTIME against the path the runner set (see above).
42
+ const harness = require(harnessPath);
43
+ harness.run(omega);
44
+ } catch (e) {
45
+ fail(`boot harness failed to load: ${e.message}`);
46
+ }
47
+ });
48
+ }
49
+
50
+ // Report a fatal harness event on the runner's channel and end the run
51
+ function fail(message) {
52
+ process.stdout.write(`${TEST_EVENT_PREFIX}${JSON.stringify({ event: 'fatal', message })}\n`);
53
+ require('electron').app.exit(1);
54
+ }
55
+
56
+ module.exports = startBootHarness;
@@ -1,5 +1,5 @@
1
- // Runtime mode helpers, shared across all three context Managers (main /
2
- // renderer / preload) and the build-time Manager.
1
+ // Runtime mode helpers: plain functions the process `Omega` classes (src/main.js,
2
+ // src/preload.js, src/renderer.js) and the build-time module (src/build.js) call.
3
3
  //
4
4
  // The environment half is NOT implemented here any more
5
5
  // ([#817](https://github.com/Omega-JS-Stack/omega/issues/817)). It is
@@ -57,20 +57,7 @@ function getVersion() {
57
57
  }
58
58
  }
59
59
 
60
- // Mix the helpers into a Manager constructor's prototype + the constructor itself
61
- // (so `Manager.isTesting()` works statically too). The environment four come from
62
- // the shared module's own attachTo(), so every desktop entry point and every
63
- // sibling framework hangs the identical functions; getVersion() is desktop's and
64
- // is attached beside them. The URL helpers in url-helpers.js depend on
65
- // this.getEnvironment() existing, so this attachTo() runs first.
66
- function attachTo(Manager) {
67
- environment.attachTo(Manager);
68
- Manager.prototype.getVersion = getVersion;
69
- Manager.getVersion = getVersion;
70
- }
71
-
72
60
  module.exports = {
73
- attachTo,
74
61
  isDevelopment: environment.isDevelopment,
75
62
  isProduction: environment.isProduction,
76
63
  isTesting: environment.isTesting,
@@ -21,8 +21,8 @@
21
21
 
22
22
  const { shipPlan, missingShipKeys, shipKeyRefusal } = require('../vendor/devkit/ship-plan.js');
23
23
 
24
- const Manager = new (require('../build.js'));
25
- const logger = Manager.logger('ship-keys');
24
+ const build = require('../build.js');
25
+ const logger = build.logger('ship-keys');
26
26
 
27
27
  /**
28
28
  * Refuse a publish whose declared formats have no credential to ship with.
@@ -36,7 +36,7 @@ const logger = Manager.logger('ship-keys');
36
36
  function assertShipKeys(options) {
37
37
  options = options || {};
38
38
 
39
- const config = options.config || Manager.getConfig();
39
+ const config = options.config || build.getConfig();
40
40
  const plan = shipPlan(config, 'desktop');
41
41
  const missing = missingShipKeys(plan, options.env || process.env);
42
42
 
@@ -0,0 +1,51 @@
1
+ // signing-status: logs whether a PACKAGED app is code-signed, and by whom, so
2
+ // runtime.log answers "did this build ship signed?" without a terminal. Fire and
3
+ // forget: the checks run async and only ever log. An unpackaged (dev or test)
4
+ // boot has nothing signed to report, so it skips.
5
+
6
+ /**
7
+ * Log this app's signing status (packaged apps only).
8
+ * @param {object} logger - the main process's logger.
9
+ */
10
+ function logSigningStatus(logger) {
11
+ try {
12
+ if (!require('electron').app.isPackaged) {
13
+ return;
14
+ }
15
+
16
+ const { execFile } = require('child_process');
17
+
18
+ if (process.platform === 'darwin') {
19
+ const appIndex = process.execPath.indexOf('.app');
20
+ if (appIndex === -1) throw new Error('no .app in execPath');
21
+ const appPath = process.execPath.substring(0, appIndex + 4);
22
+ execFile('codesign', ['--verify', '--deep', '--strict', appPath], (err) => {
23
+ if (err) {
24
+ logger.warn(`signing: NOT signed (${err.message.split('\n')[0]})`);
25
+ return;
26
+ }
27
+ execFile('codesign', ['-dv', appPath], { encoding: 'utf8' }, (e2, stdout, stderr) => {
28
+ const authority = (stderr || '').match(/Authority=(.+)/);
29
+ const adhoc = (stderr || '').includes('Signature=adhoc');
30
+ const label = adhoc ? 'ad-hoc' : (authority ? authority[1] : 'unknown');
31
+ logger.log(`signing: signed (${label})`);
32
+ });
33
+ });
34
+ } else if (process.platform === 'win32') {
35
+ execFile('powershell', ['-NoProfile', '-Command', `(Get-AuthenticodeSignature '${process.execPath}').Status`], { encoding: 'utf8' }, (err, stdout) => {
36
+ const status = (stdout || '').trim();
37
+ if (err || status === 'NotSigned') {
38
+ logger.warn('signing: NOT signed');
39
+ } else {
40
+ logger.log(`signing: signed (${status})`);
41
+ }
42
+ });
43
+ } else {
44
+ logger.log('signing: n/a (Linux has no OS-level code signing)');
45
+ }
46
+ } catch (e) {
47
+ logger.warn(`signing: check failed (${e.message})`);
48
+ }
49
+ }
50
+
51
+ module.exports = logSigningStatus;
@@ -0,0 +1,7 @@
1
+ // The ONE prefix a desktop test harness writes before each JSON event line on
2
+ // stdout (test/harness/main-entry.js, test/harness/boot-entry.js,
3
+ // utils/boot-harness.js) and each runner reads back (test/runners/electron.js,
4
+ // test/runners/boot.js).
5
+ const TEST_EVENT_PREFIX = '__OMEGA_TEST__';
6
+
7
+ module.exports = { TEST_EVENT_PREFIX };
@@ -8,23 +8,23 @@
8
8
  // - main.js — app-level activation suppression on macOS (accessory policy via
9
9
  // app.dock.hide(), so a launching test app never steals keyboard focus)
10
10
  // - test/harness/main-entry.js — same suppression for the spawned harness app,
11
- // which initializes its Manager only after app ready (too late to prevent
11
+ // which initializes its omega instance only after app ready (too late to prevent
12
12
  // the launch activation)
13
13
  //
14
- // Pass the Manager when you have one: its isTesting() reads the environment the
15
- // Manager's own config was baked with. Without one (the harness, pre-Manager
14
+ // Pass the omega instance when you have one: its isTesting() reads the environment
15
+ // its own config was baked with. Without one (the harness, pre-initialize
16
16
  // code) the standalone check reads the process's OMEGA_ENVIRONMENT, the one
17
17
  // input every lane sets ([#817](https://github.com/Omega-JS-Stack/omega/issues/817));
18
18
  // the test runners spawn their children naming `testing`.
19
19
  //
20
20
  // Usage:
21
21
  // const isTestStealth = require('./utils/test-stealth.js');
22
- // if (isTestStealth(manager)) { ... }
22
+ // if (isTestStealth(omega)) { ... }
23
23
 
24
24
  const { isTesting } = require('./mode-helpers.js');
25
25
 
26
- function isTestStealth(manager) {
27
- const testing = manager ? manager.isTesting() : isTesting();
26
+ function isTestStealth(omega) {
27
+ const testing = omega ? omega.isTesting() : isTesting();
28
28
  return testing && process.env.OMEGA_TEST_SHOW !== '1';
29
29
  }
30
30
 
@@ -1,13 +1,14 @@
1
- // Backend URL helpers, shared across all Manager contexts (main / renderer / preload /
2
- // build). Mirror @omega.js/client's contract so @omega.js/desktop apps can hit the same dev/prod backends as
3
- // UJM and BXM consumers.
1
+ // Backend URL helpers: plain functions the process `Omega` classes (main / renderer /
2
+ // preload) call, each passing itself as `context`. Mirror
3
+ // @omega.js/client's contract so @omega.js/desktop apps can hit the same dev/prod backends as
4
+ // @omega.js/web and @omega.js/extension consumers.
4
5
  //
5
6
  // `getEnvironment()` is the SINGLE SOURCE OF TRUTH and lives in src/utils/mode-helpers.js
6
- // (alongside the is*() family; mirrors @omega.js/backend/UJM/BXM). It returns exactly ONE of
7
+ // (alongside the is*() family, the same on every framework). It returns exactly ONE of
7
8
  // 'development' | 'testing' | 'production' (mutually exclusive; testing wins).
8
9
  //
9
- // `getFunctionsUrl()` / `getApiUrl()` / `getWebsiteUrl()` route through
10
- // `this.getEnvironment()` and resolve to LOCAL urls in BOTH development AND testing —
10
+ // `getFunctionsUrl()` / `getApiUrl()` / `getWebsiteUrl()` route through the context's
11
+ // `getEnvironment()` and resolve to LOCAL urls in BOTH development AND testing,
11
12
  // callers normally pass NO argument. An explicit `environment` arg is an override
12
13
  // (used mainly by tests to pin a specific environment's mapping).
13
14
 
@@ -54,9 +55,16 @@ function requiredPort(context, envName, name) {
54
55
  return port;
55
56
  }
56
57
 
57
- function getFunctionsUrl(environment) {
58
- const env = environment || this.getEnvironment();
59
- const projectId = this?.config?.cloud?.config?.projectId;
58
+ /**
59
+ * The Cloud Functions base: the local emulator in development and testing, the
60
+ * project's cloudfunctions.net host in production.
61
+ * @param {object} context - the instance asking (its `config` and `getEnvironment()`).
62
+ * @param {string} [environment] - an override of the running environment.
63
+ * @returns {string} the functions base URL.
64
+ */
65
+ function getFunctionsUrl(context, environment) {
66
+ const env = environment || context.getEnvironment();
67
+ const projectId = context.config?.cloud?.config?.projectId;
60
68
 
61
69
  if (!projectId) {
62
70
  throw new Error('cloud.config.projectId not set in config/omega.json5');
@@ -66,15 +74,22 @@ function getFunctionsUrl(environment) {
66
74
  // same three-step chain getApiUrl() walks: the OMEGA_*_PORT env channel (N7),
67
75
  // then the baked map, then the classic default.
68
76
  if (env === 'development' || env === 'testing') {
69
- const port = requiredPort(this, 'OMEGA_FUNCTIONS_PORT', 'functions');
77
+ const port = requiredPort(context, 'OMEGA_FUNCTIONS_PORT', 'functions');
70
78
  return `http://localhost:${port}/${projectId}/us-central1`;
71
79
  }
72
80
 
73
81
  return `https://us-central1-${projectId}.cloudfunctions.net`;
74
82
  }
75
83
 
76
- function getApiUrl(environment) {
77
- const env = environment || this.getEnvironment();
84
+ /**
85
+ * The API base: the local stack in development and testing, the brand's api
86
+ * subdomain in production.
87
+ * @param {object} context - the instance asking (its `config` and `getEnvironment()`).
88
+ * @param {string} [environment] - an override of the running environment.
89
+ * @returns {string} the API base URL.
90
+ */
91
+ function getApiUrl(context, environment) {
92
+ const env = environment || context.getEnvironment();
78
93
 
79
94
  // Local for development OR testing; production otherwise. Mirrors
80
95
  // @omega.js/backend's getApiUrl (N7): a resolved OMEGA_HTTPS_PORT means
@@ -82,16 +97,16 @@ function getApiUrl(environment) {
82
97
  // hosting emulator (env port, then baked port). Neither resolved is a broken
83
98
  // build, not a case to assume the classic 5002 through (#834).
84
99
  if (env === 'development' || env === 'testing') {
85
- const httpsPort = localPort(this, 'OMEGA_HTTPS_PORT', 'https');
100
+ const httpsPort = localPort(context, 'OMEGA_HTTPS_PORT', 'https');
86
101
  return httpsPort
87
102
  ? `https://localhost:${httpsPort}`
88
- : `http://localhost:${requiredPort(this, 'OMEGA_HOSTING_PORT', 'hosting')}`;
103
+ : `http://localhost:${requiredPort(context, 'OMEGA_HOSTING_PORT', 'hosting')}`;
89
104
  }
90
105
 
91
106
  // Prod: api.<brand host>. Mirrors @omega.js/client.getApiUrl. Never derive
92
107
  // from authDomain — it is an auth concern (the brand host, with /__/auth/*
93
108
  // self-hosted at build time) and must stay free to change independently.
94
- const brandUrl = this?.config?.brand?.url;
109
+ const brandUrl = context.config?.brand?.url;
95
110
  if (!brandUrl) {
96
111
  throw new Error('brand.url not set in config/omega.json5');
97
112
  }
@@ -113,20 +128,25 @@ function getApiUrl(environment) {
113
128
  // Prod → `config.brand.url`. Use this whenever app code wants to link out to "the
114
129
  // website" (Help → Website tray/menu items, "Open in browser," billing portal
115
130
  // landings) so dev runs don't punch out to the real domain.
116
- function getWebsiteUrl(environment) {
117
- const env = environment || this.getEnvironment();
131
+ /**
132
+ * @param {object} context - the instance asking (its `config` and `getEnvironment()`).
133
+ * @param {string} [environment] - an override of the running environment.
134
+ * @returns {string} the website origin (dev) or brand.url (production).
135
+ */
136
+ function getWebsiteUrl(context, environment) {
137
+ const env = environment || context.getEnvironment();
118
138
 
119
139
  // Local for development OR testing; production otherwise.
120
140
  if (env === 'development' || env === 'testing') {
121
- const origin = this?.config?.dev?.origin;
141
+ const origin = context.config?.dev?.origin;
122
142
  if (origin) {
123
143
  return origin;
124
144
  }
125
145
 
126
- return `https://localhost:${requiredPort(this, 'OMEGA_WEBSITE_PORT', 'website')}`;
146
+ return `https://localhost:${requiredPort(context, 'OMEGA_WEBSITE_PORT', 'website')}`;
127
147
  }
128
148
 
129
- const url = this?.config?.brand?.url;
149
+ const url = context.config?.brand?.url;
130
150
  if (!url) {
131
151
  throw new Error('brand.url not set in config/omega.json5');
132
152
  }
@@ -134,19 +154,25 @@ function getWebsiteUrl(environment) {
134
154
  }
135
155
 
136
156
  // Sign-in URL that round-trips an auth token back to the app. Points at the brand
137
- // website's /signin page (UJM), chained through its /token page so a successful login
157
+ // website's /signin page, chained through its /token page so a successful login
138
158
  // mints a Firebase custom token and redirects to `<brand.id>://auth/token` — the
139
- // deep-link built-in that hands the token to client-bridge (signInWithCustomToken).
159
+ // deep-link built-in that hands the token to lib/auth.js (signInWithCustomToken).
140
160
  // Same env split as getWebsiteUrl: dev/test → the local website, prod → brand.url.
141
161
  // The token page redirects with ?authToken=<token> — the ONE modern shape the
142
- // auth/token route reads (legacy-app formats are UJM's concern, not @omega.js/desktop's).
162
+ // auth/token route reads (older formats are not read).
143
163
  //
144
164
  // `returnUrl` overrides the final hop (default: `<brand.id>://auth/token`). Used by
145
165
  // lib/auth-flow.js in dev, where the custom scheme isn't OS-registered — the flow
146
166
  // returns to a loopback HTTP listener instead (RFC 8252 §7.3).
147
- function getAuthUrl(environment, returnUrl) {
148
- const site = this.getWebsiteUrl(environment);
149
- const brandId = this?.config?.brand?.id;
167
+ /**
168
+ * @param {object} context - the instance asking (its `config` and `getEnvironment()`).
169
+ * @param {string} [environment] - an override of the running environment.
170
+ * @param {string} [returnUrl] - the final hop, `<brand.id>://auth/token` by default.
171
+ * @returns {string} the sign-in URL.
172
+ */
173
+ function getAuthUrl(context, environment, returnUrl) {
174
+ const site = getWebsiteUrl(context, environment);
175
+ const brandId = context.config?.brand?.id;
150
176
  if (!brandId) {
151
177
  throw new Error('brand.id not set in config/omega.json5');
152
178
  }
@@ -159,23 +185,7 @@ function getAuthUrl(environment, returnUrl) {
159
185
  return signinUrl.toString();
160
186
  }
161
187
 
162
- // Mix the URL helpers into a Manager constructor's prototype + the constructor itself.
163
- // getEnvironment() is NOT attached here — it's the SSOT in src/utils/mode-helpers.js.
164
- // These helpers call `this.getEnvironment()`, so mode-helpers' attachTo() must run before
165
- // (or alongside) this one — every Manager entry point attaches mode-helpers first.
166
- function attachTo(Manager) {
167
- Manager.prototype.getFunctionsUrl = getFunctionsUrl;
168
- Manager.prototype.getApiUrl = getApiUrl;
169
- Manager.prototype.getWebsiteUrl = getWebsiteUrl;
170
- Manager.prototype.getAuthUrl = getAuthUrl;
171
- Manager.getFunctionsUrl = getFunctionsUrl;
172
- Manager.getApiUrl = getApiUrl;
173
- Manager.getWebsiteUrl = getWebsiteUrl;
174
- Manager.getAuthUrl = getAuthUrl;
175
- }
176
-
177
188
  module.exports = {
178
- attachTo,
179
189
  localPort,
180
190
  requiredPort,
181
191
  getFunctionsUrl,
@@ -0,0 +1,44 @@
1
+ // user-agent: the global user agent fallback every @omega.js/desktop app carries,
2
+ // so web requests (BrowserWindow loads, fetch, electron-updater downloads) send a
3
+ // branded UA: Mozilla parsers see a normal Chrome UA and the app's own
4
+ // server-side telemetry sees `{brand.name}/{app.version}`. Merge tags use
5
+ // node-powertools.template (single-curly syntax). A consumer overrides it by
6
+ // re-setting `app.userAgentFallback` from its main.js after initialize().
7
+
8
+ const TEMPLATES = {
9
+ darwin: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) {brand.name}/{app.version} Chrome/{chrome} Safari/537.36',
10
+ win32: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) {brand.name}/{app.version} Chrome/{chrome} Safari/537.36',
11
+ linux: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) {brand.name}/{app.version} Chrome/{chrome} Safari/537.36',
12
+ };
13
+
14
+ /**
15
+ * Set `app.userAgentFallback` from the brand and this process's versions.
16
+ * @param {object} omega - the main-process instance (its config, getVersion() and logger).
17
+ * @returns {string} the user agent it set.
18
+ */
19
+ function applyUserAgent(omega) {
20
+ const { template } = require('node-powertools');
21
+ const { app } = require('electron');
22
+
23
+ const ua = template(TEMPLATES[process.platform] || TEMPLATES.linux, {
24
+ brand: {
25
+ name: omega.config.brand.name,
26
+ id: omega.config.brand.id,
27
+ },
28
+ app: {
29
+ version: omega.getVersion(),
30
+ },
31
+ chrome: process.versions.chrome,
32
+ electron: process.versions.electron,
33
+ node: process.versions.node,
34
+ platform: process.platform,
35
+ arch: process.arch,
36
+ });
37
+
38
+ app.userAgentFallback = ua;
39
+ omega.logger.log(`userAgent: ${ua}`);
40
+
41
+ return ua;
42
+ }
43
+
44
+ module.exports = applyUserAgent;
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Schema resolution engine — extracted verbatim from @omega.js/backend's
3
- * src/manager/helpers/user.js, with ONE change: the '$uuid'/'$randomId'/'$apiKey'
2
+ * Schema resolution engine, extracted verbatim from @omega.js/backend's former
3
+ * user helper with ONE change: the '$uuid'/'$randomId'/'$apiKey'
4
4
  * value generators are injected via ctx.generators instead of being required
5
- * in-module. Hosts that can generate them (@omega.js/backend, Node) inject real generators;
5
+ * in-module. Hosts that can generate them (@omega.js/backend, Node) inject real generators (src/omega/services/user.js);
6
6
  * hosts that can't (@omega.js/client, browser) pass none and the fields resolve to
7
7
  * null — the doc's real values always come from the backend.
8
8
  *