@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
package/docs/ipc.md DELETED
@@ -1,61 +0,0 @@
1
- # IPC
2
-
3
- Typed channel bus for main ↔ renderer communication. All @omega.js/desktop features register their channels through this single layer rather than calling `ipcMain.handle` directly, so you have one place to look and one place to instrument.
4
-
5
- ## Main-process API
6
-
7
- ```js
8
- omega.ipc.handle(channel, async (payload, evt) => result) // request/response
9
- omega.ipc.unhandle(channel)
10
- omega.ipc.invoke(channel, payload) // call locally (also what renderer triggers)
11
- omega.ipc.on(channel, (payload, evt) => void) // one-way subscribe (renderer → main)
12
- omega.ipc.off(channel, fn)
13
- omega.ipc.broadcast(channel, payload) // → all BrowserWindows
14
- omega.ipc.send(webContents, channel, payload) // → one renderer
15
- omega.ipc.hasHandler(channel)
16
- omega.ipc.listenerCount(channel)
17
- ```
18
-
19
- ## Renderer-process API (via preload contextBridge)
20
-
21
- ```js
22
- await window.desktop.ipc.invoke(channel, payload) // → Promise<result>
23
- const off = window.desktop.ipc.on(channel, (payload) => { ... });
24
- window.desktop.ipc.send(channel, payload); // fire-and-forget
25
- ```
26
-
27
- ## Channel naming
28
-
29
- framework-internal channels are prefixed `desktop:` (e.g. `desktop:storage:get`, `desktop:storage:change`). Consumers are free to use any namespace.
30
-
31
- ## Validation
32
-
33
- - `handle()` throws if `channel` is empty/non-string or `handler` is non-function.
34
- - `handle()` throws on duplicate registration. Call `unhandle()` first if you need to swap.
35
- - `invoke()` rejects with a clear message if no handler is registered for the channel.
36
- - Handler errors propagate through `invoke()` (both main-local and renderer-side) — your renderer's `await window.desktop.ipc.invoke(...)` will reject with the original error message.
37
-
38
- ## Zero-trust payloads
39
-
40
- Registration is validated for you (above) — payload CONTENT is not. Treat every payload reaching a `handle()` / `on()` callback as untrusted input: renderers can be compromised, and apps that embed remote web content (e.g. external pages in `WebContentsView`s) expose the IPC surface to code you don't control.
41
-
42
- - **Validate shape and values before acting** — types match, IDs are well-formed, enums are from the expected set, paths resolve inside the expected roots.
43
- - **Gate any URL arriving via IPC** through `sanitize-url.js` before `shell.openExternal` / `loadURL` (the zero-trust URL rule — see [common-mistakes.md](common-mistakes.md)).
44
- - **Never feed raw payload values** into filesystem paths, shell commands, or `webContents.executeJavaScript`.
45
-
46
- ## Boot order
47
-
48
- `ipc` initializes **before** `storage` so that storage (and every other feature) can register handlers via `ipc.handle`. This is the canonical pattern: don't touch `ipcMain` directly.
49
-
50
- ## Example
51
-
52
- ```js
53
- // main
54
- omega.ipc.handle('user:get-token', async (payload) => {
55
- const token = await fetchToken(payload.userId);
56
- return { token };
57
- });
58
-
59
- // renderer
60
- const { token } = await window.desktop.ipc.invoke('user:get-token', { userId: 'abc' });
61
- ```
@@ -1,53 +0,0 @@
1
- # Lib Modules
2
-
3
- `src/lib/*.js`: every Electron concern is its own module. Each exports one object with `initialize(omega)`; the main-process instance hangs each on itself by name and initializes them in a fixed order at boot (see [boot-sequence.md](boot-sequence.md)). Each module's deep reference lives at `docs/<lib-name>.md`; the module list is in the framework guide's Architecture section ([docs/desktop/index.md](../../../docs/desktop/index.md)).
4
-
5
- ## Lib initialization contract
6
-
7
- Each lib exposes the same skeleton:
8
-
9
- ```js
10
- const myLib = {
11
- _initialized: false,
12
- _omega: null,
13
-
14
- initialize(omega) {
15
- myLib._omega = omega;
16
- // wire IPC handlers, app event listeners, etc.
17
- myLib._initialized = true;
18
- },
19
-
20
- // Public API
21
- doThing() { ... },
22
-
23
- // Disable at runtime (idempotent)
24
- disable() {
25
- // tear down listeners; safe to call multiple times
26
- },
27
- };
28
-
29
- module.exports = myLib;
30
- ```
31
-
32
- Don't use `EventEmitter` unless the lib genuinely emits multiple event types. For "fires once when ready" use a promise; for "broadcasts changes" use IPC with renderer subscriptions.
33
-
34
- ## Adding a new lib
35
-
36
- 1. Create `src/lib/<name>.js` exporting one object with `initialize(omega)`.
37
- 2. Wire it into the boot order in `src/main.js` (or the renderer/preload class if it's a per-context lib): check [boot-sequence.md](boot-sequence.md) for where it belongs and what it may depend on.
38
- 3. Set it on the instance in the `Omega` constructor as `this.<camelCaseName>`, so consumers reach it at runtime as `omega.<camelCaseName>`.
39
- 4. Write tests at every layer the lib has a surface in (see [test-framework.md](test-framework.md)) — at minimum `src/test/suites/main/<name>.test.js`.
40
- 5. Add a `docs/<name>.md` deep reference, add the module's row to the Lib modules table in the framework guide (`docs/desktop/index.md`), and link it from the Documentation index.
41
-
42
- ## Flat file vs directory split
43
-
44
- - **Default to flat `src/lib/<name>.js`.**
45
- - **Split into a directory** (`src/lib/<name>/{index,core,main,renderer,preload}.js`) ONLY when each Electron context has materially different logic that would force ugly runtime branching inside one file. `index.js` becomes a thin context detector that delegates.
46
- - `lib/sentry/` was that split (the SDK has separate main/renderer/preload entry points) until it moved WHOLE into `@omega.js/monitoring` (#380) — the backend and the client needed the same policy, so the shape it proved now lives in the shared package. `lib/restart-manager/` is split for a different, also-valid reason — a **shared-SSOT split**: its `protocol.js` (the wire contract) must be importable by the Restart Manager app via the `exports` map with zero Electron/@omega.js/desktop baggage, so the contract lives in its own pure-Node file next to the main-only `index.js` + `install.js`. `sign-helpers/` is a helpers directory, not a lib.
47
- - Don't split prophylactically; convert when the branching gets ugly.
48
-
49
- ## See also
50
-
51
- - [boot-sequence.md](boot-sequence.md): the fixed `omega.initialize()` order + rationale
52
- - [environment-detection.md](environment-detection.md): cross-context helpers shared by the three processes and the build module
53
- - [test-framework.md](test-framework.md) — the four-layer harness new libs must ship tests in
package/docs/logging.md DELETED
@@ -1,227 +0,0 @@
1
- # Logging
2
-
3
- @omega.js/desktop ships a runtime logger that writes to **both the console and a file on disk**, so production issues are inspectable without remoting into the user's machine.
4
-
5
- ## What you get
6
-
7
- - **One log file**, `runtime.log`, populated by all three Electron processes (main / preload / renderer)
8
- - **Live console output** during development (DevTools console for renderer, terminal stdout for main)
9
- - **Kept across boots** — never truncated; it rotates by size instead (see the lifetime table below), unlike `dev.log`/`build.log`/`test.log`
10
- - **Cross-process timestamps** so log lines from main + preload + renderer interleave in arrival order
11
-
12
- ## Where the file lives
13
-
14
- | Mode | Location |
15
- |---|---|
16
- | Dev (`npm start`, `app.isPackaged === false`) | `<projectRoot>/logs/runtime.log` |
17
- | Prod (installed `.dmg` / `.exe` / `.deb`, `app.isPackaged === true`) | OS log dir: `~/Library/Logs/<ProductName>/runtime.log` (macOS), `%APPDATA%\<ProductName>\logs\runtime.log` (Windows), `~/.config/<ProductName>/logs/runtime.log` (Linux) |
18
-
19
- `<ProductName>` = `config.app.productName` (falls back to `config.brand.name`). @omega.js/desktop calls `app.setName(productName)` at boot so `app.getPath('logs')` uses the human-readable brand name, not `package.json#name`.
20
-
21
- ## How to write logs
22
-
23
- In **main process**:
24
-
25
- ```js
26
- const omega = require('@omega.js/desktop/main');
27
- await omega.initialize();
28
-
29
- omega.logger.log('booted');
30
- omega.logger.warn('connection slow');
31
- omega.logger.error(new Error('boom'));
32
- ```
33
-
34
- In **preload**:
35
-
36
- ```js
37
- const omega = require('@omega.js/desktop/preload');
38
- await omega.initialize();
39
- omega.logger.log('preload ready');
40
- ```
41
-
42
- In **renderer** (use the contextBridge surface, which forwards to main → file):
43
-
44
- ```js
45
- window.desktop.logger.log('user clicked Save');
46
- window.desktop.logger.warn('IPC slow');
47
- window.desktop.logger.error(new Error('ui blew up'));
48
- ```
49
-
50
- All three end up in the same `runtime.log`, prefixed with their scope (`main`, `preload`, `renderer`):
51
-
52
- ```
53
- [2026-05-05 14:32:11.045] [info] main omega.initialize
54
- [2026-05-05 14:32:11.122] [info] main ipc ready
55
- [2026-05-05 14:32:11.187] [info] preload contextBridge exposed
56
- [2026-05-05 14:32:11.401] [info] renderer auth.listen attached
57
- [2026-05-05 14:32:12.998] [warn] main auto-updater check failed: network
58
- ```
59
-
60
- Grep one context with:
61
-
62
- ```bash
63
- grep ' main ' logs/runtime.log
64
- ```
65
-
66
- ## CLI: `npx omega logs`
67
-
68
- For dev-loop convenience. From the consumer project root:
69
-
70
- | Command | Effect |
71
- |---|---|
72
- | `npx omega logs` | Print path, then `tail -50` of the file |
73
- | `npx omega logs --tail` (or `-f`) | Follow mode (like `tail -f`). Ctrl+C to stop. Cross-platform. |
74
- | `npx omega logs --path` (or `-p`) | Print the resolved path only (pipe-friendly) |
75
- | `npx omega logs --open` | Open the log file in OS default editor |
76
- | `npx omega logs --lines=100` | Default mode with custom tail length |
77
-
78
- ### The surface argument
79
-
80
- An optional positional names which of the project's logs to read — `npx omega logs [runtime|dev|build|test]`, resolving `<cwd>/logs/<surface>.log`. It defaults to `runtime`, and every flag above works the same on whichever surface was named:
81
-
82
- ```bash
83
- npx omega logs dev --tail # follow the gulp pipeline live
84
- npx omega logs test --lines=100 # last 100 lines of the previous test run
85
- npx omega logs build --path # just the path, for piping
86
- ```
87
-
88
- Anything else fails naming the four surfaces. (The four files themselves are described in the lifetime table below; `deploy.log` and `signing.log` are not tail targets.)
89
-
90
- `mgr logs` only resolves the dev path (`<cwd>/logs/<surface>.log`). To find the production runtime log on a user's machine, use the table above or call `getLogFilePath()` from app code.
91
-
92
- ## How to find the file path from app code
93
-
94
- ```js
95
- const LoggerLite = require('@omega.js/desktop/lib/logger-lite');
96
- const filePath = LoggerLite.getLogFilePath();
97
- // → '/Users/<user>/Library/Logs/MyApp/runtime.log' in production
98
- ```
99
-
100
- Useful for:
101
- - "Send us your log" buttons in your settings UI
102
- - Programmatic log shipping (e.g. POSTing the file to your support backend)
103
- - Crash reporters that want to attach the runtime log
104
-
105
- ## What @omega.js/desktop logs automatically
106
-
107
- Beyond what you write yourself, @omega.js/desktop emits a fixed set of high-signal lifecycle lines so post-mortem debugging works without redeploying:
108
-
109
- **At boot (`omega.initialize()`):**
110
-
111
- ```
112
- (main) Initializing @omega.js/desktop (main)... pid=12345 platform=darwin arch=arm64 packaged=true argv=["--omega-launched-at-login"]
113
- (startup) startup boot summary — RAW inputs:
114
- (startup) process.argv: ["--omega-launched-at-login"]
115
- (startup) process.platform: darwin
116
- (startup) process.arch: arm64
117
- (startup) app.isPackaged: true
118
- (startup) app.getLoginItemSettings(): {"status":"enabled","openAtLogin":true,"openAsHidden":false,"restoreState":false,"wasOpenedAtLogin":false,"wasOpenedAsHidden":false}
119
- (startup) boot env: {}
120
- (startup) startup boot summary — RESOLVED values:
121
- (startup) config.startup.mode: normal
122
- (startup) config.startup.openAtLogin: {enabled:true, mode:hidden}
123
- (startup) isDev: false
124
- (startup) hasLoginArg: true
125
- (startup) wasLaunchedAtLogin(): true (via argv-flag)
126
- (startup) isLaunchHidden(): true
127
- ```
128
-
129
- The boot summary has two parallel blocks: **RAW inputs** (what the OS / shell gave us) and **RESOLVED values** (what @omega.js/desktop decided to act on). Use it to debug both directions:
130
- - "Why is @omega.js/desktop behaving like X?" → check resolved values
131
- - "Why did @omega.js/desktop decide X?" → check raw inputs
132
-
133
- The `via:` annotation on `wasLaunchedAtLogin()` distinguishes a real login launch (`via:macos-wasOpenedAtLogin`) from a flag-based simulation (`via:argv-flag` — i.e. the user passed `--omega-launched-at-login`).
134
-
135
- **App lifecycle events** (logged from `main.js`):
136
-
137
- ```
138
- app event: before-quit (entering quit sequence — close events bypass hide-on-close)
139
- app event: will-quit
140
- app event: quit code=0
141
- app event: window-all-closed
142
- app event: activate (macOS — dock click or app re-launch)
143
- app event: open-url url=myapp://auth/token?...
144
- app event: render-process-gone reason=crashed exitCode=139
145
- app event: child-process-gone type=GPU reason=killed exitCode=9
146
- process exit code=0
147
- uncaughtException: <stack>
148
- unhandledRejection: <stack>
149
- ```
150
-
151
- **Window lifecycle events** (per named window, logged from `window-manager`):
152
-
153
- ```
154
- createNamed: building "main" (show=false, hideOnClose=true)
155
- createNamed: loaded /path/to/app.asar/dist/views/main/index.html for "main"
156
- window "main": ready-to-show — staying invisible (show:false at create)
157
- window "main": ready-to-show — surfacing
158
- window "main": show event
159
- window "main": hide event
160
- window "main": focus event
161
- window "main": minimize event
162
- window "main": restore event
163
- window "main": close intercepted (hide-on-close) — hiding instead
164
- window "main": close allowed (hideOnClose=true, allowQuit=false, isQuitting=true, force=false)
165
- window "main": closed (destroyed)
166
- ```
167
-
168
- **Re-surface handlers**:
169
-
170
- ```
171
- activate (macOS) — surfacing main (visible=false, minimized=false)
172
- _ensureDockVisible — calling dock.show()
173
- _ensureDockVisible — dock already visible
174
- second-instance argv=["..."] eventArgv=["..."] cwd=/...
175
- second-instance — surfacing main (visible=false, minimized=false)
176
- ```
177
-
178
- These cover everything you'd want when debugging "why did the app go invisible / crash / fail to surface" without needing to attach a debugger.
179
-
180
- ## Log levels
181
-
182
- Standard: `log`, `info`, `warn`, `error`, `debug`. All levels are written to both transports by default.
183
-
184
- To dial down via env vars (useful in CI to silence verbose framework noise):
185
-
186
- | Var | Effect |
187
- |---|---|
188
- | `OMEGA_LOG_LEVEL_FILE=warn` | Only `warn` + `error` reach the file |
189
- | `OMEGA_LOG_LEVEL_CONSOLE=error` | Only `error` reaches stdout/stderr |
190
-
191
- Default is `silly` (everything) on both.
192
-
193
- ## How it works under the hood
194
-
195
- @omega.js/desktop's runtime logger (`lib/logger-lite.js`) detects which process it's in:
196
-
197
- - **Main**: writes to `runtime.log` directly via [electron-log](https://github.com/megahertz/electron-log)'s file transport. Sets up an IPC listener on channel `desktop:log:forward` to receive forwarded calls from preload + renderer.
198
- - **Preload**: writes to console (DevTools) AND forwards each call via `ipcRenderer.send('desktop:log:forward', ...)` to main.
199
- - **Renderer**: same as preload via `window.desktop.logger` (contextBridge surface).
200
- - **Outside Electron** (build/CLI tools that happen to require this module): falls back to console-only.
201
-
202
- File path resolution in main:
203
- 1. Read `app.isPackaged`.
204
- 2. If packaged → `app.getPath('logs')`.
205
- 3. If dev → `<cwd>/logs/`.
206
- 4. `mkdirSync` the dir, point electron-log at `<dir>/runtime.log`.
207
-
208
- The transport is set up lazily on first `log()` call, so importing `LoggerLite` in build/CLI contexts that have no Electron is harmless.
209
-
210
- ## Coexisting with `dev.log`, `build.log`, `test.log`, and `deploy.log`
211
-
212
- Five separate logs in `<projectRoot>/logs/`:
213
-
214
- | File | Source | Lifetime |
215
- |---|---|---|
216
- | `runtime.log` | Packaged-app runtime in dev mode | Persistent, rotates at 10 MB to `runtime.old.log` (one archive generation) |
217
- | `dev.log` | Gulp pipeline + spawned Electron child stdout (`npm start`) | Truncated each `npm start` |
218
- | `build.log` | Gulp pipeline output for production builds/packages (`npm run build` / `package` / `publish`, i.e. `OMEGA_BUILD_MODE=true`) | Truncated each build |
219
- | `test.log` | `npx omega test` runner output (suite names, pass/fail states, harness boot lines) | Truncated each test run |
220
- | `deploy.log` | GH Actions run output, streamed locally by the follower every target's deploy uses (`omega deploy`, `npm run release`) ([#873](https://github.com/Omega-JS-Stack/omega/issues/873); this was `ci.log`) | Truncated each deploy |
221
- | `signing.log` | JSONL signing events from Windows code-signing (local dev fallback; on CI this writes to the runner home as `omega-signing.log` instead) | Appended (not truncated) |
222
-
223
- `dev.log` and `build.log` are the same gulp tee — which one it writes is chosen by `OMEGA_BUILD_MODE`, so they never both fill up in one run. (Disable the tee with `OMEGA_LOG_FILE=false`; override its path with `OMEGA_LOG_FILE=<path>`.)
224
-
225
- They serve different purposes and don't overlap: `dev.log`/`build.log` show you "is the build still running?", `test.log` shows you "which test failed on the last run?", `deploy.log` shows you "did the release workflow pass?", `runtime.log` shows you "is my app's auto-updater finding the right release feed?". All useful.
226
-
227
- In production: only `runtime.log` exists (no project, no gulp, no GH Actions stream).
package/docs/menu.md DELETED
@@ -1,160 +0,0 @@
1
- # Application Menu
2
-
3
- File-based application menu (the macOS menu bar / Windows + Linux menu). Same builder + id-path API as [tray](tray.md) and [context-menu](context-menu.md).
4
-
5
- ## Config
6
-
7
- No config block. Path is conventional: `src/integrations/menu/index.js`. To opt out, call `omega.menu.disable()` from your main entry.
8
-
9
- ## Definition file
10
-
11
- ```js
12
- // src/integrations/menu/index.js
13
- module.exports = ({ omega, menu, defaults }) => {
14
- // Easiest: start from the platform-aware default template.
15
- menu.useDefaults();
16
-
17
- // Mutate by id-path:
18
- menu.show('main/preferences'); // @omega.js/desktop ships this hidden by default
19
- menu.update('main/check-for-updates', { label: 'Get Latest Version' });
20
- menu.insertAfter('main/check-for-updates', {
21
- id: 'main/account', label: 'Account...', click: () => omega.windows.show('account'),
22
- });
23
- menu.remove('view/reload');
24
- menu.hide('main/services');
25
-
26
- // Or add a whole new top-level menu:
27
- menu.menu('Tools', [{ id: 'tools/sync', label: 'Sync Now', click: () => {} }]);
28
- };
29
- ```
30
-
31
- ## Builder API (during definition)
32
-
33
- ```js
34
- menu.menu(label, items) // add a top-level menu bar entry
35
- menu.useDefaults() // populate with the platform-appropriate default template
36
- menu.append(item) // append a top-level descriptor (rare; prefer menu())
37
- menu.clear() // start over
38
- ```
39
-
40
- ## Id-path API
41
-
42
- Same shape across menu / tray / context-menu. Available **during definition** (on the `menu` builder arg) AND **at runtime** on `omega.menu`:
43
-
44
- ```js
45
- .find(idPath) // live descriptor or null
46
- .has(idPath) // bool
47
- .update(idPath, patch) // Object.assign + re-render. returns true if found.
48
- .remove(idPath) // splice + re-render. returns true if removed.
49
- .enable(idPath, bool = true) // sugar over update({enabled})
50
- .show(idPath, bool = true) // sugar over update({visible})
51
- .hide(idPath) // visible:false
52
- .insertBefore(idPath, item) // splice in a sibling
53
- .insertAfter(idPath, item) // splice in a sibling
54
- .appendTo(idPath, item) // push into a submenu (creates submenu if absent)
55
- ```
56
-
57
- Menu ids are **paths** because menus actually nest (`main/check-for-updates`, `view/developer/toggle-devtools`). @omega.js/desktop matches by full id field first; if that misses it walks the path treating each segment as the last component of an id.
58
-
59
- ## Default template ids
60
-
61
- Every item in @omega.js/desktop's default template carries a stable id you can target.
62
-
63
- ### macOS App menu (the one labeled with your app name)
64
-
65
- | ID | Item | Notes |
66
- |---|---|---|
67
- | `main/about` | About | |
68
- | `main/check-for-updates` | Check for Updates… | Auto-updater wired |
69
- | `main/preferences` | Preferences… | `visible:false` by default — use `menu.show('main/preferences')` |
70
- | `main/services` | Services submenu | |
71
- | `main/hide` | Hide | |
72
- | `main/hide-others` | Hide Others | |
73
- | `main/show-all` | Show All | |
74
- | `main/relaunch` | Relaunch | Restarts the app |
75
- | `main/quit` | Quit | |
76
-
77
- ### File menu (win/linux equivalents of the App menu)
78
-
79
- | ID | Item | Notes |
80
- |---|---|---|
81
- | `file/close` | Close (mac only) | |
82
- | `file/preferences` | Preferences… (win/linux) | `visible:false` by default |
83
- | `file/relaunch` | Relaunch (win/linux) | |
84
- | `file/quit` | Exit | |
85
-
86
- ### Cross-platform
87
-
88
- | ID | Item |
89
- |---|---|
90
- | `edit/undo`, `edit/redo`, `edit/cut`, `edit/copy`, `edit/paste`, `edit/select-all`, `edit/delete` | Edit submenu |
91
- | `edit/paste-and-match-style` | mac only |
92
- | `view/reload`, `view/reset-zoom`, `view/zoom-in`, `view/zoom-out`, `view/toggle-fullscreen` | View submenu |
93
- | `view/developer` | Submenu (dev mode only) |
94
- | `view/developer/toggle-devtools` | Toggle Developer Tools |
95
- | `view/developer/inspect-elements` | Inspect Element |
96
- | `view/developer/force-reload` | Force Reload |
97
- | `view/developer/simulate-update` | Simulate update submenu (see [docs/auto-updater.md](auto-updater.md)) |
98
- | `view/developer/simulate-update/available`, `.../unavailable`, `.../error` | Run the update simulator for one scenario |
99
- | `window/minimize`, `window/zoom`, `window/front` | Window submenu (mac) |
100
- | `window/minimize`, `window/close` | Window submenu (win/linux) |
101
-
102
- ### Help menu
103
-
104
- | ID | Item | Notes |
105
- |---|---|---|
106
- | `help/check-for-updates` | Check for Updates… (win/linux only) | Auto-updater wired |
107
- | `help/website` | "`<brandName>` Home" | Only when `brand.url` configured |
108
-
109
- ### Development menu (dev mode only)
110
-
111
- Top-level, only visible when `omega.isDevelopment()`. Mirrors legacy @omega.js/desktop's developer utilities.
112
-
113
- | ID | Item | Action |
114
- |---|---|---|
115
- | `development/open-exe-folder` | Open exe folder | Reveals `app.getPath('exe')` |
116
- | `development/open-user-data` | Open user data folder | Reveals `app.getPath('userData')` |
117
- | `development/open-logs` | Open logs folder | Reveals `app.getPath('logs')` |
118
- | `development/open-app-config` | Open app config folder | Reveals `app.getPath('appData')` |
119
- | `development/test-error` | Throw test error | Throws an uncaught error (verifies sentry / error handling) |
120
-
121
- ## Built-in framework items
122
-
123
- `main/check-for-updates` (mac) and `help/check-for-updates` (win/linux) are **wired to `omega.autoUpdater`**:
124
- - Label updates dynamically: *Checking…*, *Downloading 42%*, *Restart to Update v1.2.3*, *You're up to date*.
125
- - Click triggers `autoUpdater.checkNow()` or `autoUpdater.installNow()` depending on state.
126
-
127
- The same hook also patches the tray's `check-for-updates` item if present, so both UIs stay in lockstep.
128
-
129
- Patch or remove either as needed — the auto-updater hook is a no-op when the item is missing.
130
-
131
- ## Item descriptors
132
-
133
- Same dynamic conveniences as tray:
134
- - `label` / `enabled` / `visible` / `checked` may be functions, evaluated on every `refresh()`
135
- - `click` wrapped to catch errors
136
- - `submenu` recursively resolved
137
-
138
- ## Runtime API on `omega.menu`
139
-
140
- ```js
141
- omega.menu.refresh() // re-evaluate dynamic state
142
- omega.menu.define(fn) // replace the whole definition at runtime
143
- omega.menu.destroy() // tear down (mostly for tests)
144
- omega.menu.disable() // turn the menu off entirely (idempotent)
145
-
146
- // Id-path API — same as listed above.
147
- omega.menu.find('main/check-for-updates')
148
- omega.menu.update('main/check-for-updates', { label: 'Updates...' })
149
- omega.menu.remove('view/reload')
150
- omega.menu.insertAfter('main/check-for-updates', { id: 'main/account', label: 'Account...' })
151
-
152
- // Inspection
153
- omega.menu.getItems() // top-level descriptors (shallow copy)
154
- omega.menu.isRendered() // bool
155
- omega.menu.getMenu() // the underlying Electron Menu instance
156
- ```
157
-
158
- ## Default scaffold
159
-
160
- The scaffold every verb runs ships `src/integrations/menu/index.js` calling `menu.useDefaults()` plus commented-out examples (show preferences, insertAfter, update, remove, hide, add a Tools menu, appendTo).