@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,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The .env line grammar the marker engine merges by and every in-place key
|
|
3
|
+
* writer sets keys by: logical lines (a quoted value spanning several physical
|
|
4
|
+
* lines is one unit), the key a line assigns, the double-quote normalization,
|
|
5
|
+
* and the replace-or-append of a key's lines. dotenv is the reader every OMEGA loader
|
|
6
|
+
* uses, so it is the judge: a normalized line must read back to the same value,
|
|
7
|
+
* and a key's winning line is its LAST one, as dotenv reads it.
|
|
8
|
+
*/
|
|
9
|
+
const dotenv = require('dotenv');
|
|
10
|
+
const { envLine } = require('../config/index.js');
|
|
11
|
+
|
|
12
|
+
// An assignment dotenv accepts: optional indent and `export `, then KEY=
|
|
13
|
+
const ASSIGNMENT = /^(\s*(?:export\s+)?)([\w.-]+)\s*=(.*)$/s;
|
|
14
|
+
const QUOTED_OPEN = /^\s*(?:export\s+)?[\w.-]+\s*=\s*(["'`])/;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The index of the quote closing a value opened at `from`, as dotenv picks it:
|
|
18
|
+
* a quote after a backslash may close the value or be passed, the first quote
|
|
19
|
+
* after no backslash cannot be passed, and dotenv takes the LAST closing
|
|
20
|
+
* candidate followed on its line by only whitespace or a `# comment`, so
|
|
21
|
+
* `K="x\"` reads `x\`. -1 when none closes it.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} text
|
|
24
|
+
* @param {string} quote - `"`, `'` or a backtick
|
|
25
|
+
* @param {number} from - First index after the opening quote
|
|
26
|
+
* @returns {number}
|
|
27
|
+
*/
|
|
28
|
+
function closingQuote(text, quote, from) {
|
|
29
|
+
const lineRest = /[^\S\n]*(?:#[^\n]*)?(?:\n|$)/y;
|
|
30
|
+
let close = -1;
|
|
31
|
+
for (let i = from; i < text.length; i += 1) {
|
|
32
|
+
if (text[i] !== quote) continue;
|
|
33
|
+
lineRest.lastIndex = i + 1;
|
|
34
|
+
if (lineRest.test(text)) close = i;
|
|
35
|
+
if (text[i - 1] !== '\\') break;
|
|
36
|
+
}
|
|
37
|
+
return close;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Group physical lines into logical ones: a quoted value that closes on a later
|
|
42
|
+
* line joins those lines (newlines kept) into one unit, so it moves and
|
|
43
|
+
* survives whole. An unterminated quote stays line by line, as dotenv reads it.
|
|
44
|
+
*
|
|
45
|
+
* @param {string[]} lines - The file split on `\n`
|
|
46
|
+
* @returns {string[]}
|
|
47
|
+
*/
|
|
48
|
+
function joinEnvUnits(lines) {
|
|
49
|
+
const units = [];
|
|
50
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
51
|
+
const open = lines[i].match(QUOTED_OPEN);
|
|
52
|
+
const rest = open ? lines.slice(i).join('\n') : '';
|
|
53
|
+
const close = open ? closingQuote(rest, open[1], open[0].length) : -1;
|
|
54
|
+
if (close < 0) {
|
|
55
|
+
units.push(lines[i]);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const end = i + rest.slice(0, close).split('\n').length - 1;
|
|
60
|
+
units.push(lines.slice(i, end + 1).join('\n'));
|
|
61
|
+
i = end;
|
|
62
|
+
}
|
|
63
|
+
return units;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The key a line assigns, or null for a comment, a blank, or anything else.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} line
|
|
70
|
+
* @returns {string|null}
|
|
71
|
+
*/
|
|
72
|
+
function envKey(line) {
|
|
73
|
+
const match = line.match(ASSIGNMENT);
|
|
74
|
+
return match ? match[2] : null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// The inline comment after a raw value: past the closing quote of a quoted
|
|
78
|
+
// value, from the first `#` of an unquoted one.
|
|
79
|
+
function trailingComment(raw) {
|
|
80
|
+
let rest = raw;
|
|
81
|
+
if (raw[0] === "'" || raw[0] === '`') {
|
|
82
|
+
const close = closingQuote(raw, raw[0], 1);
|
|
83
|
+
if (close >= 0) rest = raw.slice(close + 1);
|
|
84
|
+
}
|
|
85
|
+
const hash = rest.indexOf('#');
|
|
86
|
+
return hash < 0 ? '' : rest.slice(hash).trim();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Normalize one .env line to the double-quoted form: `KEY=raw` and `KEY='x'`
|
|
91
|
+
* become `KEY="..."`, an inline comment kept; an empty value becomes `KEY=""`;
|
|
92
|
+
* a double-quoted value, a comment and a blank are left alone. The rewrite
|
|
93
|
+
* happens only when dotenv reads the same value back; otherwise the line stays.
|
|
94
|
+
*
|
|
95
|
+
* @param {string} line - One logical line
|
|
96
|
+
* @returns {string}
|
|
97
|
+
*/
|
|
98
|
+
function normalizeEnvLine(line) {
|
|
99
|
+
const match = line.match(ASSIGNMENT);
|
|
100
|
+
if (!match) return line;
|
|
101
|
+
const [, prefix, key, rawValue] = match;
|
|
102
|
+
const raw = rawValue.trim();
|
|
103
|
+
|
|
104
|
+
if (raw === '') return `${prefix}${key}=""`;
|
|
105
|
+
if (raw.startsWith('"')) return line;
|
|
106
|
+
|
|
107
|
+
const value = dotenv.parse(line)[key];
|
|
108
|
+
if (value === undefined) return line;
|
|
109
|
+
|
|
110
|
+
let quoted;
|
|
111
|
+
try {
|
|
112
|
+
quoted = envLine(key, value);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
// envLine refuses a value dotenv would read back changed: the line stays
|
|
115
|
+
return line;
|
|
116
|
+
}
|
|
117
|
+
const comment = trailingComment(raw);
|
|
118
|
+
const candidate = `${prefix}${quoted}${comment ? ` ${comment}` : ''}`;
|
|
119
|
+
return dotenv.parse(candidate)[key] === value ? candidate : line;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The line that sets `key`: the LAST one, the value dotenv reads.
|
|
124
|
+
*
|
|
125
|
+
* @param {string[]} lines
|
|
126
|
+
* @param {string} key
|
|
127
|
+
* @returns {string} - `KEY=""` when no line sets it
|
|
128
|
+
*/
|
|
129
|
+
function findKeyLine(lines, key) {
|
|
130
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
131
|
+
if (envKey(lines[i]) === key) return lines[i];
|
|
132
|
+
}
|
|
133
|
+
return `${key}=""`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// A placeholder, `# KEY=""` or a bare `# KEY=`, → KEY; any other comment → null.
|
|
137
|
+
function parsePlaceholderKey(trimmed) {
|
|
138
|
+
const match = trimmed.match(/^#\s*([A-Za-z_][A-Za-z0-9_]*)=\s*(?:"")?\s*$/);
|
|
139
|
+
return match ? match[1] : null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Set keys in .env content by logical line: the first unit assigning a key, or
|
|
144
|
+
* its `# KEY=""` placeholder, becomes the given line and every later one drops,
|
|
145
|
+
* so dotenv reads the new value; a key the content never had is appended.
|
|
146
|
+
* Every other line keeps its place.
|
|
147
|
+
*
|
|
148
|
+
* @param {string} content - Current file content ('' for none)
|
|
149
|
+
* @param {Object<string, string>} lineFor - KEY to its whole line, e.g. envLine's
|
|
150
|
+
* @returns {string} The new content, ending in exactly one newline
|
|
151
|
+
*/
|
|
152
|
+
function setEnvLines(content, lineFor) {
|
|
153
|
+
const body = content.replace(/(?:\r?\n)+$/, '');
|
|
154
|
+
const seen = new Set();
|
|
155
|
+
|
|
156
|
+
const out = joinEnvUnits(body === '' ? [] : body.split(/\r?\n/)).flatMap((unit) => {
|
|
157
|
+
const key = envKey(unit) ?? parsePlaceholderKey(unit.trim());
|
|
158
|
+
if (key === null || !Object.hasOwn(lineFor, key)) return [unit];
|
|
159
|
+
if (seen.has(key)) return [];
|
|
160
|
+
seen.add(key);
|
|
161
|
+
return [lineFor[key]];
|
|
162
|
+
});
|
|
163
|
+
for (const key of Object.keys(lineFor)) {
|
|
164
|
+
if (!seen.has(key)) out.push(lineFor[key]);
|
|
165
|
+
}
|
|
166
|
+
return `${out.join('\n')}\n`;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// The framework's own .env comment grammar: a boxed group header or a
|
|
170
|
+
// `# KEY=""` placeholder. Regenerated from the template, never a consumer's note.
|
|
171
|
+
function isMachineComment(trimmed) {
|
|
172
|
+
return /^# ── .* ──$/.test(trimmed) || parsePlaceholderKey(trimmed) !== null;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// KEY= / KEY="" / KEY='' (whitespace tolerated) count as empty.
|
|
176
|
+
function envValueIsEmpty(line) {
|
|
177
|
+
const eqIdx = line.indexOf('=');
|
|
178
|
+
if (eqIdx < 0) return true;
|
|
179
|
+
const value = line.slice(eqIdx + 1).trim();
|
|
180
|
+
return value === '' || value === '""' || value === "''";
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
module.exports = { joinEnvUnits, envKey, normalizeEnvLine, findKeyLine, parsePlaceholderKey, isMachineComment, envValueIsEmpty, setEnvLines };
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
* into the monorepo is read-only and stops the boot loudly, any other local
|
|
17
17
|
* checkout is rebuilt and the invocation re-execs once
|
|
18
18
|
*
|
|
19
|
-
* Consumers: `omega dev --local` (@omega.js/web),
|
|
20
|
-
*
|
|
21
|
-
* own scripts/watch-all.js (lock helpers + vendor propagation).
|
|
19
|
+
* Consumers: `omega dev --local` (@omega.js/web), @omega.js/manager's
|
|
20
|
+
* brand-root `omega i local` / `omega i live` (src/commands/install.js), and the
|
|
21
|
+
* monorepo's own scripts/watch-all.js (lock helpers + vendor propagation).
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
// Libraries
|
|
@@ -276,6 +276,43 @@ function regenerateBrandLockfile(installRoot, logger) {
|
|
|
276
276
|
return regenerateLockfile({ root: installRoot, log: logger ? (line) => logger.log(line) : undefined });
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
+
/**
|
|
280
|
+
* Prune the install root's lockfile before a tree install (#862): npm's install
|
|
281
|
+
* honors a locked link just as its lock-only run does. Loaded lazily, as above.
|
|
282
|
+
* @param {string} installRoot - The brand root (or standalone target).
|
|
283
|
+
* @param {object} [logger] - Logger with log (silent when omitted).
|
|
284
|
+
*/
|
|
285
|
+
function pruneBrandLockfile(installRoot, logger) {
|
|
286
|
+
const { pruneLockfile } = require('./lockfile.js');
|
|
287
|
+
pruneLockfile({ root: installRoot, log: logger ? (line) => logger.log(line) : undefined });
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Throw when any @omega.js package of the tree still resolves into a checkout
|
|
292
|
+
* (#862): a symlink under the install root's or any target's node_modules, or
|
|
293
|
+
* a resolution that lands in a monorepo. The one check `omega i live` ends on.
|
|
294
|
+
* @param {string} installRoot - The brand root (or standalone target).
|
|
295
|
+
*/
|
|
296
|
+
function assertRegistryTree(installRoot) {
|
|
297
|
+
for (const targetDir of discoverTargets(installRoot)) {
|
|
298
|
+
const scopeDir = path.join(targetDir, 'node_modules', SCOPE);
|
|
299
|
+
// No scope folder here: this target's copies are hoisted, or it has none.
|
|
300
|
+
if (!fs.existsSync(scopeDir)) continue;
|
|
301
|
+
|
|
302
|
+
for (const name of fs.readdirSync(scopeDir)) {
|
|
303
|
+
const installed = path.join(scopeDir, name);
|
|
304
|
+
if (fs.lstatSync(installed).isSymbolicLink()) {
|
|
305
|
+
throw new Error(`omega i live left ${installed} linked into ${path.resolve(scopeDir, fs.readlinkSync(installed))}`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const monorepoRoot = resolveLinkedMonorepo(installRoot);
|
|
311
|
+
if (monorepoRoot) {
|
|
312
|
+
throw new Error(`omega i live left ${installRoot} linked into ${monorepoRoot}`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
279
316
|
/**
|
|
280
317
|
* Whether the install root's lockfile is missing or disagrees with its
|
|
281
318
|
* manifests' @omega.js registry specs: the deploy gate's own read (#938).
|
|
@@ -301,9 +338,10 @@ function brandLockfileStale(installRoot) {
|
|
|
301
338
|
* ONE `npm install` materializes the links for the whole tree. Standalone
|
|
302
339
|
* targets degenerate to themselves.
|
|
303
340
|
*
|
|
304
|
-
* Idempotent: dependencies already resolving to the monorepo copy
|
|
305
|
-
* skipped, and when nothing needs
|
|
306
|
-
* followed by the brand's OWN
|
|
341
|
+
* Idempotent: dependencies already resolving to the monorepo copy AND
|
|
342
|
+
* already declaring its file: spec are skipped, and when nothing needs
|
|
343
|
+
* linking no install runs. An install is followed by the brand's OWN
|
|
344
|
+
* lockfile regeneration (#938).
|
|
307
345
|
* @param {object} options
|
|
308
346
|
* @param {string} options.dir - Target directory to link from (any target in the brand).
|
|
309
347
|
* @param {string} options.monorepoRoot - Monorepo root path.
|
|
@@ -339,13 +377,13 @@ async function linkLocalPackages(options) {
|
|
|
339
377
|
continue;
|
|
340
378
|
}
|
|
341
379
|
|
|
342
|
-
|
|
380
|
+
const spec = `file:${relativeSpecPath(entry.dir, target)}`;
|
|
381
|
+
if (isLinkedTo(entry.dir, entry.name, target) && entry.spec === spec) {
|
|
343
382
|
actions.push({ name: entry.name, dir: entry.dir, target, action: 'skip' });
|
|
344
383
|
logger && logger.log(`${entry.name}: already linked to the monorepo`);
|
|
345
384
|
continue;
|
|
346
385
|
}
|
|
347
386
|
|
|
348
|
-
const spec = `file:${relativeSpecPath(entry.dir, target)}`;
|
|
349
387
|
if (entry.spec === spec) {
|
|
350
388
|
// Spec already correct, only the install is missing — no rewrite,
|
|
351
389
|
// so a committed relative spec is never churned to a new layout.
|
|
@@ -398,8 +436,9 @@ async function linkLocalPackages(options) {
|
|
|
398
436
|
* caller owns that string. Idempotent: registry-spec'd entries are untouched;
|
|
399
437
|
* nothing to flip → no install. Same transactional manifest restore as the
|
|
400
438
|
* linker when the install fails. Either way the brand's OWN lockfile ends up
|
|
401
|
-
* agreeing with the manifests (#938):
|
|
402
|
-
* regenerated alone when nothing flipped but the lock
|
|
439
|
+
* agreeing with the manifests (#938): pruned before the install and
|
|
440
|
+
* regenerated after it, and regenerated alone when nothing flipped but the lock
|
|
441
|
+
* still disagrees. Every run but a dryRun ends on assertRegistryTree() (#862).
|
|
403
442
|
* @param {object} options
|
|
404
443
|
* @param {string} options.dir - Any directory inside the brand.
|
|
405
444
|
* @param {object} [options.logger] - Logger with log/warn (silent when omitted).
|
|
@@ -456,12 +495,21 @@ async function restoreRegistrySpecs(options) {
|
|
|
456
495
|
}
|
|
457
496
|
|
|
458
497
|
if (installNeeded) {
|
|
498
|
+
// The prune below rewrites the lock, so a failed install puts it back too.
|
|
499
|
+
const lockPath = path.join(installRoot, 'package-lock.json');
|
|
500
|
+
const lockBackup = fs.existsSync(lockPath) ? fs.readFileSync(lockPath, 'utf8') : null;
|
|
501
|
+
|
|
459
502
|
try {
|
|
503
|
+
// BEFORE the install (#862): npm keeps a locked link whose checkout
|
|
504
|
+
// satisfies the flipped spec, in the lock and in node_modules' hidden lock.
|
|
505
|
+
pruneBrandLockfile(installRoot, logger);
|
|
506
|
+
fs.rmSync(path.join(installRoot, 'node_modules', '.package-lock.json'), { force: true });
|
|
460
507
|
await safeInstall('npm install', { log: true, config: { cwd: installRoot } });
|
|
461
508
|
} catch (error) {
|
|
462
509
|
for (const [manifestPath, contents] of manifestBackups) {
|
|
463
510
|
fs.writeFileSync(manifestPath, contents);
|
|
464
511
|
}
|
|
512
|
+
if (lockBackup !== null) fs.writeFileSync(lockPath, lockBackup);
|
|
465
513
|
logger && logger.warn(`install failed — restored ${manifestBackups.size} manifest(s) to their file: specs`);
|
|
466
514
|
throw error;
|
|
467
515
|
}
|
|
@@ -476,6 +524,10 @@ async function restoreRegistrySpecs(options) {
|
|
|
476
524
|
await regenerateBrandLockfile(installRoot, logger);
|
|
477
525
|
}
|
|
478
526
|
|
|
527
|
+
// Every run, not only after an install: a brand already on registry specs
|
|
528
|
+
// can still be linked, which is the state this verb exists to end.
|
|
529
|
+
assertRegistryTree(installRoot);
|
|
530
|
+
|
|
479
531
|
return actions;
|
|
480
532
|
}
|
|
481
533
|
|
|
@@ -1981,6 +2033,8 @@ module.exports = {
|
|
|
1981
2033
|
findBrandRoot,
|
|
1982
2034
|
discoverTargets,
|
|
1983
2035
|
frameworkPackagesOf,
|
|
2036
|
+
resolvePackageRealDir,
|
|
2037
|
+
isLocalCheckout,
|
|
1984
2038
|
linkLocalPackages,
|
|
1985
2039
|
restoreRegistrySpecs,
|
|
1986
2040
|
resolveLinkedMonorepo,
|
|
@@ -82,6 +82,34 @@ function dropDrift(lock, drift) {
|
|
|
82
82
|
return dropped;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Prune `root`'s package-lock.json in place: the stale path entries, then the
|
|
87
|
+
* @omega.js entries the deploy gate refuses. The lock-only regeneration runs it
|
|
88
|
+
* first, and so does `omega i live` before its tree install
|
|
89
|
+
* ([#862](https://github.com/Omega-JS-Stack/omega/issues/862)), since that
|
|
90
|
+
* install honors the lock's old links just the same.
|
|
91
|
+
*
|
|
92
|
+
* @param {object} options
|
|
93
|
+
* @param {string} options.root - The install root whose lock is pruned.
|
|
94
|
+
* @param {function} [options.log] - Line sink (silent when omitted).
|
|
95
|
+
* @returns {void}
|
|
96
|
+
*/
|
|
97
|
+
function pruneLockfile({ root, log }) {
|
|
98
|
+
const { lockPath, lock, drift } = brandLockfileDrift({ root });
|
|
99
|
+
|
|
100
|
+
// No lock, or one without a `packages` map, has no entry to prune.
|
|
101
|
+
if (!lock || !lock.packages) return;
|
|
102
|
+
|
|
103
|
+
const pruned = dropStalePaths(lock, root);
|
|
104
|
+
const dropped = dropDrift(lock, drift);
|
|
105
|
+
|
|
106
|
+
if (pruned.length || dropped.length) {
|
|
107
|
+
jetpack.write(lockPath, `${JSON.stringify(lock, null, 2)}\n`);
|
|
108
|
+
}
|
|
109
|
+
if (log && pruned.length) log(`Pruned the lock entries of folders no longer on disk (${pruned.join(', ')}) so npm stops honoring what they declare`);
|
|
110
|
+
if (log && dropped.length) log(`Dropped the stale lock entries of ${dropped.join(', ')} so npm resolves them from the manifests`);
|
|
111
|
+
}
|
|
112
|
+
|
|
85
113
|
/**
|
|
86
114
|
* Regenerate `root`'s package-lock.json from its manifests, lock-only: no
|
|
87
115
|
* scripts, no node_modules writes.
|
|
@@ -92,19 +120,10 @@ function dropDrift(lock, drift) {
|
|
|
92
120
|
* @returns {Promise<void>}
|
|
93
121
|
*/
|
|
94
122
|
async function regenerateLockfile({ root, log }) {
|
|
95
|
-
const
|
|
96
|
-
const original =
|
|
97
|
-
|
|
98
|
-
if (lock && lock.packages) {
|
|
99
|
-
const pruned = dropStalePaths(lock, root);
|
|
100
|
-
const dropped = dropDrift(lock, drift);
|
|
123
|
+
const lockPath = path.join(root, 'package-lock.json');
|
|
124
|
+
const original = jetpack.exists(lockPath) === 'file' ? jetpack.read(lockPath) : null;
|
|
101
125
|
|
|
102
|
-
|
|
103
|
-
jetpack.write(lockPath, `${JSON.stringify(lock, null, 2)}\n`);
|
|
104
|
-
}
|
|
105
|
-
if (log && pruned.length) log(`Pruned the lock entries of folders no longer on disk (${pruned.join(', ')}) so npm stops honoring what they declare`);
|
|
106
|
-
if (log && dropped.length) log(`Dropped the stale lock entries of ${dropped.join(', ')} so npm resolves them from the manifests`);
|
|
107
|
-
}
|
|
126
|
+
pruneLockfile({ root, log });
|
|
108
127
|
|
|
109
128
|
if (log) log(`Regenerating ${path.basename(root)}/package-lock.json...`);
|
|
110
129
|
|
|
@@ -124,4 +143,4 @@ async function regenerateLockfile({ root, log }) {
|
|
|
124
143
|
}
|
|
125
144
|
}
|
|
126
145
|
|
|
127
|
-
module.exports = { regenerateLockfile };
|
|
146
|
+
module.exports = { pruneLockfile, regenerateLockfile };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Build-time logger — timestamped, tag-scoped console output for CLI commands, gulp
|
|
2
|
-
// tasks, and test runners. `new Logger('setup')` then logger.log/error/warn/info,
|
|
2
|
+
// tasks, and test runners. `new Logger('setup')` then logger.log/error/warn/info/debug,
|
|
3
3
|
// which prints `[HH:MM:SS] [@omega.js/<package>:setup] message`.
|
|
4
4
|
//
|
|
5
5
|
// NOT for app/runtime logging — frameworks with runtime logging needs (e.g. desktop's
|
|
@@ -87,8 +87,13 @@ function Logger(name) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// Make methods that log to console with the tag and time: [xx:xx:xx] [@omega.js/pkg:name] message
|
|
90
|
-
['log', 'error', 'warn', 'info'].forEach((method) => {
|
|
90
|
+
['log', 'error', 'warn', 'info', 'debug'].forEach((method) => {
|
|
91
91
|
Logger.prototype[method] = function () {
|
|
92
|
+
// debug is the one opt-in level (docs/shared/logging.md): OMEGA_DEBUG, read live.
|
|
93
|
+
if (method === 'debug' && !process.env.OMEGA_DEBUG) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
92
97
|
const time = new Date().toLocaleTimeString('en-US', {
|
|
93
98
|
hour12: false,
|
|
94
99
|
hour: '2-digit',
|