@omega.js/desktop 0.52.0 → 0.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -48
- package/dist/assets/css/core/_initialize.scss +1 -1
- package/dist/assets/js/core/app-shell.js +14 -15
- package/dist/assets/themes/_template/_theme.js +6 -6
- package/dist/assets/themes/base/_includes/global/sections/account.html +4 -4
- package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +5 -5
- package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +3 -3
- package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/blog/tags/tag.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/payment/confirmation.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/newsletter-cta/section.js +2 -3
- package/dist/assets/themes/base/_sections/verts/unit/section.html +1 -1
- package/dist/assets/themes/base/_sections/verts/unit/section.js +3 -4
- package/dist/assets/themes/base/_theme.js +4 -3
- package/dist/assets/themes/bootstrap/_theme.js +2 -2
- package/dist/assets/themes/bootstrap/overrides/_links.scss +1 -1
- package/dist/assets/themes/classy/_theme.js +8 -6
- package/dist/assets/themes/classy/css/marketing/_sections.scss +1 -2
- package/dist/assets/themes/classy/js/hero-demo-form.js +3 -2
- package/dist/assets/themes/neobrutalism/_theme.js +5 -5
- package/dist/assets/themes/neobrutalism/js/pages/test/libraries/layers/index.js +1 -1
- package/dist/assets/themes/newsflash/_theme.js +6 -6
- package/dist/assets/themes/newsflash/js/pages/test/libraries/layers/index.js +1 -1
- package/dist/build.js +87 -111
- package/dist/cli-run.js +4 -1
- package/dist/cli.js +3 -3
- package/dist/commands/build.js +2 -2
- package/dist/commands/cdp/capture.js +2 -2
- package/dist/commands/cdp/client.js +1 -1
- package/dist/commands/cdp/quit.js +2 -2
- package/dist/commands/cdp/relaunch.js +2 -2
- package/dist/commands/cdp/theme.js +1 -1
- package/dist/commands/cdp.js +1 -1
- package/dist/commands/clean.js +4 -5
- package/dist/commands/deploy.js +4 -4
- package/dist/commands/dev.js +25 -0
- package/dist/commands/finalize-release.js +4 -4
- package/dist/commands/launch.js +2 -2
- package/dist/commands/lib/deploy-precheck.js +3 -3
- package/dist/commands/lib/ensure-target.js +18 -23
- package/dist/commands/lib/migrate.js +17 -0
- package/dist/commands/logs.js +1 -1
- package/dist/commands/package.js +2 -2
- package/dist/commands/publish.js +2 -2
- package/dist/commands/release.js +4 -4
- package/dist/commands/runner.js +11 -11
- package/dist/commands/sign-windows.js +5 -5
- package/dist/commands/test.js +8 -8
- package/dist/commands/update.js +7 -6
- package/dist/commands/validate-certs.js +4 -4
- package/dist/commands/version.js +3 -3
- package/dist/defaults/.github/workflows/build.yml +18 -18
- package/dist/defaults/_.gitignore +0 -2
- package/dist/defaults/_mas/README.md +3 -3
- package/dist/defaults/config/certs/README.md +1 -1
- package/dist/defaults/config/omega.json5 +43 -43
- package/dist/defaults/docs/README.md +3 -3
- package/dist/defaults/gulpfile.js +1 -1
- package/dist/defaults/hooks/build/post.js +2 -2
- package/dist/defaults/hooks/build/pre.js +2 -2
- package/dist/defaults/hooks/deploy/pre.js +1 -1
- package/dist/defaults/hooks/notarize/post.js +2 -2
- package/dist/defaults/hooks/release/post.js +2 -2
- package/dist/defaults/hooks/release/pre.js +2 -2
- package/dist/defaults/src/assets/js/components/about/index.js +3 -5
- package/dist/defaults/src/assets/js/components/main/index.js +3 -5
- package/dist/defaults/src/assets/js/components/settings/index.js +3 -5
- package/dist/defaults/src/assets/scss/pages/about.scss +1 -1
- package/dist/defaults/src/assets/scss/pages/main.scss +1 -1
- package/dist/defaults/src/assets/scss/pages/settings.scss +1 -1
- package/dist/defaults/src/integrations/context-menu/index.js +13 -13
- package/dist/defaults/src/integrations/menu/index.js +8 -8
- package/dist/defaults/src/integrations/tray/index.js +12 -12
- package/dist/defaults/src/main.js +5 -7
- package/dist/defaults/src/preload.js +4 -6
- package/dist/defaults/test/README.md +5 -5
- package/dist/defaults/test/_init.js +1 -1
- package/dist/gulp/main.js +9 -10
- package/dist/gulp/tasks/audit.js +11 -14
- package/dist/gulp/tasks/build-config.js +8 -8
- package/dist/gulp/tasks/bundle.js +16 -16
- package/dist/gulp/tasks/defaults.js +3 -3
- package/dist/gulp/tasks/distribute.js +2 -2
- package/dist/gulp/tasks/html.js +9 -9
- package/dist/gulp/tasks/package-quick.js +3 -3
- package/dist/gulp/tasks/package.js +3 -3
- package/dist/gulp/tasks/release.js +3 -3
- package/dist/gulp/tasks/sass.js +6 -6
- package/dist/gulp/tasks/serve.js +4 -4
- package/dist/hooks/notarize-artifacts.js +1 -1
- package/dist/hooks/notarize.js +1 -1
- package/dist/index.js +5 -8
- package/dist/lib/_environment-mixin.js +50 -0
- package/dist/lib/_lifecycle-mixin.js +45 -0
- package/dist/lib/analytics.js +33 -35
- package/dist/lib/app-state.js +14 -14
- package/dist/lib/auth-flow.js +18 -18
- package/dist/lib/auth-persistence.js +12 -12
- package/dist/lib/auth.js +421 -0
- package/dist/lib/auto-updater.js +49 -49
- package/dist/lib/context-menu.js +13 -13
- package/dist/lib/context.js +19 -19
- package/dist/lib/deep-link.js +34 -34
- package/dist/lib/fontawesome.js +5 -5
- package/dist/lib/ipc.js +4 -4
- package/dist/lib/menu.js +25 -25
- package/dist/lib/protocol.js +5 -5
- package/dist/lib/remote-config.js +22 -22
- package/dist/lib/remote-scripts.js +21 -21
- package/dist/lib/restart-manager/index.js +29 -29
- package/dist/lib/restart-manager/install.js +1 -1
- package/dist/lib/restart-manager/protocol.js +1 -1
- package/dist/lib/sign-helpers/exec-with-limit.js +1 -1
- package/dist/lib/sign-helpers/sign-events.js +1 -1
- package/dist/lib/startup.js +18 -13
- package/dist/lib/storage.js +10 -10
- package/dist/lib/templating.js +16 -16
- package/dist/lib/theme.js +10 -10
- package/dist/lib/tray.js +27 -27
- package/dist/lib/usage.js +11 -11
- package/dist/lib/window-manager.js +26 -26
- package/dist/main.js +399 -483
- package/dist/preload.js +236 -176
- package/dist/renderer.js +417 -391
- package/dist/test/fixtures/consumer-app/config/omega.json5 +1 -1
- package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +8 -11
- package/dist/test/fixtures/consumer-app/src/main.js +5 -7
- package/dist/test/fixtures/consumer-app/src/preload.js +2 -2
- package/dist/test/harness/boot-entry.js +22 -20
- package/dist/test/harness/main-entry.js +31 -30
- package/dist/test/harness/renderer-entry.js +5 -5
- package/dist/test/harness/renderer-preload.js +137 -141
- package/dist/test/index.js +10 -10
- package/dist/test/runner.js +2 -2
- package/dist/test/runners/boot.js +7 -6
- package/dist/test/runners/electron.js +3 -2
- package/dist/test/runners/render-event.js +2 -2
- package/dist/test/suites/boot/consumer-app-boots.test.js +57 -26
- package/dist/test/suites/boot/restart-manager.test.js +2 -2
- package/dist/test/suites/boot/storage-bundled.test.js +5 -5
- package/dist/test/suites/boot/theme.test.js +13 -13
- package/dist/test/suites/build/audit.test.js +21 -8
- package/dist/test/suites/build/auth-persistence-resolve.test.js +6 -6
- package/dist/test/suites/build/boot-fixture.test.js +2 -2
- package/dist/test/suites/build/boot-runner-timeout.test.js +6 -5
- package/dist/test/suites/build/brand-scss.test.js +1 -1
- package/dist/test/suites/build/build-json-bake.test.js +1 -1
- package/dist/test/suites/build/build-workflow-jobs.test.js +2 -2
- package/dist/test/suites/build/cli.test.js +30 -2
- package/dist/test/suites/build/config-schema.test.js +5 -5
- package/dist/test/suites/build/defaults-em-dash.test.js +22 -0
- package/dist/test/suites/build/defaults-scaffold.test.js +21 -7
- package/dist/test/suites/build/deploy-direct.test.js +7 -5
- package/dist/test/suites/build/deploy-dispatch.test.js +2 -1
- package/dist/test/suites/build/deploy-hook.test.js +7 -5
- package/dist/test/suites/build/dev-verb.test.js +67 -0
- package/dist/test/suites/build/ensure-target.test.js +13 -5
- package/dist/test/suites/build/env-delivery.test.js +2 -2
- package/dist/test/suites/build/esm-only-dependency.test.js +2 -2
- package/dist/test/suites/build/exports.test.js +9 -8
- package/dist/test/suites/build/get-config.test.js +4 -4
- package/dist/test/suites/build/manifest-deps.test.js +1 -1
- package/dist/test/suites/build/merge-line-files.test.js +7 -7
- package/dist/test/suites/build/migrate.test.js +29 -0
- package/dist/test/suites/build/omega-shell.test.js +34 -2
- package/dist/test/suites/build/omega.test.js +350 -0
- package/dist/test/suites/build/project-scripts-deps.test.js +6 -10
- package/dist/test/suites/build/renderer-auth-bridge.test.js +211 -78
- package/dist/test/suites/build/runner-env-write.test.js +73 -0
- package/dist/test/suites/build/runner.test.js +11 -10
- package/dist/test/suites/build/sentry.test.js +2 -2
- package/dist/test/suites/build/setup-scripts.test.js +27 -0
- package/dist/test/suites/build/sign-windows-e2e.test.js +2 -2
- package/dist/test/suites/build/templating.test.js +3 -3
- package/dist/test/suites/build/test-stealth.test.js +7 -9
- package/dist/test/suites/build/url-helpers.test.js +55 -56
- package/dist/test/suites/build/validate-config.test.js +15 -4
- package/dist/test/suites/build/verb-logs.test.js +20 -0
- package/dist/test/suites/build/wave5-pins.test.js +2 -2
- package/dist/test/suites/main/analytics.test.js +59 -59
- package/dist/test/suites/main/app-state.test.js +66 -66
- package/dist/test/suites/main/auth-flow.test.js +41 -41
- package/dist/test/suites/main/auth-persistence.test.js +54 -43
- package/dist/test/suites/main/{client-bridge.integration.test.js → auth.integration.test.js} +10 -9
- package/dist/test/suites/main/auth.test.js +336 -0
- package/dist/test/suites/main/auto-updater.test.js +134 -134
- package/dist/test/suites/main/boot-sequence.test.js +37 -49
- package/dist/test/suites/main/context-menu.test.js +51 -50
- package/dist/test/suites/main/context.test.js +25 -25
- package/dist/test/suites/main/deep-link.test.js +74 -74
- package/dist/test/suites/main/fontawesome.test.js +27 -27
- package/dist/test/suites/main/ipc.test.js +35 -35
- package/dist/test/suites/main/menu.test.js +101 -100
- package/dist/test/suites/main/protocol.test.js +19 -19
- package/dist/test/suites/main/remote-config.test.js +63 -63
- package/dist/test/suites/main/remote-scripts.test.js +103 -103
- package/dist/test/suites/main/request.test.js +71 -0
- package/dist/test/suites/main/restart-manager.test.js +33 -33
- package/dist/test/suites/main/startup-paths-and-ua.test.js +4 -4
- package/dist/test/suites/main/startup.test.js +26 -26
- package/dist/test/suites/main/stealth-window.test.js +1 -1
- package/dist/test/suites/main/storage.test.js +25 -25
- package/dist/test/suites/main/theme.test.js +34 -34
- package/dist/test/suites/main/tray.test.js +79 -79
- package/dist/test/suites/main/url-helpers.test.js +133 -133
- package/dist/test/suites/main/usage.test.js +25 -25
- package/dist/test/suites/main/window-bounds.test.js +27 -27
- package/dist/test/suites/main/window-manager.test.js +44 -44
- package/dist/test/suites/renderer/analytics-bridge.test.js +5 -5
- package/dist/test/suites/renderer/cross-context-helpers.test.js +37 -31
- package/dist/test/suites/renderer/round-trip.test.js +3 -3
- package/dist/test/suites/renderer/tooltips.test.js +15 -15
- package/dist/test/suites/renderer/{window-em-surface.test.js → window-desktop-surface.test.js} +28 -8
- package/dist/test/utils/extended-mode-warning.js +1 -1
- package/dist/utils/boot-harness.js +56 -0
- package/dist/utils/build-pipeline.js +4 -4
- package/dist/utils/mode-helpers.js +2 -15
- package/dist/utils/runner-env.js +13 -28
- package/dist/utils/ship-keys.js +3 -3
- package/dist/utils/signing-status.js +51 -0
- package/dist/utils/test-events.js +7 -0
- package/dist/utils/test-stealth.js +6 -6
- package/dist/utils/url-helpers.js +52 -42
- package/dist/utils/user-agent.js +44 -0
- package/dist/vendor/account/engine.js +3 -3
- package/dist/vendor/account/index.js +14 -45
- package/dist/vendor/account/resolve-account.js +44 -0
- package/dist/vendor/account/schema.js +1 -1
- package/dist/vendor/account/user.js +99 -0
- package/dist/vendor/config/client-config.js +1 -1
- package/dist/vendor/config/company.js +46 -14
- package/dist/vendor/config/defaults.js +30 -7
- package/dist/vendor/config/edit.js +25 -3
- package/dist/vendor/config/env-delivery.js +1 -1
- package/dist/vendor/config/env-schema.js +3 -6
- package/dist/vendor/config/env.js +34 -22
- package/dist/vendor/config/environment.js +11 -30
- package/dist/vendor/config/index.js +21 -28
- package/dist/vendor/config/load.js +16 -9
- package/dist/vendor/config/platforms.js +1 -1
- package/dist/vendor/config/repo.js +10 -27
- package/dist/vendor/config/schema-client.js +64 -0
- package/dist/vendor/config/schema-cloud.js +38 -0
- package/dist/vendor/config/schema-manager.js +118 -0
- package/dist/vendor/config/schema-overrides.js +68 -0
- package/dist/vendor/config/schema.js +104 -160
- package/dist/vendor/config/site-global.js +2 -3
- package/dist/vendor/config/validate.js +97 -78
- package/dist/vendor/config/winback.js +1 -1
- package/dist/vendor/devkit/actions-secrets.js +1 -1
- package/dist/vendor/devkit/agents-md.js +233 -0
- package/dist/vendor/devkit/attach-log-file.js +16 -2
- package/dist/vendor/devkit/build-json.js +1 -1
- package/dist/vendor/devkit/ci-workflows.js +30 -30
- package/dist/vendor/devkit/cli-router.js +16 -11
- package/dist/vendor/devkit/defaults-engine.js +15 -51
- package/dist/vendor/devkit/deploy-snapshot.js +44 -9
- package/dist/vendor/devkit/env-lines.js +183 -0
- package/dist/vendor/devkit/local.js +64 -10
- package/dist/vendor/devkit/lockfile.js +32 -13
- package/dist/vendor/devkit/logger.js +7 -2
- package/dist/vendor/devkit/merge-line-files.js +219 -177
- package/dist/vendor/devkit/omega-bin.js +208 -111
- package/dist/vendor/devkit/preludes/docs-sync.js +52 -0
- package/dist/vendor/devkit/preludes/index.js +1 -0
- package/dist/vendor/devkit/target-picker.js +45 -0
- package/dist/vendor/devkit/test/dashed-files.js +37 -0
- package/dist/vendor/devkit/test/run-verb-under-tee.js +71 -0
- package/dist/vendor/devkit/test/runner-core.js +6 -6
- package/dist/vendor/devkit/update.js +15 -15
- package/dist/vendor/devkit/verb-scripts.js +40 -0
- package/dist/vendor/devkit/verbs.js +170 -0
- package/dist/vendor/monitoring/env.js +2 -2
- package/dist/vendor/monitoring/index.js +1 -1
- package/dist/vendor/monitoring/main.js +1 -1
- package/dist/vendor/monitoring/preload.js +1 -1
- package/dist/vendor/monitoring/renderer.js +1 -1
- package/package.json +19 -26
- package/dist/commands/install.js +0 -37
- package/dist/defaults/AGENTS.md +0 -110
- package/dist/defaults/CLAUDE.md +0 -1
- package/dist/lib/client-bridge.js +0 -374
- package/dist/lib/logger.js +0 -4
- package/dist/test/suites/build/manager.test.js +0 -213
- package/dist/test/suites/main/client-bridge.test.js +0 -262
- package/dist/vendor/config/env-retired.js +0 -137
- package/dist/vendor/config/retired-keys.js +0 -635
- package/docs/analytics.md +0 -140
- package/docs/app-state.md +0 -92
- package/docs/audit.md +0 -69
- package/docs/auto-updater.md +0 -243
- package/docs/boot-sequence.md +0 -39
- package/docs/build-system.md +0 -169
- package/docs/cdp-debugging.md +0 -169
- package/docs/client-bridge.md +0 -269
- package/docs/common-mistakes.md +0 -21
- package/docs/config-schema.md +0 -120
- package/docs/context-menu.md +0 -112
- package/docs/context.md +0 -81
- package/docs/css.md +0 -90
- package/docs/deep-link.md +0 -186
- package/docs/environment-detection.md +0 -112
- package/docs/fontawesome.md +0 -107
- package/docs/hooks.md +0 -89
- package/docs/icons.md +0 -79
- package/docs/index.md +0 -317
- package/docs/installer-options.md +0 -165
- package/docs/ipc.md +0 -61
- package/docs/lib-modules.md +0 -53
- package/docs/logging.md +0 -229
- package/docs/menu.md +0 -160
- package/docs/releasing.md +0 -239
- package/docs/remote-config.md +0 -118
- package/docs/remote-scripts.md +0 -144
- package/docs/restart-manager.md +0 -144
- package/docs/runner.md +0 -290
- package/docs/sentry.md +0 -97
- package/docs/shared/agent-docs.md +0 -89
- package/docs/shared/analytics.md +0 -612
- package/docs/shared/brands.md +0 -57
- package/docs/shared/breaking-changes.md +0 -851
- package/docs/shared/config.md +0 -1952
- package/docs/shared/deploys.md +0 -341
- package/docs/shared/icons.md +0 -219
- package/docs/shared/local-dev.md +0 -167
- package/docs/shared/logging.md +0 -205
- package/docs/shared/monitoring.md +0 -167
- package/docs/shared/publishing.md +0 -187
- package/docs/shared/rulings.md +0 -34
- package/docs/shared/testing.md +0 -147
- package/docs/shared/theming.md +0 -629
- package/docs/shared/translation.md +0 -333
- package/docs/shared/updates.md +0 -61
- package/docs/signing.md +0 -293
- package/docs/startup.md +0 -142
- package/docs/storage.md +0 -59
- package/docs/templating.md +0 -101
- package/docs/test-boot-layer.md +0 -157
- package/docs/test-framework.md +0 -362
- package/docs/themes.md +0 -149
- package/docs/tooltips.md +0 -99
- package/docs/tray.md +0 -164
- package/docs/usage.md +0 -58
- package/docs/verts.md +0 -62
- package/docs/windows.md +0 -149
|
@@ -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
|
|
3
|
-
*
|
|
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
|
*
|
|
@@ -1,53 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @omega.js/account
|
|
2
|
+
* @omega.js/account: the single source of truth for the OMEGA user/account schema.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `new User(Manager, settings).properties` API, @omega.js/client keeps
|
|
10
|
-
* `resolveAccount(rawData, firebaseUser)`).
|
|
4
|
+
* The account shape once lived in two drifted places: @omega.js/backend's user
|
|
5
|
+
* helper (canonical, schema engine + tokens) and @omega.js/client's hand-rolled
|
|
6
|
+
* DEFAULT_ACCOUNT (missing flags/activity/personal branches and `everPaid`).
|
|
7
|
+
* This package unifies them; each framework is a thin wrapper (the backend's
|
|
8
|
+
* src/omega/services/user.js, the client's modules/auth.js).
|
|
11
9
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* options.user — optional auth-user overlay ({ uid, email }): fills
|
|
18
|
-
* account.auth identity when the doc doesn't carry it (@omega.js/client's
|
|
19
|
-
* resolveAccount(rawData, firebaseUser) semantic).
|
|
10
|
+
* Exports:
|
|
11
|
+
* User: the account as a class (user.js), the stored document as own fields
|
|
12
|
+
* plus the computed getters.
|
|
13
|
+
* resolveAccount(data, options): the plain resolved document (resolve-account.js).
|
|
14
|
+
* resolveSubscription(account): the subscription math (subscription.js).
|
|
20
15
|
*/
|
|
21
16
|
const USER_SCHEMA = require('./schema.js');
|
|
22
|
-
const
|
|
17
|
+
const resolveAccount = require('./resolve-account.js');
|
|
23
18
|
const resolveSubscription = require('./subscription.js');
|
|
19
|
+
const User = require('./user.js');
|
|
24
20
|
const features = require('./features.js');
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
options = options || {};
|
|
28
|
-
|
|
29
|
-
// Time context — byte-identical to @omega.js/backend's node-powertools timestamps:
|
|
30
|
-
// powertools.timestamp(d, { output: 'string' }) === d.toISOString(),
|
|
31
|
-
// powertools.timestamp(d, { output: 'unix' }) === floor(ms / 1000).
|
|
32
|
-
const now = new Date();
|
|
33
|
-
const ctx = {
|
|
34
|
-
generators: options.generators || {},
|
|
35
|
-
now: now.toISOString(),
|
|
36
|
-
nowUNIX: Math.floor(now.getTime() / 1000),
|
|
37
|
-
oldDate: new Date(0).toISOString(),
|
|
38
|
-
oldDateUNIX: 0,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const account = resolve(USER_SCHEMA, data || {}, ctx);
|
|
42
|
-
|
|
43
|
-
// Auth-user overlay (frontend semantic): identity from the signed-in Firebase
|
|
44
|
-
// user when the stored doc doesn't already carry it
|
|
45
|
-
if (options.user) {
|
|
46
|
-
account.auth.uid = account.auth.uid || options.user.uid || null;
|
|
47
|
-
account.auth.email = account.auth.email || options.user.email || null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return account;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
module.exports = { USER_SCHEMA, resolveAccount, resolveSubscription, ...features };
|
|
22
|
+
module.exports = { USER_SCHEMA, User, resolveAccount, resolveSubscription, ...features };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* resolveAccount: the ONE document resolution, shared by the User class and
|
|
3
|
+
* every caller that still wants the plain resolved object.
|
|
4
|
+
*
|
|
5
|
+
* resolveAccount(data, options):
|
|
6
|
+
* options.generators: { uuid, randomId, apiKey } value generators for the
|
|
7
|
+
* '$uuid'/'$randomId'/'$apiKey' schema tokens. @omega.js/backend injects real ones
|
|
8
|
+
* (uuid v4, Utilities().randomId, uid-generator); the frontend passes none
|
|
9
|
+
* and the fields resolve to null (real values always come from the backend).
|
|
10
|
+
* options.user: optional auth-user overlay ({ uid, email }): fills
|
|
11
|
+
* account.auth identity when the doc doesn't carry it (@omega.js/client's
|
|
12
|
+
* resolveAccount(rawData, firebaseUser) semantic).
|
|
13
|
+
*/
|
|
14
|
+
const USER_SCHEMA = require('./schema.js');
|
|
15
|
+
const { resolve } = require('./engine.js');
|
|
16
|
+
|
|
17
|
+
function resolveAccount(data, options) {
|
|
18
|
+
options = options || {};
|
|
19
|
+
|
|
20
|
+
// Time context, byte-identical to @omega.js/backend's node-powertools timestamps:
|
|
21
|
+
// powertools.timestamp(d, { output: 'string' }) === d.toISOString(),
|
|
22
|
+
// powertools.timestamp(d, { output: 'unix' }) === floor(ms / 1000).
|
|
23
|
+
const now = new Date();
|
|
24
|
+
const ctx = {
|
|
25
|
+
generators: options.generators || {},
|
|
26
|
+
now: now.toISOString(),
|
|
27
|
+
nowUNIX: Math.floor(now.getTime() / 1000),
|
|
28
|
+
oldDate: new Date(0).toISOString(),
|
|
29
|
+
oldDateUNIX: 0,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const account = resolve(USER_SCHEMA, data || {}, ctx);
|
|
33
|
+
|
|
34
|
+
// Auth-user overlay (frontend semantic): identity from the signed-in Firebase
|
|
35
|
+
// user when the stored doc doesn't already carry it
|
|
36
|
+
if (options.user) {
|
|
37
|
+
account.auth.uid = account.auth.uid || options.user.uid || null;
|
|
38
|
+
account.auth.email = account.auth.email || options.user.email || null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return account;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = resolveAccount;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* USER_SCHEMA — the canonical OMEGA user/account schema (pure data, no logic).
|
|
3
3
|
*
|
|
4
|
-
* Extracted verbatim from @omega.js/backend's
|
|
4
|
+
* Extracted verbatim from @omega.js/backend's former user helper, which was
|
|
5
5
|
* the authoritative shape (@omega.js/client's DEFAULT_ACCOUNT had drifted from it).
|
|
6
6
|
*
|
|
7
7
|
* Each leaf field is { type, default, nullable }
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User: the OMEGA account as one class, the same on the backend and in the browser.
|
|
3
|
+
*
|
|
4
|
+
* The own enumerable fields are the resolved stored document (every schema
|
|
5
|
+
* branch, in schema order), so `user.auth.uid` and `user.subscription.status`
|
|
6
|
+
* read as they always have and `toJSON()` is the one stored shape a Firestore
|
|
7
|
+
* write or an API response carries. Everything derived lives on the prototype
|
|
8
|
+
* as getters, computed on every read, so it never reaches the stored shape and
|
|
9
|
+
* never goes stale when code mutates `user.subscription` in place.
|
|
10
|
+
*
|
|
11
|
+
* `new User()` is the signed-out user: `authenticated` false, `plan` basic.
|
|
12
|
+
*/
|
|
13
|
+
const resolveAccount = require('./resolve-account.js');
|
|
14
|
+
const resolveSubscription = require('./subscription.js');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* An account: the stored document as own fields, identity-derived and
|
|
18
|
+
* subscription-derived facts as getters.
|
|
19
|
+
*/
|
|
20
|
+
class User {
|
|
21
|
+
// The '$uuid'/'$randomId'/'$apiKey' token generators. Static because there is one host per process:
|
|
22
|
+
// the Node backend assigns { uuid, randomId, apiKey } once at boot; the browser never does, so those fields resolve to null.
|
|
23
|
+
static generators = {};
|
|
24
|
+
|
|
25
|
+
// The schema's own EMPTY discount node, which is what a CLEARED discount is
|
|
26
|
+
// ([#333](https://github.com/Omega-JS-Stack/omega/issues/333)). The webhook
|
|
27
|
+
// pipeline clears the node with a MERGE write, so every field has to be named or
|
|
28
|
+
// half of the old claim survives it. Read off the resolver rather than spelled
|
|
29
|
+
// out again: the node's shape keeps its one home in the schema, and a field
|
|
30
|
+
// added there is cleared without anyone remembering a second list.
|
|
31
|
+
static EMPTY_DISCOUNT = resolveAccount({}).subscription.discount;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param {object} [document] - the stored account document (any partial object)
|
|
35
|
+
* @param {object|null} [identity] - { uid, email, displayName, photoURL, emailVerified }; a Firebase user satisfies it as-is
|
|
36
|
+
*/
|
|
37
|
+
constructor(document = {}, identity = null) {
|
|
38
|
+
Object.assign(this, resolveAccount(document, { generators: User.generators, user: identity }));
|
|
39
|
+
|
|
40
|
+
// Non-enumerable so it never reaches toJSON() or Object.keys(): the profile
|
|
41
|
+
// comes from the sign-in, never from the stored document
|
|
42
|
+
const source = identity || {};
|
|
43
|
+
Object.defineProperty(this, 'profile', {
|
|
44
|
+
value: {
|
|
45
|
+
displayName: source.displayName || null,
|
|
46
|
+
photoURL: source.photoURL || null,
|
|
47
|
+
emailVerified: source.emailVerified === true,
|
|
48
|
+
},
|
|
49
|
+
writable: true,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** True only when the account carries a non-empty uid. */
|
|
54
|
+
get authenticated() {
|
|
55
|
+
return typeof this.auth.uid === 'string' && this.auth.uid.length > 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The account's uid, or null when signed out. */
|
|
59
|
+
get uid() {
|
|
60
|
+
return this.auth.uid;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** The account's email, or null when signed out. */
|
|
64
|
+
get email() {
|
|
65
|
+
return this.auth.email;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** The plan the user has access to right now ('basic' when cancelled or suspended). */
|
|
69
|
+
get plan() {
|
|
70
|
+
return resolveSubscription(this).plan;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** True when a paid plan is active (including trialing and cancelling). */
|
|
74
|
+
get active() {
|
|
75
|
+
return resolveSubscription(this).active;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** True while a claimed trial on an active paid plan has not yet expired. */
|
|
79
|
+
get trialing() {
|
|
80
|
+
return resolveSubscription(this).trialing;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** True when an active paid plan (not trialing) has a cancellation pending. */
|
|
84
|
+
get cancelling() {
|
|
85
|
+
return resolveSubscription(this).cancelling;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** True when the user has ever paid (a payment start date exists). */
|
|
89
|
+
get everPaid() {
|
|
90
|
+
return resolveSubscription(this).everPaid;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The stored document alone: own enumerable fields, never getters or profile. */
|
|
94
|
+
toJSON() {
|
|
95
|
+
return { ...this };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = User;
|
|
@@ -88,7 +88,7 @@ function pickPaths(section, paths) {
|
|
|
88
88
|
|
|
89
89
|
/**
|
|
90
90
|
* The subset of a resolved config a browser may see.
|
|
91
|
-
* @param {object} [resolved] - a resolved config (
|
|
91
|
+
* @param {object} [resolved] - a resolved config (build.getConfig() output),
|
|
92
92
|
* with this build's facts composed onto it.
|
|
93
93
|
* @returns {object} the blob every browser surface bakes as OMEGA_BUILD_JSON.config.
|
|
94
94
|
* @throws {Error} when a section that is about to ship carries a secret-shaped key.
|
|
@@ -44,6 +44,9 @@ const fs = require('node:fs');
|
|
|
44
44
|
const os = require('node:os');
|
|
45
45
|
const path = require('node:path');
|
|
46
46
|
const JSON5 = require('json5');
|
|
47
|
+
const Logger = require('../devkit/logger.js');
|
|
48
|
+
|
|
49
|
+
const logger = new Logger('company');
|
|
47
50
|
|
|
48
51
|
// The company TREE inside the parent brand's repo, and the file an off-laptop
|
|
49
52
|
// run reads the resolved layer from: GENERATED beside the brand config by the
|
|
@@ -62,13 +65,16 @@ const REGISTRY_FILE = 'brands.json';
|
|
|
62
65
|
// it visible").
|
|
63
66
|
const SELF = 'self';
|
|
64
67
|
|
|
65
|
-
// The
|
|
66
|
-
const
|
|
68
|
+
// The `company` keys the LOADER fills: never typed, always resolved.
|
|
69
|
+
const RESOLVED_COMPANY_KEYS = ['name', 'url', 'images'];
|
|
67
70
|
|
|
68
71
|
// One warning per company id per process: a missing parent is a state a whole
|
|
69
72
|
// build runs in, never a per-call event.
|
|
70
73
|
const warned = new Set();
|
|
71
74
|
|
|
75
|
+
// One warning per process for a registry file that is there but will not parse.
|
|
76
|
+
let warnedUnreadable = false;
|
|
77
|
+
|
|
72
78
|
/**
|
|
73
79
|
* The machine home OMEGA keeps its per-machine state in. `OMEGA_HOME` moves it
|
|
74
80
|
* (the test lanes point it at a temp dir so a fixture never writes a real line).
|
|
@@ -118,6 +124,17 @@ function readRegistry() {
|
|
|
118
124
|
return readJson(registryFile()) || {};
|
|
119
125
|
}
|
|
120
126
|
|
|
127
|
+
/**
|
|
128
|
+
* A registry line's root when it is on this machine now, else null: the ONE
|
|
129
|
+
* test both the reader and the write's prune apply, so a line the reader would
|
|
130
|
+
* resolve is never a line the prune drops.
|
|
131
|
+
* @param {object} line - A registry line.
|
|
132
|
+
* @returns {string|null}
|
|
133
|
+
*/
|
|
134
|
+
function liveRoot(line) {
|
|
135
|
+
return line && typeof line.root === 'string' && isDir(line.root) ? line.root : null;
|
|
136
|
+
}
|
|
137
|
+
|
|
121
138
|
/**
|
|
122
139
|
* Record (or refresh) ONE brand's line in the machine registry, which is what
|
|
123
140
|
* every `loadConfig()` does for the brand it just loaded: the map of where the
|
|
@@ -130,7 +147,13 @@ function readRegistry() {
|
|
|
130
147
|
*
|
|
131
148
|
* A write also PRUNES the lines whose root is gone: the file is a map of what
|
|
132
149
|
* is on this machine, so a brand that was deleted or moved (and re-recorded
|
|
133
|
-
* under its new root) leaves nothing behind to resolve into.
|
|
150
|
+
* under its new root) leaves nothing behind to resolve into. A line whose root
|
|
151
|
+
* is on disk is never pruned (`liveRoot`, the reader's own test).
|
|
152
|
+
*
|
|
153
|
+
* A registry file that is THERE but will not parse is never rewritten: writing
|
|
154
|
+
* over it would keep one line and drop every other brand. The write itself is
|
|
155
|
+
* a rename of a finished temp file, so a racing reader never sees half a file.
|
|
156
|
+
* Every write logs its caller and the kept and pruned ids at debug level.
|
|
134
157
|
*
|
|
135
158
|
* @param {object} entry - The brand's own facts.
|
|
136
159
|
* @param {string} entry.id - `brand.id` (the key).
|
|
@@ -143,7 +166,17 @@ function recordBrand({ id, root, name, url }) {
|
|
|
143
166
|
if (!id || !root) return false;
|
|
144
167
|
|
|
145
168
|
try {
|
|
146
|
-
const
|
|
169
|
+
const file = registryFile();
|
|
170
|
+
const registry = fs.existsSync(file) ? readJson(file) : {};
|
|
171
|
+
|
|
172
|
+
if (!registry) {
|
|
173
|
+
if (!warnedUnreadable) {
|
|
174
|
+
warnedUnreadable = true;
|
|
175
|
+
logger.warn(`Machine registry ${file} does not parse: left as it is, no brand recorded. Delete it and any omega verb rebuilds it.`);
|
|
176
|
+
}
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
|
|
147
180
|
const current = registry[id];
|
|
148
181
|
const line = { root, name: name || null, url: url || null };
|
|
149
182
|
|
|
@@ -153,10 +186,15 @@ function recordBrand({ id, root, name, url }) {
|
|
|
153
186
|
|
|
154
187
|
registry[id] = { ...line, updatedAt: new Date().toISOString() };
|
|
155
188
|
|
|
156
|
-
const live = Object.fromEntries(Object.entries(registry).filter(([, entry]) =>
|
|
189
|
+
const live = Object.fromEntries(Object.entries(registry).filter(([, entry]) => liveRoot(entry)));
|
|
190
|
+
const pruned = Object.keys(registry).filter((key) => !(key in live));
|
|
157
191
|
|
|
158
192
|
fs.mkdirSync(omegaHome(), { recursive: true });
|
|
159
|
-
|
|
193
|
+
const temp = `${file}.${process.pid}.tmp`;
|
|
194
|
+
fs.writeFileSync(temp, `${JSON.stringify(live, null, 2)}\n`);
|
|
195
|
+
fs.renameSync(temp, file);
|
|
196
|
+
|
|
197
|
+
logger.debug(`Registry write by ${process.argv[1] || process.argv0} (pid ${process.pid}): kept [${Object.keys(live).join(', ')}], pruned [${pruned.join(', ')}]`);
|
|
160
198
|
return true;
|
|
161
199
|
} catch {
|
|
162
200
|
return false;
|
|
@@ -271,13 +309,6 @@ function resolveCompany(brandRoot, brandConfig) {
|
|
|
271
309
|
const webhooks = !(config.company && config.company.webhooks === false);
|
|
272
310
|
const reply = (facts) => answer({ ...facts, webhooks });
|
|
273
311
|
|
|
274
|
-
// A brand still carrying the retired stamp hears about it once: the folder it
|
|
275
|
-
// points at is not read any more, by anything.
|
|
276
|
-
if (root && fs.existsSync(path.join(root, RETIRED_MARKER)) && !warned.has(RETIRED_MARKER)) {
|
|
277
|
-
warned.add(RETIRED_MARKER);
|
|
278
|
-
console.warn(`${path.join(root, RETIRED_MARKER)} is retired (#677): delete it, and name the company with company: { id: '<parent brand.id>' } in omega.json5.`);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
312
|
// No company: the brand IS the whole entity, so the company facts are its own
|
|
282
313
|
// and every reader works without a fallback.
|
|
283
314
|
if (!id) {
|
|
@@ -290,7 +321,7 @@ function resolveCompany(brandRoot, brandConfig) {
|
|
|
290
321
|
}
|
|
291
322
|
|
|
292
323
|
const line = readRegistry()[id];
|
|
293
|
-
const parentRoot =
|
|
324
|
+
const parentRoot = liveRoot(line);
|
|
294
325
|
|
|
295
326
|
if (parentRoot) {
|
|
296
327
|
const parentBrand = (readBrandConfig(parentRoot) || {}).brand || {};
|
|
@@ -347,4 +378,5 @@ module.exports = {
|
|
|
347
378
|
COMPANY_DIR,
|
|
348
379
|
COMPANY_RESOLVED_FILE,
|
|
349
380
|
COMPANY_SELF: SELF,
|
|
381
|
+
RESOLVED_COMPANY_KEYS,
|
|
350
382
|
};
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
* brand config is a copy that drifts from the thing it came from.
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
+
const { isDeepStrictEqual } = require('node:util');
|
|
31
|
+
|
|
30
32
|
const { SHARED_SCHEMA, TARGET_SCHEMAS } = require('./schema.js');
|
|
31
33
|
const { isPlainObject } = require('./merge.js');
|
|
32
34
|
|
|
@@ -59,6 +61,12 @@ function defaultRules(target) {
|
|
|
59
61
|
return rules.filter(hasDefault);
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Set a value at a dot-path, creating the objects on the way.
|
|
66
|
+
* @param {object} target
|
|
67
|
+
* @param {string} dotted
|
|
68
|
+
* @param {*} value
|
|
69
|
+
*/
|
|
62
70
|
function setAtPath(target, dotted, value) {
|
|
63
71
|
const names = dotted.split('.');
|
|
64
72
|
const leaf = names.pop();
|
|
@@ -127,13 +135,26 @@ function defaultComments(target) {
|
|
|
127
135
|
return comments;
|
|
128
136
|
}
|
|
129
137
|
|
|
130
|
-
|
|
131
|
-
|
|
138
|
+
/**
|
|
139
|
+
* What filling `present` from `incoming` does, key by key, never overwriting:
|
|
140
|
+
* a path `present` lacks is ADDED at its highest missing point (one block,
|
|
141
|
+
* not one edit per key inside it), and a path `present` already answers
|
|
142
|
+
* differently is KEPT. An equal value is neither.
|
|
143
|
+
* @param {object} incoming - The values on offer.
|
|
144
|
+
* @param {object} present - The authored config they would fill.
|
|
145
|
+
* @returns {{ added: Array<{ path: string, value: * }>, kept: Array<{ path: string, value: *, incoming: * }> }}
|
|
146
|
+
*/
|
|
147
|
+
function planMerge(incoming, present) {
|
|
148
|
+
return collectPlan(incoming, present, '', { added: [], kept: [] });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function collectPlan(incoming, present, prefix, plan) {
|
|
152
|
+
for (const [key, value] of Object.entries(incoming)) {
|
|
132
153
|
const dotted = prefix ? `${prefix}.${key}` : key;
|
|
133
154
|
const authored = isPlainObject(present) && Object.prototype.hasOwnProperty.call(present, key);
|
|
134
155
|
|
|
135
156
|
if (!authored) {
|
|
136
|
-
|
|
157
|
+
plan.added.push({ path: dotted, value });
|
|
137
158
|
continue;
|
|
138
159
|
}
|
|
139
160
|
|
|
@@ -141,11 +162,13 @@ function collectMissing(defaults, present, prefix, target, found) {
|
|
|
141
162
|
// A brand that authored anything else at this path (a scalar, false, null)
|
|
142
163
|
// made a decision: never dive in, never overwrite.
|
|
143
164
|
if (isPlainObject(value) && isPlainObject(present[key])) {
|
|
144
|
-
|
|
165
|
+
collectPlan(value, present[key], dotted, plan);
|
|
166
|
+
} else if (!isDeepStrictEqual(value, present[key])) {
|
|
167
|
+
plan.kept.push({ path: dotted, value: present[key], incoming: value });
|
|
145
168
|
}
|
|
146
169
|
}
|
|
147
170
|
|
|
148
|
-
return
|
|
171
|
+
return plan;
|
|
149
172
|
}
|
|
150
173
|
|
|
151
174
|
/**
|
|
@@ -167,7 +190,7 @@ function missingDefaults(config, target) {
|
|
|
167
190
|
// copy to drift ([#793](https://github.com/Omega-JS-Stack/omega/issues/793))
|
|
168
191
|
const writable = defaultsFrom(defaultRules(target).filter(isMaterialized));
|
|
169
192
|
|
|
170
|
-
return
|
|
193
|
+
return planMerge(writable, config || {}).added;
|
|
171
194
|
}
|
|
172
195
|
|
|
173
|
-
module.exports = { schemaDefaults, missingDefaults, defaultComments, defaultRules };
|
|
196
|
+
module.exports = { schemaDefaults, missingDefaults, defaultComments, defaultRules, planMerge, setAtPath };
|
|
@@ -579,12 +579,23 @@ function applyConfigEdits(source, edits, { comments = {} } = {}) {
|
|
|
579
579
|
* @param {{ dryRun?: boolean, comments?: Object<string, string> }} [options]
|
|
580
580
|
* @returns {{ path: string, changed: boolean, applied: string[] }}
|
|
581
581
|
*/
|
|
582
|
-
function writeConfigValues(projectDir, edits,
|
|
582
|
+
function writeConfigValues(projectDir, edits, options) {
|
|
583
583
|
const configPath = resolveConfigPath(projectDir);
|
|
584
584
|
if (!configPath) {
|
|
585
585
|
throw new Error(`No ${FILE_NAME} found under ${projectDir} — cannot write config values`);
|
|
586
586
|
}
|
|
587
587
|
|
|
588
|
+
return writeConfigFileValues(configPath, edits, options);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* writeConfigValues on one named omega file (an overlay, a target's own file).
|
|
593
|
+
* @param {string} configPath - The file to edit.
|
|
594
|
+
* @param {Object<string, *>} edits - Dot-path → value.
|
|
595
|
+
* @param {{ dryRun?: boolean, comments?: Object<string, string> }} [options]
|
|
596
|
+
* @returns {{ path: string, changed: boolean, applied: string[] }}
|
|
597
|
+
*/
|
|
598
|
+
function writeConfigFileValues(configPath, edits, { dryRun = false, comments = {} } = {}) {
|
|
588
599
|
const source = fs.readFileSync(configPath, 'utf8');
|
|
589
600
|
const applied = pendingEdits(JSON5.parse(source), edits).map(([path]) => path);
|
|
590
601
|
// Every writeback also normalizes top-level key order (comments travel
|
|
@@ -748,12 +759,23 @@ function applyConfigRemovals(source, paths) {
|
|
|
748
759
|
* @param {{ dryRun?: boolean }} [options]
|
|
749
760
|
* @returns {{ path: string, changed: boolean, removed: string[] }}
|
|
750
761
|
*/
|
|
751
|
-
function removeConfigValues(projectDir, paths,
|
|
762
|
+
function removeConfigValues(projectDir, paths, options) {
|
|
752
763
|
const configPath = resolveConfigPath(projectDir);
|
|
753
764
|
if (!configPath) {
|
|
754
765
|
throw new Error(`No ${FILE_NAME} found under ${projectDir} — cannot remove config values`);
|
|
755
766
|
}
|
|
756
767
|
|
|
768
|
+
return removeConfigFileValues(configPath, paths, options);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* removeConfigValues on one named omega file (an overlay, a target's own file).
|
|
773
|
+
* @param {string} configPath - The file to edit.
|
|
774
|
+
* @param {string[]} paths - Dot-paths to delete.
|
|
775
|
+
* @param {{ dryRun?: boolean }} [options]
|
|
776
|
+
* @returns {{ path: string, changed: boolean, removed: string[] }}
|
|
777
|
+
*/
|
|
778
|
+
function removeConfigFileValues(configPath, paths, { dryRun = false } = {}) {
|
|
757
779
|
const source = fs.readFileSync(configPath, 'utf8');
|
|
758
780
|
const parsed = JSON5.parse(source);
|
|
759
781
|
const removed = paths.filter((path) => getAtPath(parsed, path) !== undefined);
|
|
@@ -766,4 +788,4 @@ function removeConfigValues(projectDir, paths, { dryRun = false } = {}) {
|
|
|
766
788
|
return { path: configPath, changed: next !== source, removed };
|
|
767
789
|
}
|
|
768
790
|
|
|
769
|
-
module.exports = { applyConfigEdits, writeConfigValues, applyConfigRemovals, removeConfigValues, parseRoot };
|
|
791
|
+
module.exports = { applyConfigEdits, writeConfigValues, writeConfigFileValues, applyConfigRemovals, removeConfigValues, removeConfigFileValues, parseRoot };
|
|
@@ -54,7 +54,7 @@ const WORKFLOW_OWNED_KEYS = ['GH_TOKEN', 'CLOUDFLARE_TOKEN', 'NODE_VERSION', 'NO
|
|
|
54
54
|
|
|
55
55
|
// Rendered in place of the block when a target delivers nothing, so the
|
|
56
56
|
// generated region is always a valid, self-explaining line of YAML.
|
|
57
|
-
const EMPTY_BLOCK = '# (no CI-delivered keys for this target
|
|
57
|
+
const EMPTY_BLOCK = '# (no CI-delivered keys for this target: the next omega verb regenerates this block)';
|
|
58
58
|
|
|
59
59
|
// What a target's generated workflow carries in the runner env, per target.
|
|
60
60
|
//
|
|
@@ -874,12 +874,9 @@ const ENV_SCHEMA = [
|
|
|
874
874
|
description: 'Edge Add-ons API key the publish request authenticates with.',
|
|
875
875
|
},
|
|
876
876
|
|
|
877
|
-
// No test-lane credentials live here
|
|
878
|
-
//
|
|
879
|
-
//
|
|
880
|
-
// against a persona the backend emulator seeds, so a suite never asks a
|
|
881
|
-
// brand for a key. The pair that used to sit here is retired outright
|
|
882
|
-
// (env-retired.js carries both rows); #904 owns the replacement.
|
|
877
|
+
// No test-lane credentials live here: web, desktop and extension each sign
|
|
878
|
+
// in as a persona the backend emulator seeds, so a suite never asks a brand
|
|
879
|
+
// for a key. The retired pair's rows are @omega.js/manager's migrate table.
|
|
883
880
|
|
|
884
881
|
{
|
|
885
882
|
name: 'OMEGA_FONTAWESOME_ROOT',
|