@omega.js/desktop 0.50.0 → 0.51.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 (267) hide show
  1. package/README.md +1 -1
  2. package/dist/assets/css/tokens/_index.scss +1 -1
  3. package/dist/assets/themes/base/_includes/frontend/sections/account-section-header.html +4 -1
  4. package/dist/assets/themes/base/_includes/frontend/sections/footer.html +13 -6
  5. package/dist/assets/themes/base/_includes/frontend/sections/nav.html +10 -8
  6. package/dist/assets/themes/base/_includes/global/sections/account.html +3 -1
  7. package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +12 -8
  8. package/dist/assets/themes/base/_includes/global/sections/app-topbar.html +10 -6
  9. package/dist/assets/themes/base/_includes/global/sections/page-header.html +8 -4
  10. package/dist/assets/themes/base/_layouts/backend/pages/dashboard/index.html +24 -24
  11. package/dist/assets/themes/base/_layouts/frontend/pages/about.html +10 -10
  12. package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +35 -35
  13. package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +4 -4
  14. package/dist/assets/themes/base/_layouts/frontend/pages/auth/signin.html +1 -1
  15. package/dist/assets/themes/base/_layouts/frontend/pages/auth/signup.html +4 -4
  16. package/dist/assets/themes/base/_layouts/frontend/pages/contact.html +3 -3
  17. package/dist/assets/themes/base/_layouts/frontend/pages/download.html +34 -33
  18. package/dist/assets/themes/base/_layouts/frontend/pages/extension/index.html +11 -11
  19. package/dist/assets/themes/base/_layouts/frontend/pages/legal/document.html +1 -1
  20. package/dist/assets/themes/base/_layouts/frontend/pages/status.html +1 -1
  21. package/dist/assets/themes/base/_layouts/frontend/pages/team/index.html +9 -7
  22. package/dist/assets/themes/base/_layouts/frontend/pages/team/member.html +5 -3
  23. package/dist/assets/themes/base/_sections/about/letter/section.html +1 -1
  24. package/dist/assets/themes/base/_sections/about/letter/section.json5 +4 -4
  25. package/dist/assets/themes/base/_sections/marketing/bento/section.html +1 -1
  26. package/dist/assets/themes/base/_sections/marketing/bento/section.json5 +15 -15
  27. package/dist/assets/themes/base/_sections/marketing/cta/section.json5 +1 -1
  28. package/dist/assets/themes/base/_sections/marketing/hero/section.html +6 -6
  29. package/dist/assets/themes/base/_sections/marketing/hero/section.json5 +10 -10
  30. package/dist/assets/themes/base/_sections/marketing/product-demo/section.html +1 -1
  31. package/dist/assets/themes/base/_sections/marketing/product-demo/section.json5 +2 -2
  32. package/dist/assets/themes/base/_sections/marketing/stats/section.html +1 -1
  33. package/dist/assets/themes/base/_sections/marketing/stats/section.json5 +5 -5
  34. package/dist/assets/themes/base/_sections/marketing/trusted-by/section.html +1 -1
  35. package/dist/assets/themes/base/_sections/marketing/trusted-by/section.json5 +2 -2
  36. package/dist/assets/themes/neobrutalism/_layouts/frontend/pages/index.html +10 -10
  37. package/dist/assets/themes/newsflash/_layouts/frontend/pages/index.html +10 -10
  38. package/dist/assets/themes/newsflash/_sections/marketing/desks/section.html +2 -2
  39. package/dist/assets/themes/newsflash/_sections/marketing/desks/section.json5 +4 -4
  40. package/dist/build.js +69 -28
  41. package/dist/cli-run.js +20 -13
  42. package/dist/cli.js +12 -7
  43. package/dist/commands/build.js +0 -2
  44. package/dist/commands/deploy.js +116 -44
  45. package/dist/commands/finalize-release.js +5 -4
  46. package/dist/commands/launch.js +12 -7
  47. package/dist/commands/lib/deploy-precheck.js +66 -34
  48. package/dist/commands/lib/ensure-target.js +71 -11
  49. package/dist/commands/package.js +0 -1
  50. package/dist/commands/publish.js +11 -4
  51. package/dist/commands/release.js +99 -252
  52. package/dist/commands/runner.js +42 -5
  53. package/dist/commands/sign-windows.js +46 -15
  54. package/dist/commands/test.js +4 -3
  55. package/dist/commands/validate-certs.js +291 -115
  56. package/dist/config/page-template.html +4 -0
  57. package/dist/defaults/.github/workflows/build.yml +144 -64
  58. package/dist/defaults/AGENTS.md +3 -2
  59. package/dist/defaults/_.gitignore +4 -2
  60. package/dist/defaults/config/certs/README.md +25 -45
  61. package/dist/defaults/config/omega.json5 +66 -32
  62. package/dist/defaults/hooks/deploy/pre.js +10 -0
  63. package/dist/defaults/src/assets/scss/main.scss +12 -2
  64. package/dist/defaults/src/integrations/tray/index.js +1 -1
  65. package/dist/gulp/main.js +13 -25
  66. package/dist/gulp/tasks/audit.js +18 -6
  67. package/dist/gulp/tasks/build-config.js +181 -60
  68. package/dist/gulp/tasks/bundle.js +108 -36
  69. package/dist/gulp/tasks/release.js +86 -4
  70. package/dist/gulp/tasks/sass.js +11 -0
  71. package/dist/hooks/lib/notarize-tools.js +137 -0
  72. package/dist/hooks/notarize-artifacts.js +57 -0
  73. package/dist/hooks/notarize.js +59 -8
  74. package/dist/lib/auth-persistence.js +25 -0
  75. package/dist/lib/client-bridge.js +11 -8
  76. package/dist/lib/deep-link.js +15 -8
  77. package/dist/lib/protocol.js +7 -1
  78. package/dist/lib/restart-manager/install.js +6 -3
  79. package/dist/lib/sign-helpers/auto-unlock.js +65 -27
  80. package/dist/lib/sign-helpers/console-lock.js +34 -0
  81. package/dist/lib/sign-helpers/exec-with-limit.js +68 -0
  82. package/dist/lib/sign-helpers/resolve-icons.js +6 -4
  83. package/dist/lib/tray.js +7 -6
  84. package/dist/main.js +16 -0
  85. package/dist/preload.js +8 -0
  86. package/dist/renderer.js +16 -4
  87. package/dist/runner/job-started.js +104 -0
  88. package/dist/test/fixtures/consumer-app/config/omega.json5 +7 -0
  89. package/dist/test/fixtures/consumer-app/package.json +1 -1
  90. package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +7 -1
  91. package/dist/test/harness/main-entry.js +2 -1
  92. package/dist/test/harness/renderer-preload.js +12 -3
  93. package/dist/test/runners/boot.js +101 -11
  94. package/dist/test/runners/electron.js +1 -1
  95. package/dist/test/suites/boot/consumer-app-boots.test.js +54 -0
  96. package/dist/test/suites/build/audit.test.js +45 -6
  97. package/dist/test/suites/build/auth-persistence-resolve.test.js +119 -0
  98. package/dist/test/suites/build/auto-unlock.test.js +105 -0
  99. package/dist/test/suites/build/boot-runner-timeout.test.js +253 -0
  100. package/dist/test/suites/build/brand-scss.test.js +106 -0
  101. package/dist/test/suites/build/build-config.test.js +146 -36
  102. package/dist/test/suites/build/build-json-bake.test.js +245 -0
  103. package/dist/test/suites/build/build-verbs.test.js +48 -15
  104. package/dist/test/suites/build/build-workflow-jobs.test.js +190 -0
  105. package/dist/test/suites/build/cli.test.js +32 -10
  106. package/dist/test/suites/build/config-schema.test.js +4 -4
  107. package/dist/test/suites/build/console-lock.test.js +51 -0
  108. package/dist/test/suites/build/defaults-scaffold.test.js +71 -2
  109. package/dist/test/suites/build/deploy-direct.test.js +241 -0
  110. package/dist/test/suites/build/deploy-dispatch.test.js +287 -0
  111. package/dist/test/suites/build/deploy-hook.test.js +169 -0
  112. package/dist/test/suites/build/ensure-target.test.js +14 -2
  113. package/dist/test/suites/build/env-delivery.test.js +19 -10
  114. package/dist/test/suites/build/env-watch.test.js +18 -7
  115. package/dist/test/suites/build/esm-only-dependency.test.js +127 -0
  116. package/dist/test/suites/build/exec-with-limit.test.js +53 -0
  117. package/dist/test/suites/build/finalize-release.test.js +2 -2
  118. package/dist/test/suites/build/get-config.test.js +120 -8
  119. package/dist/test/suites/build/github-utils.test.js +12 -6
  120. package/dist/test/suites/build/license-stamp.test.js +6 -4
  121. package/dist/test/suites/build/manager.test.js +88 -68
  122. package/dist/test/suites/build/manifest-deps.test.js +116 -0
  123. package/dist/test/suites/build/merge-line-files.test.js +27 -4
  124. package/dist/test/suites/build/notarize-artifacts.test.js +135 -0
  125. package/dist/test/suites/build/notarize-tools.test.js +38 -0
  126. package/dist/test/suites/build/notarize.test.js +207 -0
  127. package/dist/test/suites/build/release-pipeline.test.js +38 -60
  128. package/dist/test/suites/build/release-skipped-upload.test.js +107 -0
  129. package/dist/test/suites/build/resolve-icons.test.js +35 -35
  130. package/dist/test/suites/build/runner-job-guard.test.js +182 -0
  131. package/dist/test/suites/build/runner.test.js +25 -2
  132. package/dist/test/suites/build/sentry.test.js +8 -3
  133. package/dist/test/suites/build/setup-scripts.test.js +3 -0
  134. package/dist/test/suites/build/sign-windows.test.js +92 -8
  135. package/dist/test/suites/build/test-stealth.test.js +17 -11
  136. package/dist/test/suites/build/url-helpers.test.js +37 -17
  137. package/dist/test/suites/build/validate-certs.test.js +428 -55
  138. package/dist/test/suites/build/validate-config.test.js +3 -3
  139. package/dist/test/suites/main/auth-flow.test.js +12 -0
  140. package/dist/test/suites/main/auth-persistence.test.js +14 -17
  141. package/dist/test/suites/main/auto-updater.test.js +2 -2
  142. package/dist/test/suites/main/boot-sequence.test.js +1 -1
  143. package/dist/test/suites/main/client-bridge.integration.test.js +5 -82
  144. package/dist/test/suites/main/client-bridge.test.js +19 -6
  145. package/dist/test/suites/main/deep-link.test.js +54 -0
  146. package/dist/test/suites/main/startup-paths-and-ua.test.js +1 -1
  147. package/dist/test/suites/main/url-helpers.test.js +81 -72
  148. package/dist/test/suites/renderer/cross-context-helpers.test.js +19 -16
  149. package/dist/utils/build-pipeline.js +10 -10
  150. package/dist/utils/github.js +12 -51
  151. package/dist/utils/load-env.js +66 -0
  152. package/dist/utils/mode-helpers.js +43 -111
  153. package/dist/utils/platform.js +37 -0
  154. package/dist/utils/runner-env.js +2 -1
  155. package/dist/utils/runner-job-guard.js +149 -0
  156. package/dist/utils/ship-keys.js +52 -0
  157. package/dist/utils/test-stealth.js +5 -3
  158. package/dist/utils/url-helpers.js +33 -17
  159. package/dist/vendor/config/bundle-id.js +53 -0
  160. package/dist/vendor/config/client-config.js +141 -0
  161. package/dist/vendor/config/company.js +334 -15
  162. package/dist/vendor/config/dev-facts.js +48 -0
  163. package/dist/vendor/config/env-delivery.js +231 -9
  164. package/dist/vendor/config/env-retired.js +137 -0
  165. package/dist/vendor/config/env-rules.js +22 -3
  166. package/dist/vendor/config/env-schema.js +234 -117
  167. package/dist/vendor/config/env.js +55 -26
  168. package/dist/vendor/config/environment.js +189 -0
  169. package/dist/vendor/config/hooks.js +13 -11
  170. package/dist/vendor/config/index.js +121 -44
  171. package/dist/vendor/config/load.js +366 -115
  172. package/dist/vendor/config/merge.js +2 -2
  173. package/dist/vendor/config/order.js +3 -3
  174. package/dist/vendor/config/platforms.js +276 -0
  175. package/dist/vendor/config/repo.js +226 -104
  176. package/dist/vendor/config/retired-keys.js +232 -27
  177. package/dist/vendor/config/schema.js +525 -99
  178. package/dist/vendor/config/site-global.js +63 -53
  179. package/dist/vendor/config/targets.js +187 -0
  180. package/dist/vendor/config/validate.js +119 -59
  181. package/dist/vendor/devkit/argv.js +118 -0
  182. package/dist/vendor/devkit/attach-log-file.js +21 -13
  183. package/dist/vendor/devkit/brand-tokens.js +278 -0
  184. package/dist/vendor/devkit/brand-version.js +264 -0
  185. package/dist/vendor/devkit/build-json.js +91 -0
  186. package/dist/vendor/devkit/bundle.js +48 -0
  187. package/dist/vendor/devkit/certificate-expiry.js +108 -0
  188. package/dist/vendor/devkit/certs.js +16 -194
  189. package/dist/vendor/devkit/ci-workflows.js +124 -8
  190. package/dist/vendor/devkit/cli-router.js +3 -3
  191. package/dist/vendor/devkit/defaults-engine.js +69 -7
  192. package/dist/vendor/devkit/deploy-follow.js +297 -0
  193. package/dist/vendor/devkit/deploy-precheck.js +23 -8
  194. package/dist/vendor/devkit/deploy-record.js +11 -27
  195. package/dist/vendor/devkit/deploy-snapshot.js +661 -0
  196. package/dist/vendor/devkit/deploy.js +445 -75
  197. package/dist/vendor/devkit/git-auth.js +73 -0
  198. package/dist/vendor/devkit/git-remote.js +95 -0
  199. package/dist/vendor/devkit/github-repo.js +290 -0
  200. package/dist/vendor/devkit/local.js +47 -0
  201. package/dist/vendor/devkit/merge-line-files.js +23 -16
  202. package/dist/vendor/devkit/omega-bin.js +18 -3
  203. package/dist/vendor/devkit/pack-local.js +391 -0
  204. package/dist/vendor/devkit/preludes/index.js +120 -0
  205. package/dist/vendor/devkit/preludes/origin-heal.js +156 -0
  206. package/dist/vendor/devkit/service-account.js +43 -0
  207. package/dist/vendor/devkit/ship-plan.js +112 -0
  208. package/dist/vendor/devkit/signing-env.js +180 -0
  209. package/dist/vendor/devkit/signing-tree.js +92 -0
  210. package/dist/vendor/devkit/target-seams.js +142 -0
  211. package/dist/vendor/devkit/target-secrets.js +235 -50
  212. package/dist/vendor/devkit/test/esm-only-fixture.js +48 -0
  213. package/dist/vendor/devkit/test/fixtures/esm-only-package/browser.js +19 -0
  214. package/dist/vendor/devkit/test/fixtures/esm-only-package/index.js +20 -0
  215. package/dist/vendor/devkit/test/fixtures/esm-only-package/package.json +13 -0
  216. package/dist/vendor/monitoring/env.js +20 -10
  217. package/dist/vendor/monitoring/main.js +1 -1
  218. package/dist/vendor/monitoring/preload.js +1 -1
  219. package/dist/vendor/monitoring/renderer.js +1 -1
  220. package/docs/analytics.md +1 -1
  221. package/docs/auto-updater.md +5 -5
  222. package/docs/boot-sequence.md +1 -1
  223. package/docs/build-system.md +15 -7
  224. package/docs/client-bridge.md +9 -7
  225. package/docs/config-schema.md +4 -4
  226. package/docs/css.md +8 -2
  227. package/docs/deep-link.md +12 -4
  228. package/docs/environment-detection.md +32 -24
  229. package/docs/hooks.md +3 -1
  230. package/docs/icons.md +7 -7
  231. package/docs/index.md +61 -23
  232. package/docs/installer-options.md +24 -21
  233. package/docs/logging.md +5 -5
  234. package/docs/releasing.md +25 -17
  235. package/docs/runner.md +40 -5
  236. package/docs/shared/brands.md +12 -6
  237. package/docs/shared/breaking-changes.md +375 -21
  238. package/docs/shared/config.md +757 -199
  239. package/docs/shared/deploys.md +194 -91
  240. package/docs/shared/icons.md +18 -0
  241. package/docs/shared/local-dev.md +24 -6
  242. package/docs/shared/logging.md +9 -6
  243. package/docs/shared/monitoring.md +27 -13
  244. package/docs/shared/publishing.md +3 -3
  245. package/docs/shared/rulings.md +2 -2
  246. package/docs/shared/testing.md +1 -1
  247. package/docs/shared/theming.md +26 -1
  248. package/docs/shared/translation.md +49 -7
  249. package/docs/shared/updates.md +1 -1
  250. package/docs/signing.md +59 -33
  251. package/docs/test-framework.md +10 -5
  252. package/docs/themes.md +15 -1
  253. package/package.json +18 -12
  254. package/bin/omega-desktop +0 -2
  255. package/dist/commands/push-secrets.js +0 -141
  256. package/dist/test/suites/build/deliver-certs.test.js +0 -95
  257. package/dist/test/suites/build/derive-signing-env.test.js +0 -122
  258. package/dist/test/suites/build/push-secrets.test.js +0 -226
  259. package/dist/test/suites/build/resolve-signing-cert.test.js +0 -342
  260. package/dist/utils/deliver-certs.js +0 -69
  261. package/dist/utils/derive-signing-env.js +0 -56
  262. package/dist/utils/resolve-signing-cert.js +0 -175
  263. package/dist/vendor/config/desktop-artifacts.js +0 -110
  264. package/dist/vendor/config/instances.js +0 -208
  265. /package/dist/defaults/config/icons/{macos → mac}/dmg.png +0 -0
  266. /package/dist/defaults/config/icons/{macos → mac}/icon.png +0 -0
  267. /package/dist/defaults/config/icons/{macos → mac}/tray.png +0 -0
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * One merge behavior at every level of the hierarchy:
5
5
  *
6
- * framework defaults ← company ← brand shared ← brand targets.<type>
7
- * ← local shared ← local targets.<type>
6
+ * framework defaults ← company ← brand shared ← brand targets.<name>
7
+ * ← local shared ← local targets.<name>
8
8
  *
9
9
  * Semantics:
10
10
  * - Plain objects merge recursively; every other value (string, number,
@@ -36,14 +36,14 @@ const { parseRoot } = require('./edit.js');
36
36
  // manager-owned block (#484 retired `testing`: no schema rule, and the testing
37
37
  // service reads no config at all, so converters were carrying a dead key).
38
38
  const CANONICAL_TOP_LEVEL_ORDER = [
39
- 'enabled', 'parent', 'brand', 'url', 'company', 'socials', 'account', 'local', 'ports',
40
- 'repo', 'github', 'domain',
39
+ 'enabled', 'brand', 'url', 'type', 'company', 'socials', 'account', 'local', 'ports',
40
+ 'repo', 'domain',
41
41
  'edge', 'cloud', 'captcha', 'analytics',
42
42
  'monitoring', 'advertising', 'features', 'payment', 'connections', 'sponsorships',
43
43
  'marketing', 'blog', 'devlog', 'reviews', 'seo', 'search',
44
44
  'dataRequest', 'forms', 'inbound',
45
45
  'server', 'assets', 'directory',
46
- 'certificates', 'theme', 'ai', 'translation', 'client', 'migrations', 'targets',
46
+ 'certificates', 'publishing', 'theme', 'ai', 'translation', 'client', 'migrations', 'targets',
47
47
  ];
48
48
 
49
49
  /**
@@ -0,0 +1,276 @@
1
+ /**
2
+ * @omega.js/config platforms: the ONE shipping vocabulary and the ONE format
3
+ * table ([#867](https://github.com/Omega-JS-Stack/omega/issues/867)), the
4
+ * successor of desktop-artifacts.js.
5
+ *
6
+ * The vocabulary is the CLIENT's (@omega.js/client's `getPlatform()` /
7
+ * `getBrowser()`): platforms `mac`, `windows`, `linux`, `chrome`, `firefox`,
8
+ * `edge`; formats `dmg`, `nsis`, `deb`, `appimage`, `snap`, `zip`, `store`.
9
+ * `mac`, never `macos`, because that is the word a stored login record, a
10
+ * download card and a `/download/<platform>` URL already carry. Node's
11
+ * `darwin`/`win32` and electron-builder's `mac`/`win`/`AppImage`/`nsis` are
12
+ * FOREIGN vocabularies, each translated at exactly one point (the desktop
13
+ * framework's `utils/platform.js` for Node's, its `gulp/tasks/build-config.js`
14
+ * for electron-builder's).
15
+ *
16
+ * Two things live here, and every target reads them the same way:
17
+ *
18
+ * 1. PLATFORMS: what a target can ship to at all.
19
+ * 2. FORMATS: per target, platform and format, what that format IS
20
+ * (`kind: 'asset'` = a file on the brand's releases repo, with an `ext`;
21
+ * `kind: 'store'` = a publish to somebody's store), the env keys it
22
+ * cannot ship without (`requires`), and the per-listing CONFIG paths a
23
+ * store needs before it can accept an upload (`listing`, #893: the ids
24
+ * are config, never .env keys).
25
+ *
26
+ * A brand DECLARES what it ships in one shape on both targets:
27
+ * `targets.<name>.platforms.<platform>.formats.<format>`. Presence is the
28
+ * switch, every platform and format defaults ON, and a default is dropped with
29
+ * `false` (the `certificates: false` idiom). Per-format settings live inside
30
+ * the format (`linux.formats.snap.channels`,
31
+ * `firefox.formats.store.channel`), which is why the declaration is an object
32
+ * and not a list.
33
+ *
34
+ * Everything that ships derives from here: the desktop build's electron-builder
35
+ * target lists, the website's `/download/<platform>/<format>` links, and the
36
+ * manage walk's per-brand list of ship credentials.
37
+ */
38
+
39
+ const { ENV_SCHEMA } = require('./env-schema.js');
40
+ const { requiredWhenHolds } = require('./env-rules.js');
41
+
42
+ // What each target can ship to, in the order it offers them. The FIRST platform
43
+ // entry's first format is what a bare `/download/<platform>` leads with.
44
+ const PLATFORMS = {
45
+ desktop: ['mac', 'windows', 'linux'],
46
+ extension: ['chrome', 'firefox', 'edge'],
47
+ };
48
+
49
+ /**
50
+ * The Windows signing keys, read off the env schema rather than restated: the
51
+ * schema already gates each one on `platforms.windows.signing.*` (#891 pins
52
+ * them to the strategy and cloud provider that owns them), so the nsis format
53
+ * names THAT set and `formatKeys` narrows it per brand. SIGNTOOL_PATH is
54
+ * deliberately not in it: it is where signtool.exe sits on the runner, gated by
55
+ * nothing, and nobody mints it on a store page.
56
+ * @returns {string[]} Key names, in schema order.
57
+ */
58
+ function windowsSigningKeys() {
59
+ return ENV_SCHEMA
60
+ .filter((entry) => typeof entry.requiredWhen === 'string' && entry.requiredWhen.startsWith('platforms.windows.signing.'))
61
+ .map((entry) => entry.name);
62
+ }
63
+
64
+ // Every format each platform ships, in offer order. `requires` names env keys
65
+ // (the env schema is the one home of what each is and where it is minted);
66
+ // `listing` names CONFIG paths (#893). A `store` also carries the two facts a
67
+ // human needs when its listing does not exist yet: the store's `label` and the
68
+ // `console` page that creates the listing, so the manage walk's Enter-to-open
69
+ // ask and the publish's manual step read one home instead of two tables.
70
+ //
71
+ // Deliberately absent on desktop: the mac auto-update ZIP. electron-updater
72
+ // fetches it from the feed and nobody links it, so it is a build detail of the
73
+ // mac leg rather than something a brand declares.
74
+ const FORMATS = {
75
+ desktop: {
76
+ mac: {
77
+ // Apple's material (certificates, notarization keys) is the certificates
78
+ // service's, not a per-format requirement: one Apple identity signs every
79
+ // mac format the brand ever adds.
80
+ dmg: { kind: 'asset', ext: 'dmg', requires: [], listing: [] },
81
+ },
82
+ windows: {
83
+ nsis: { kind: 'asset', ext: 'exe', requires: windowsSigningKeys(), listing: [] },
84
+ },
85
+ linux: {
86
+ deb: { kind: 'asset', ext: 'deb', requires: [], listing: [] },
87
+ appimage: { kind: 'asset', ext: 'AppImage', requires: [], listing: [] },
88
+ // The Snap Store publishes the snap, so it is never a release asset and
89
+ // has no versionless filename to spell. Its listing is the snap NAME,
90
+ // registered with the same credentials that publish, so there is no id
91
+ // to collect before the first upload.
92
+ snap: { kind: 'store', requires: ['SNAPCRAFT_STORE_CREDENTIALS'], listing: [], label: 'Snap Store', console: 'https://snapcraft.io/account' },
93
+ },
94
+ },
95
+ extension: {
96
+ chrome: {
97
+ zip: { kind: 'asset', ext: 'zip', requires: [], listing: [] },
98
+ store: { kind: 'store', requires: ['CHROME_CLIENT_ID', 'CHROME_CLIENT_SECRET', 'CHROME_REFRESH_TOKEN'], listing: ['listings.chrome.id'], label: 'Chrome Web Store', console: 'https://chrome.google.com/webstore/devconsole' },
99
+ },
100
+ firefox: {
101
+ zip: { kind: 'asset', ext: 'zip', requires: [], listing: [] },
102
+ // Firefox's id IS the manifest's gecko id, so a brand that declared none
103
+ // still publishes and its `listing` is empty: this store needs nothing
104
+ // before it can accept an upload, and the id is ours anyway (the local
105
+ // scaffold pins the derived `listings.firefox.id` into config, #893).
106
+ // Nothing ever asks for it.
107
+ store: { kind: 'store', requires: ['FIREFOX_API_KEY', 'FIREFOX_API_SECRET'], listing: [], label: 'Firefox Add-ons', console: 'https://addons.mozilla.org/en-US/developers/addon/submit/distribution' },
108
+ },
109
+ edge: {
110
+ // Edge ships the CHROME build (one chromium artifact, two stores).
111
+ zip: { kind: 'asset', ext: 'zip', requires: [], listing: [] },
112
+ store: { kind: 'store', requires: ['EDGE_CLIENT_ID', 'EDGE_API_KEY'], listing: ['listings.edge.id'], label: 'Microsoft Edge Add-ons', console: 'https://partner.microsoft.com/dashboard/microsoftedge/' },
113
+ },
114
+ },
115
+ };
116
+
117
+ /**
118
+ * The keys one format needs, optionally narrowed to a brand.
119
+ *
120
+ * With no config the whole declared set comes back. With one, a `requires` key
121
+ * whose schema entry carries a `requiredWhen` that does NOT hold for that
122
+ * config is dropped: the EV token belongs to the self-hosted Windows strategy,
123
+ * never to the cloud one, and the schema is where that is written down.
124
+ *
125
+ * @param {string} target - Target type ('desktop' | 'extension').
126
+ * @param {string} platform - Platform key ('mac', 'chrome', ...).
127
+ * @param {string} format - Format key ('dmg', 'store', ...).
128
+ * @param {object} [config] - A resolved target config, to narrow `requires`.
129
+ * @returns {{ requires: string[], listing: string[] }} Empty lists for a format
130
+ * nobody declares.
131
+ */
132
+ function formatKeys(target, platform, format, config) {
133
+ const spec = FORMATS[target]?.[platform]?.[format];
134
+ if (!spec) return { requires: [], listing: [] };
135
+
136
+ const requires = config
137
+ ? spec.requires.filter((key) => {
138
+ const entry = ENV_SCHEMA.find((candidate) => candidate.name === key);
139
+ // No gate declared = the format needs it whenever the format ships
140
+ return !entry?.requiredWhen || requiredWhenHolds(config, entry.requiredWhen);
141
+ })
142
+ : [...spec.requires];
143
+
144
+ return { requires, listing: [...spec.listing] };
145
+ }
146
+
147
+ /**
148
+ * Everything a config ships for a target, read off the declaration.
149
+ *
150
+ * Presence is the switch and every platform and format defaults ON, so the
151
+ * only thing that drops one is a literal `false`. A key the vocabulary does not
152
+ * carry is ignored here (the validator names it as undeclared); nothing is
153
+ * invented from it.
154
+ *
155
+ * @param {object} config - A resolved target config (the declaration is read at
156
+ * `config.platforms`, which is where `targets.<name>.platforms` resolves to).
157
+ * @param {string} target - Target type ('desktop' | 'extension').
158
+ * @returns {Array<{ platform: string, format: string, options: object }>} In
159
+ * offer order; `options` is the format's own settings block ({} when it has
160
+ * none).
161
+ */
162
+ function enabledFormats(config, target) {
163
+ const declared = config?.platforms;
164
+ const enabled = [];
165
+
166
+ for (const platform of PLATFORMS[target] || []) {
167
+ const platformDeclaration = declared?.[platform];
168
+ if (platformDeclaration === false) continue;
169
+
170
+ const formatDeclarations = platformDeclaration?.formats;
171
+ for (const format of Object.keys(FORMATS[target][platform])) {
172
+ const declaration = formatDeclarations?.[format];
173
+ if (declaration === false) continue;
174
+
175
+ enabled.push({ platform, format, options: declaration && typeof declaration === 'object' ? declaration : {} });
176
+ }
177
+ }
178
+
179
+ return enabled;
180
+ }
181
+
182
+ /**
183
+ * The product name a desktop target packages under: the same derivation
184
+ * @omega.js/desktop's `Manager.getConfig()` applies (`app.productName` then
185
+ * `brand.name`), so the website reads the name the packager actually used.
186
+ *
187
+ * @param {object} config - Desktop-shaped config (`{ app, brand }`).
188
+ * @returns {string} Product name ('' when neither key resolves).
189
+ */
190
+ function desktopProductName(config) {
191
+ return config?.app?.productName || config?.brand?.name || '';
192
+ }
193
+
194
+ /**
195
+ * A product name reduced to filename-safe characters. electron-builder's
196
+ * `${productName}` keeps spaces, which become dots in NSIS output and behave
197
+ * inconsistently across targets; hyphens are consistent everywhere.
198
+ *
199
+ * @param {string} productName - Raw product name ("Deployment Playground").
200
+ * @returns {string} Sanitized name ("Deployment-Playground"), '' when empty.
201
+ */
202
+ function sanitizeProductName(productName) {
203
+ return String(productName || '')
204
+ .replace(/[^A-Za-z0-9._-]+/g, '-')
205
+ .replace(/-+/g, '-')
206
+ .replace(/^-|-$/g, '');
207
+ }
208
+
209
+ /**
210
+ * One asset's versionless filename: `<Product>-<platform>-<format>.<ext>`
211
+ * ([#620](https://github.com/Omega-JS-Stack/omega/issues/620)).
212
+ *
213
+ * Names carry NO version, which is the whole point: GitHub's
214
+ * `/releases/latest/download/<asset>` only resolves when the asset name is the
215
+ * same in every release, so releasing a desktop version never touches the
216
+ * website and the published URLs never change. electron-updater is unaffected:
217
+ * it reads the feed files (`latest-mac.yml`, `latest.yml`), which name whatever
218
+ * artifact the build produced.
219
+ *
220
+ * Nothing puts an arch back into a name that omits one (electron-builder's
221
+ * macro expander only REPLACES a `${arch}` token where it appears), so these
222
+ * names support exactly the default build: a UNIVERSAL mac, a SINGLE linux
223
+ * arch, and windows' multi-arch NSIS installer, which merges every arch into
224
+ * one file anyway. build-config refuses any other arch set rather than let two
225
+ * builds collide on one name.
226
+ *
227
+ * @param {string} productName - Raw product name (sanitized here).
228
+ * @param {string} platform - Platform key (mac, windows, linux).
229
+ * @param {string} format - Format key (dmg, nsis, deb, appimage).
230
+ * @param {string} [ext] - Extension override: pass electron-builder's literal
231
+ * `${ext}` to get a TEMPLATE that covers every target sharing the platform's
232
+ * fallback.
233
+ * @returns {string} The filename ('' for a store format, or with no product
234
+ * name to build it from).
235
+ */
236
+ function desktopArtifactName(productName, platform, format, ext) {
237
+ const product = sanitizeProductName(productName);
238
+ const extension = ext || FORMATS.desktop[platform]?.[format]?.ext;
239
+ if (!product || !extension) return '';
240
+
241
+ return `${product}-${platform}-${format}.${extension}`;
242
+ }
243
+
244
+ /**
245
+ * Every published asset's filename, keyed platform then format, in offer order.
246
+ * Store formats are absent: they have no file on the releases repo.
247
+ *
248
+ * @param {string} productName - Raw product name.
249
+ * @returns {object} `{ mac: { dmg: 'App-mac-dmg.dmg' }, ... }`, or `{}` when
250
+ * there is no product name to derive from.
251
+ */
252
+ function desktopArtifactNames(productName) {
253
+ if (!sanitizeProductName(productName)) return {};
254
+
255
+ const names = {};
256
+ for (const [platform, formats] of Object.entries(FORMATS.desktop)) {
257
+ names[platform] = {};
258
+ for (const [format, spec] of Object.entries(formats)) {
259
+ if (spec.kind !== 'asset') continue;
260
+ names[platform][format] = desktopArtifactName(productName, platform, format);
261
+ }
262
+ }
263
+
264
+ return names;
265
+ }
266
+
267
+ module.exports = {
268
+ PLATFORMS,
269
+ FORMATS,
270
+ enabledFormats,
271
+ formatKeys,
272
+ desktopProductName,
273
+ sanitizeProductName,
274
+ desktopArtifactName,
275
+ desktopArtifactNames,
276
+ };