@omega.js/desktop 0.53.0 → 0.54.1

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 (161) hide show
  1. package/README.md +38 -38
  2. package/dist/cli-run.js +4 -1
  3. package/dist/cli.js +2 -2
  4. package/dist/commands/cdp/client.js +1 -1
  5. package/dist/commands/cdp.js +1 -1
  6. package/dist/commands/clean.js +2 -3
  7. package/dist/commands/dev.js +25 -0
  8. package/dist/commands/lib/ensure-target.js +12 -17
  9. package/dist/commands/lib/migrate.js +17 -0
  10. package/dist/commands/logs.js +1 -1
  11. package/dist/commands/release.js +1 -1
  12. package/dist/commands/test.js +4 -4
  13. package/dist/commands/update.js +5 -4
  14. package/dist/defaults/.github/workflows/build.yml +18 -18
  15. package/dist/defaults/_.gitignore +0 -2
  16. package/dist/defaults/_mas/README.md +3 -3
  17. package/dist/defaults/config/certs/README.md +1 -1
  18. package/dist/defaults/config/omega.json5 +36 -36
  19. package/dist/defaults/docs/README.md +3 -3
  20. package/dist/defaults/gulpfile.js +1 -1
  21. package/dist/defaults/hooks/build/post.js +1 -1
  22. package/dist/defaults/hooks/build/pre.js +1 -1
  23. package/dist/defaults/hooks/notarize/post.js +2 -2
  24. package/dist/defaults/hooks/release/post.js +1 -1
  25. package/dist/defaults/hooks/release/pre.js +1 -1
  26. package/dist/defaults/src/assets/scss/pages/about.scss +1 -1
  27. package/dist/defaults/src/assets/scss/pages/main.scss +1 -1
  28. package/dist/defaults/src/assets/scss/pages/settings.scss +1 -1
  29. package/dist/defaults/src/integrations/context-menu/index.js +11 -11
  30. package/dist/defaults/src/integrations/menu/index.js +5 -5
  31. package/dist/defaults/src/integrations/tray/index.js +9 -9
  32. package/dist/defaults/src/main.js +2 -2
  33. package/dist/defaults/src/preload.js +1 -1
  34. package/dist/defaults/test/README.md +3 -3
  35. package/dist/defaults/test/_init.js +1 -1
  36. package/dist/gulp/tasks/audit.js +5 -8
  37. package/dist/lib/restart-manager/index.js +1 -1
  38. package/dist/lib/restart-manager/install.js +1 -1
  39. package/dist/lib/restart-manager/protocol.js +1 -1
  40. package/dist/main.js +4 -3
  41. package/dist/preload.js +1 -1
  42. package/dist/test/suites/build/audit.test.js +20 -7
  43. package/dist/test/suites/build/build-workflow-jobs.test.js +2 -2
  44. package/dist/test/suites/build/cli.test.js +28 -0
  45. package/dist/test/suites/build/defaults-em-dash.test.js +22 -0
  46. package/dist/test/suites/build/defaults-scaffold.test.js +19 -5
  47. package/dist/test/suites/build/deploy-direct.test.js +7 -5
  48. package/dist/test/suites/build/deploy-dispatch.test.js +2 -1
  49. package/dist/test/suites/build/deploy-hook.test.js +4 -2
  50. package/dist/test/suites/build/dev-verb.test.js +67 -0
  51. package/dist/test/suites/build/ensure-target.test.js +11 -3
  52. package/dist/test/suites/build/merge-line-files.test.js +6 -6
  53. package/dist/test/suites/build/migrate.test.js +29 -0
  54. package/dist/test/suites/build/project-scripts-deps.test.js +6 -10
  55. package/dist/test/suites/build/runner-env-write.test.js +73 -0
  56. package/dist/test/suites/build/runner.test.js +9 -8
  57. package/dist/test/suites/build/setup-scripts.test.js +27 -0
  58. package/dist/test/suites/build/validate-config.test.js +13 -2
  59. package/dist/test/suites/build/verb-logs.test.js +20 -0
  60. package/dist/test/suites/renderer/window-desktop-surface.test.js +1 -1
  61. package/dist/utils/build-pipeline.js +4 -4
  62. package/dist/utils/runner-env.js +13 -28
  63. package/dist/vendor/config/company.js +46 -14
  64. package/dist/vendor/config/defaults.js +30 -7
  65. package/dist/vendor/config/edit.js +25 -3
  66. package/dist/vendor/config/env-delivery.js +1 -1
  67. package/dist/vendor/config/env-schema.js +3 -6
  68. package/dist/vendor/config/env.js +34 -22
  69. package/dist/vendor/config/index.js +13 -17
  70. package/dist/vendor/config/load.js +15 -7
  71. package/dist/vendor/config/repo.js +10 -27
  72. package/dist/vendor/config/schema-client.js +64 -0
  73. package/dist/vendor/config/schema-cloud.js +38 -0
  74. package/dist/vendor/config/schema-manager.js +118 -0
  75. package/dist/vendor/config/schema-overrides.js +68 -0
  76. package/dist/vendor/config/schema.js +99 -152
  77. package/dist/vendor/config/validate.js +97 -77
  78. package/dist/vendor/devkit/agents-md.js +233 -0
  79. package/dist/vendor/devkit/attach-log-file.js +15 -1
  80. package/dist/vendor/devkit/ci-workflows.js +30 -30
  81. package/dist/vendor/devkit/cli-router.js +13 -7
  82. package/dist/vendor/devkit/defaults-engine.js +9 -43
  83. package/dist/vendor/devkit/deploy-snapshot.js +44 -9
  84. package/dist/vendor/devkit/env-lines.js +183 -0
  85. package/dist/vendor/devkit/local.js +62 -10
  86. package/dist/vendor/devkit/lockfile.js +32 -13
  87. package/dist/vendor/devkit/logger.js +7 -2
  88. package/dist/vendor/devkit/merge-line-files.js +219 -176
  89. package/dist/vendor/devkit/omega-bin.js +208 -111
  90. package/dist/vendor/devkit/preludes/docs-sync.js +52 -0
  91. package/dist/vendor/devkit/preludes/index.js +1 -0
  92. package/dist/vendor/devkit/target-picker.js +45 -0
  93. package/dist/vendor/devkit/test/dashed-files.js +37 -0
  94. package/dist/vendor/devkit/test/run-verb-under-tee.js +71 -0
  95. package/dist/vendor/devkit/update.js +15 -15
  96. package/dist/vendor/devkit/verb-scripts.js +40 -0
  97. package/dist/vendor/devkit/verbs.js +170 -0
  98. package/package.json +18 -24
  99. package/dist/commands/install.js +0 -37
  100. package/dist/defaults/AGENTS.md +0 -119
  101. package/dist/defaults/CLAUDE.md +0 -1
  102. package/dist/vendor/config/env-retired.js +0 -137
  103. package/dist/vendor/config/retired-keys.js +0 -635
  104. package/docs/analytics.md +0 -140
  105. package/docs/app-state.md +0 -92
  106. package/docs/audit.md +0 -69
  107. package/docs/auth.md +0 -284
  108. package/docs/auto-updater.md +0 -243
  109. package/docs/boot-sequence.md +0 -44
  110. package/docs/build-system.md +0 -169
  111. package/docs/cdp-debugging.md +0 -169
  112. package/docs/common-mistakes.md +0 -21
  113. package/docs/config-schema.md +0 -120
  114. package/docs/context-menu.md +0 -112
  115. package/docs/context.md +0 -81
  116. package/docs/css.md +0 -84
  117. package/docs/deep-link.md +0 -186
  118. package/docs/environment-detection.md +0 -112
  119. package/docs/fontawesome.md +0 -109
  120. package/docs/hooks.md +0 -89
  121. package/docs/icons.md +0 -79
  122. package/docs/index.md +0 -328
  123. package/docs/installer-options.md +0 -165
  124. package/docs/ipc.md +0 -61
  125. package/docs/lib-modules.md +0 -53
  126. package/docs/logging.md +0 -227
  127. package/docs/menu.md +0 -160
  128. package/docs/releasing.md +0 -239
  129. package/docs/remote-config.md +0 -118
  130. package/docs/remote-scripts.md +0 -144
  131. package/docs/restart-manager.md +0 -144
  132. package/docs/runner.md +0 -290
  133. package/docs/sentry.md +0 -97
  134. package/docs/shared/agent-docs.md +0 -89
  135. package/docs/shared/analytics.md +0 -612
  136. package/docs/shared/brands.md +0 -57
  137. package/docs/shared/breaking-changes.md +0 -917
  138. package/docs/shared/config.md +0 -1948
  139. package/docs/shared/deploys.md +0 -341
  140. package/docs/shared/icons.md +0 -219
  141. package/docs/shared/local-dev.md +0 -167
  142. package/docs/shared/logging.md +0 -205
  143. package/docs/shared/monitoring.md +0 -167
  144. package/docs/shared/publishing.md +0 -187
  145. package/docs/shared/rulings.md +0 -34
  146. package/docs/shared/testing.md +0 -147
  147. package/docs/shared/theming.md +0 -629
  148. package/docs/shared/translation.md +0 -342
  149. package/docs/shared/updates.md +0 -61
  150. package/docs/signing.md +0 -293
  151. package/docs/startup.md +0 -142
  152. package/docs/storage.md +0 -59
  153. package/docs/templating.md +0 -101
  154. package/docs/test-boot-layer.md +0 -157
  155. package/docs/test-framework.md +0 -362
  156. package/docs/themes.md +0 -149
  157. package/docs/tooltips.md +0 -99
  158. package/docs/tray.md +0 -164
  159. package/docs/usage.md +0 -58
  160. package/docs/verts.md +0 -62
  161. package/docs/windows.md +0 -149
@@ -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), `mgr i local`
20
- * (@omega.js/backend, @omega.js/desktop, @omega.js/extension), and the monorepo's
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 are
305
- * skipped, and when nothing needs linking no install runs. An install is
306
- * followed by the brand's OWN lockfile regeneration (#938).
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
- if (isLinkedTo(entry.dir, entry.name, target)) {
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): regenerated after the install, and
402
- * regenerated alone when nothing flipped but the lock still disagrees.
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
 
@@ -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 { lockPath, lock, drift } = brandLockfileDrift({ root });
96
- const original = lock ? jetpack.read(lockPath) : null;
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
- if (pruned.length || dropped.length) {
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',