@zenbujs/core 0.0.4 → 0.0.8
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/dist/{advice-config-BLXjqjGN.mjs → advice-config-DXSIo0sg.mjs} +49 -38
- package/dist/advice.d.mts +8 -8
- package/dist/advice.mjs +2 -2
- package/dist/base-window-BxBZ2md_.mjs +143 -0
- package/dist/build-config-Dzg2frpk.d.mts +215 -0
- package/dist/build-config-pWdmLnrk.mjs +53 -0
- package/dist/{build-electron-C3Beey84.mjs → build-electron-Dsbb1EMl.mjs} +308 -120
- package/dist/{build-source-BvC4bPqH.mjs → build-source-d1J3shV8.mjs} +62 -27
- package/dist/chunk-DsiFFCwN.mjs +16 -0
- package/dist/cli/bin.mjs +7 -7
- package/dist/cli/build.d.mts +2 -2
- package/dist/cli/build.mjs +2 -3
- package/dist/cli/resolve-config.mjs +3 -2
- package/dist/{cli-F0B4dvSg.mjs → cli-kL6mPgBE.mjs} +4 -4
- package/dist/{config-BlRXeUXx.mjs → config-BK78JDRI.mjs} +1 -1
- package/dist/config.d.mts +3 -2
- package/dist/config.mjs +3 -3
- package/dist/{db-Cd5ETuPG.mjs → db-Bc292RYo.mjs} +2 -2
- package/dist/db.d.mts +1 -1
- package/dist/db.mjs +2 -2
- package/dist/dev-B2emj0HZ.mjs +301 -0
- package/dist/env-bootstrap.d.mts +1 -1
- package/dist/env-bootstrap.mjs +52 -1
- package/dist/events.d.mts +19 -0
- package/dist/events.mjs +1 -0
- package/dist/host-version-BIrF8tX7.mjs +65 -0
- package/dist/index-w5QyDjuf.d.mts +780 -0
- package/dist/index.d.mts +5 -6
- package/dist/index.mjs +5 -5
- package/dist/installing-preload.cjs +60 -0
- package/dist/launcher.mjs +2615 -122
- package/dist/{link-BJmsKgPa.mjs → link-glX89NV5.mjs} +215 -89
- package/dist/{load-config-BG2tPIfF.mjs → load-config-C4Oe2qZO.mjs} +22 -3
- package/dist/loaders/zenbu.d.mts +1 -0
- package/dist/loaders/zenbu.mjs +108 -86
- package/dist/{monorepo-DCruz9Jx.mjs → monorepo-Dct-kkbQ.mjs} +3 -0
- package/dist/node-loader.mjs +1 -1
- package/dist/{publish-source-34Hn9zb0.mjs → publish-source-Dq2c0iOw.mjs} +2 -2
- package/dist/react.d.mts +56 -7
- package/dist/react.mjs +118 -7
- package/dist/registry-CMp8FYgS.d.mts +47 -0
- package/dist/registry-generated.d.mts +26 -0
- package/dist/registry-generated.mjs +1 -0
- package/dist/registry.d.mts +2 -2
- package/dist/{reloader-DJoCB0bC.mjs → reloader-B22UiNA2.mjs} +7 -7
- package/dist/{renderer-host-ztaSIOGx.mjs → renderer-host-DD16MXhI.mjs} +178 -57
- package/dist/{rpc-CsgWnlZx.mjs → rpc-C4_NQmpT.mjs} +11 -8
- package/dist/rpc.d.mts +1 -1
- package/dist/rpc.mjs +1 -1
- package/dist/runtime-BQWntcOb.d.mts +218 -0
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.mjs +578 -2
- package/dist/{schema-DvT61x2_.d.mts → schema-CjrMVk36.d.mts} +3 -3
- package/dist/schema.d.mts +1 -1
- package/dist/schema.mjs +27 -1
- package/dist/{server-DB3Eki_G.mjs → server-CZLMF8Dj.mjs} +6 -6
- package/dist/services/default.d.mts +3 -3
- package/dist/services/default.mjs +14 -13
- package/dist/services/index.d.mts +2 -276
- package/dist/services/index.mjs +8 -7
- package/dist/setup-gate.d.mts +1 -1
- package/dist/setup-gate.mjs +341 -1
- package/dist/{transform-DJH3vN4b.mjs → transform-BzrwkEdf.mjs} +23 -917
- package/dist/{transport-BMSzG2-F.mjs → transport-F2hv_OEm.mjs} +1 -1
- package/dist/updater-DCkz9M1c.mjs +1008 -0
- package/dist/{vite-plugins-t4MlFcz3.mjs → vite-plugins-tt6KAtyE.mjs} +27 -26
- package/dist/vite.d.mts +3 -3
- package/dist/vite.mjs +1 -1
- package/dist/{window-DUvMTons.mjs → window-YFKvAM0l.mjs} +36 -19
- package/dist/{write-9dRFczGJ.mjs → write-DgIRjo23.mjs} +1 -1
- package/package.json +18 -5
- package/dist/advice-config-D6K_a7e9.mjs +0 -2
- package/dist/base-window-D8CpxMU3.mjs +0 -94
- package/dist/base-window-OXg2KSyP.mjs +0 -2
- package/dist/build-config-BwnnfrN-.mjs +0 -23
- package/dist/chunk-Dm34NbLt.mjs +0 -6
- package/dist/config-Ch1FreWU.mjs +0 -2
- package/dist/db-Bz_CDIWg.mjs +0 -2
- package/dist/dev-DLutFPyo.mjs +0 -85
- package/dist/env-bootstrap-rj7I-59x.mjs +0 -53
- package/dist/http-B36qtsm0.mjs +0 -2
- package/dist/load-config-CQG4297M.mjs +0 -2
- package/dist/registry-CioEYLI5.d.mts +0 -61
- package/dist/reloader-FeHKV2jd.mjs +0 -2
- package/dist/renderer-host-BQpS0ZM2.mjs +0 -2
- package/dist/rpc-D_s7-WZe.mjs +0 -2
- package/dist/runtime-C95iyVn6.mjs +0 -461
- package/dist/runtime-CsiDppGF.d.mts +0 -149
- package/dist/schema-dGK6qkfR.mjs +0 -28
- package/dist/server-CgzQOPSW.mjs +0 -2
- package/dist/setup-gate-D8XfYY52.mjs +0 -140
- package/dist/transforms-DVoy8dCu.mjs +0 -47
- package/dist/transforms-EVd5Fgyk.d.mts +0 -136
- package/dist/view-registry-2zePxTEg.mjs +0 -2
- package/dist/window-S3TlTXlK.mjs +0 -2
- /package/dist/{env-bootstrap-uCKbw2q8.d.mts → env-bootstrap-rTs8KR3-.d.mts} +0 -0
- /package/dist/{index-CE0iPntP.d.mts → index-C-ALz_SH.d.mts} +0 -0
- /package/dist/{index-CKKoxA9V.d.mts → index-ClXLQ1fw.d.mts} +0 -0
- /package/dist/{index-UK58xuoR.d.mts → index-DeDxePAa.d.mts} +0 -0
- /package/dist/{log-CyKv8hQg.mjs → log-6rzaCV0I.mjs} +0 -0
- /package/dist/{mirror-sync-EiWvdzTJ.mjs → mirror-sync-pYU6f3-c.mjs} +0 -0
- /package/dist/{node-CvZnTx53.mjs → node-BhfLKYCi.mjs} +0 -0
- /package/dist/{schema-CIg4GzHQ.mjs → schema-Ca7SxXgS.mjs} +0 -0
- /package/dist/{setup-gate-D62nX5lk.d.mts → setup-gate-BQq0QgZH.d.mts} +0 -0
- /package/dist/{src-pELM4_iH.mjs → src-Cven45mq.mjs} +0 -0
- /package/dist/{trace-DCB7qFzT.mjs → trace-BaVg0rnY.mjs} +0 -0
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as __exportAll } from "./chunk-DsiFFCwN.mjs";
|
|
2
|
+
import { getPlugins, runtime } from "./runtime.mjs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { fileURLToPath } from "node:url";
|
|
4
5
|
//#region src/services/advice-config.ts
|
|
6
|
+
var advice_config_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
getAdvice: () => getAdvice,
|
|
8
|
+
getAllAdviceTypes: () => getAllAdviceTypes,
|
|
9
|
+
getAllContentScriptPaths: () => getAllContentScriptPaths,
|
|
10
|
+
getAllTypes: () => getAllTypes,
|
|
11
|
+
getContentScripts: () => getContentScripts,
|
|
12
|
+
registerAdvice: () => registerAdvice,
|
|
13
|
+
registerContentScript: () => registerContentScript
|
|
14
|
+
});
|
|
5
15
|
/**
|
|
6
16
|
* Find the plugin whose `dir` contains the file at `metaUrl`. The runtime
|
|
7
17
|
* plugin registry (populated by the loader-emitted barrel) is the source
|
|
@@ -43,64 +53,65 @@ const RESOLVED_PREFIX = "\0@advice-prelude/";
|
|
|
43
53
|
const APP_RENDERER_RELOADER_ID = "app";
|
|
44
54
|
const adviceEntries = /* @__PURE__ */ new Map();
|
|
45
55
|
const contentScripts = /* @__PURE__ */ new Map();
|
|
46
|
-
function invalidatePrelude(
|
|
56
|
+
function invalidatePrelude(type) {
|
|
47
57
|
try {
|
|
48
58
|
const reloader = runtime.getSlot("reloader")?.instance;
|
|
49
59
|
if (!reloader) return;
|
|
50
60
|
const coreEntry = reloader.get(APP_RENDERER_RELOADER_ID);
|
|
51
61
|
if (!coreEntry?.viteServer) return;
|
|
52
62
|
const graph = coreEntry.viteServer.moduleGraph;
|
|
53
|
-
const
|
|
54
|
-
const prefix = RESOLVED_PREFIX + s;
|
|
63
|
+
const invalidateMatching = (test) => {
|
|
55
64
|
const ids = [];
|
|
56
65
|
for (const id of graph.idToModuleMap.keys()) {
|
|
57
66
|
if (typeof id !== "string") continue;
|
|
58
|
-
if (id
|
|
67
|
+
if (test(id)) ids.push(id);
|
|
59
68
|
}
|
|
60
69
|
for (const id of ids) {
|
|
61
70
|
const mod = graph.getModuleById(id);
|
|
62
71
|
if (mod) graph.invalidateModule(mod);
|
|
63
72
|
}
|
|
64
73
|
};
|
|
65
|
-
if (
|
|
66
|
-
else
|
|
74
|
+
if (type === "*") invalidateMatching((id) => id.startsWith(RESOLVED_PREFIX));
|
|
75
|
+
else {
|
|
76
|
+
const prefix = RESOLVED_PREFIX + type;
|
|
77
|
+
invalidateMatching((id) => id === prefix || id.startsWith(prefix + "?"));
|
|
78
|
+
}
|
|
67
79
|
} catch {}
|
|
68
80
|
}
|
|
69
|
-
function emitReload(
|
|
70
|
-
invalidatePrelude(
|
|
81
|
+
function emitReload(type) {
|
|
82
|
+
invalidatePrelude(type);
|
|
71
83
|
try {
|
|
72
84
|
const rpc = runtime.getSlot("rpc")?.instance;
|
|
73
85
|
if (!rpc) return;
|
|
74
|
-
|
|
75
|
-
else rpc.emit.advice.reload({ scope });
|
|
86
|
+
rpc.emit.advice.reload({ type });
|
|
76
87
|
} catch {}
|
|
77
88
|
}
|
|
78
|
-
function registerAdvice(
|
|
89
|
+
function registerAdvice(type, entry, meta) {
|
|
79
90
|
const resolvedEntry = {
|
|
80
91
|
...entry,
|
|
81
92
|
modulePath: resolvePluginPath(entry.modulePath, meta)
|
|
82
93
|
};
|
|
83
|
-
const list = adviceEntries.get(
|
|
94
|
+
const list = adviceEntries.get(type) ?? [];
|
|
84
95
|
list.push(resolvedEntry);
|
|
85
|
-
adviceEntries.set(
|
|
86
|
-
emitReload(
|
|
96
|
+
adviceEntries.set(type, list);
|
|
97
|
+
emitReload(type);
|
|
87
98
|
return () => {
|
|
88
|
-
const current = adviceEntries.get(
|
|
99
|
+
const current = adviceEntries.get(type);
|
|
89
100
|
if (!current) return;
|
|
90
101
|
const idx = current.indexOf(resolvedEntry);
|
|
91
102
|
if (idx >= 0) current.splice(idx, 1);
|
|
92
|
-
if (current.length === 0) adviceEntries.delete(
|
|
93
|
-
emitReload(
|
|
103
|
+
if (current.length === 0) adviceEntries.delete(type);
|
|
104
|
+
emitReload(type);
|
|
94
105
|
};
|
|
95
106
|
}
|
|
96
|
-
function getAdvice(
|
|
97
|
-
return adviceEntries.get(
|
|
107
|
+
function getAdvice(type) {
|
|
108
|
+
return adviceEntries.get(type) ?? [];
|
|
98
109
|
}
|
|
99
|
-
function
|
|
110
|
+
function getAllAdviceTypes() {
|
|
100
111
|
return [...adviceEntries.keys()];
|
|
101
112
|
}
|
|
102
113
|
/**
|
|
103
|
-
* Register a content script for the given
|
|
114
|
+
* Register a content script for the given view type. `modulePath` is normally
|
|
104
115
|
* a path relative to the plugin root (the folder with `zenbu.plugin.json`);
|
|
105
116
|
* pass `import.meta` so we can resolve it. Absolute paths are accepted as
|
|
106
117
|
* an escape hatch.
|
|
@@ -109,35 +120,35 @@ function getAllAdviceScopes() {
|
|
|
109
120
|
* registerContentScript("app", "src/content/clock.tsx", import.meta),
|
|
110
121
|
* )
|
|
111
122
|
*/
|
|
112
|
-
function registerContentScript(
|
|
123
|
+
function registerContentScript(type, modulePath, meta) {
|
|
113
124
|
const entry = { path: resolvePluginPath(modulePath, meta) };
|
|
114
|
-
const list = contentScripts.get(
|
|
125
|
+
const list = contentScripts.get(type) ?? [];
|
|
115
126
|
list.push(entry);
|
|
116
|
-
contentScripts.set(
|
|
117
|
-
emitReload(
|
|
127
|
+
contentScripts.set(type, list);
|
|
128
|
+
emitReload(type === "*" ? "*" : type);
|
|
118
129
|
return () => {
|
|
119
|
-
const current = contentScripts.get(
|
|
130
|
+
const current = contentScripts.get(type);
|
|
120
131
|
if (!current) return;
|
|
121
132
|
const idx = current.indexOf(entry);
|
|
122
133
|
if (idx >= 0) current.splice(idx, 1);
|
|
123
|
-
if (current.length === 0) contentScripts.delete(
|
|
124
|
-
emitReload(
|
|
134
|
+
if (current.length === 0) contentScripts.delete(type);
|
|
135
|
+
emitReload(type === "*" ? "*" : type);
|
|
125
136
|
};
|
|
126
137
|
}
|
|
127
|
-
function getContentScripts(
|
|
128
|
-
const scoped = (contentScripts.get(
|
|
129
|
-
return [...
|
|
138
|
+
function getContentScripts(type) {
|
|
139
|
+
const scoped = (contentScripts.get(type) ?? []).map((e) => e.path);
|
|
140
|
+
return [...type !== "*" ? (contentScripts.get("*") ?? []).map((e) => e.path) : [], ...scoped];
|
|
130
141
|
}
|
|
131
142
|
function getAllContentScriptPaths() {
|
|
132
143
|
const paths = [];
|
|
133
144
|
for (const list of contentScripts.values()) for (const entry of list) paths.push(entry.path);
|
|
134
145
|
return paths;
|
|
135
146
|
}
|
|
136
|
-
function
|
|
137
|
-
const
|
|
138
|
-
for (const k of adviceEntries.keys())
|
|
139
|
-
for (const k of contentScripts.keys()) if (k !== "*")
|
|
140
|
-
return [...
|
|
147
|
+
function getAllTypes() {
|
|
148
|
+
const types = /* @__PURE__ */ new Set();
|
|
149
|
+
for (const k of adviceEntries.keys()) types.add(k);
|
|
150
|
+
for (const k of contentScripts.keys()) if (k !== "*") types.add(k);
|
|
151
|
+
return [...types];
|
|
141
152
|
}
|
|
142
153
|
//#endregion
|
|
143
|
-
export {
|
|
154
|
+
export { getAllTypes as a, registerContentScript as c, getAllContentScriptPaths as i, getAdvice as n, getContentScripts as o, getAllAdviceTypes as r, registerAdvice as s, advice_config_exports as t };
|
package/dist/advice.d.mts
CHANGED
|
@@ -15,11 +15,11 @@ interface ViewAdviceEntry {
|
|
|
15
15
|
type AdviceSpec = Omit<ViewAdviceEntry, "modulePath"> & {
|
|
16
16
|
modulePath: string;
|
|
17
17
|
};
|
|
18
|
-
declare function registerAdvice(
|
|
19
|
-
declare function getAdvice(
|
|
20
|
-
declare function
|
|
18
|
+
declare function registerAdvice(type: string, entry: AdviceSpec, meta?: ImportMeta): () => void;
|
|
19
|
+
declare function getAdvice(type: string): ViewAdviceEntry[];
|
|
20
|
+
declare function getAllAdviceTypes(): string[];
|
|
21
21
|
/**
|
|
22
|
-
* Register a content script for the given
|
|
22
|
+
* Register a content script for the given view type. `modulePath` is normally
|
|
23
23
|
* a path relative to the plugin root (the folder with `zenbu.plugin.json`);
|
|
24
24
|
* pass `import.meta` so we can resolve it. Absolute paths are accepted as
|
|
25
25
|
* an escape hatch.
|
|
@@ -28,9 +28,9 @@ declare function getAllAdviceScopes(): string[];
|
|
|
28
28
|
* registerContentScript("app", "src/content/clock.tsx", import.meta),
|
|
29
29
|
* )
|
|
30
30
|
*/
|
|
31
|
-
declare function registerContentScript(
|
|
32
|
-
declare function getContentScripts(
|
|
31
|
+
declare function registerContentScript(type: string, modulePath: string, meta?: ImportMeta): () => void;
|
|
32
|
+
declare function getContentScripts(type: string): string[];
|
|
33
33
|
declare function getAllContentScriptPaths(): string[];
|
|
34
|
-
declare function
|
|
34
|
+
declare function getAllTypes(): string[];
|
|
35
35
|
//#endregion
|
|
36
|
-
export { type AdviceSpec, type ViewAdviceEntry, getAdvice,
|
|
36
|
+
export { type AdviceSpec, type ViewAdviceEntry, getAdvice, getAllAdviceTypes, getAllContentScriptPaths, getAllTypes, getContentScripts, registerAdvice, registerContentScript };
|
package/dist/advice.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { getAdvice,
|
|
1
|
+
import { a as getAllTypes, c as registerContentScript, i as getAllContentScriptPaths, n as getAdvice, o as getContentScripts, r as getAllAdviceTypes, s as registerAdvice } from "./advice-config-DXSIo0sg.mjs";
|
|
2
|
+
export { getAdvice, getAllAdviceTypes, getAllContentScriptPaths, getAllTypes, getContentScripts, registerAdvice, registerContentScript };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { n as __exportAll } from "./chunk-DsiFFCwN.mjs";
|
|
2
|
+
import { Service, getAppEntrypoint, runtime } from "./runtime.mjs";
|
|
3
|
+
import { t as createLogger } from "./log-6rzaCV0I.mjs";
|
|
4
|
+
import { a as DbService } from "./renderer-host-DD16MXhI.mjs";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { nanoid } from "nanoid";
|
|
8
|
+
import { BaseWindow } from "electron";
|
|
9
|
+
//#region src/shared/zenbu-bg.ts
|
|
10
|
+
const META_RE = /<meta\s+name=["']zenbu-bg["']\s+content=["']([^"']+)["']/i;
|
|
11
|
+
/**
|
|
12
|
+
* Read the `<meta name="zenbu-bg" content="#xxx">` value from an HTML
|
|
13
|
+
* file. Returns the configured value, or `fallback` when the file is
|
|
14
|
+
* missing, unreadable, or has no `zenbu-bg` meta tag.
|
|
15
|
+
*
|
|
16
|
+
* This convention exists because Electron paints a `BaseWindow`'s
|
|
17
|
+
* `backgroundColor` for the brief window between the window appearing
|
|
18
|
+
* on screen and the `WebContentsView`'s first frame reaching the
|
|
19
|
+
* compositor — and similarly the view itself flashes its
|
|
20
|
+
* `setBackgroundColor` before any HTML renders. Reading the meta from
|
|
21
|
+
* the same HTML the renderer will paint keeps both colors in sync with
|
|
22
|
+
* whatever theme the renderer is committing to (`#111` for a dark app,
|
|
23
|
+
* `#F4F4F4` for a light one), so the user never sees a single white
|
|
24
|
+
* frame on window open.
|
|
25
|
+
*/
|
|
26
|
+
function readZenbuBgColor(htmlPath, fallback = "#F4F4F4") {
|
|
27
|
+
try {
|
|
28
|
+
const match = fs.readFileSync(htmlPath, "utf8").match(META_RE);
|
|
29
|
+
if (match?.[1]) return match[1];
|
|
30
|
+
} catch {}
|
|
31
|
+
return fallback;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the renderer entrypoint's `zenbu-bg` color via the global
|
|
35
|
+
* plugin registry. Convenience wrapper: services creating windows
|
|
36
|
+
* post-boot don't need to plumb the entrypoint path through —
|
|
37
|
+
* `getAppEntrypoint()` returns whatever was published by the loader's
|
|
38
|
+
* registry-setup module at import time.
|
|
39
|
+
*
|
|
40
|
+
* Returns `fallback` if the registry hasn't been populated yet (i.e.
|
|
41
|
+
* pre-loader code paths) or if the entrypoint dir has no `index.html`
|
|
42
|
+
* with a `zenbu-bg` meta tag.
|
|
43
|
+
*/
|
|
44
|
+
function entrypointBgColor(fallback = "#F4F4F4") {
|
|
45
|
+
const entrypoint = getAppEntrypoint();
|
|
46
|
+
if (!entrypoint) return fallback;
|
|
47
|
+
return readZenbuBgColor(path.join(entrypoint, "index.html"), fallback);
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/services/base-window.ts
|
|
51
|
+
var base_window_exports = /* @__PURE__ */ __exportAll({
|
|
52
|
+
BaseWindowService: () => BaseWindowService,
|
|
53
|
+
MAIN_WINDOW_ID: () => MAIN_WINDOW_ID
|
|
54
|
+
});
|
|
55
|
+
const log = createLogger("base-window");
|
|
56
|
+
const MAIN_WINDOW_ID = "main";
|
|
57
|
+
var BaseWindowService = class extends Service.create({
|
|
58
|
+
key: "base-window",
|
|
59
|
+
deps: { db: DbService }
|
|
60
|
+
}) {
|
|
61
|
+
windows = /* @__PURE__ */ new Map();
|
|
62
|
+
get bootWindows() {
|
|
63
|
+
return globalThis.__zenbu_boot_windows__ ?? [];
|
|
64
|
+
}
|
|
65
|
+
set bootWindows(v) {
|
|
66
|
+
globalThis.__zenbu_boot_windows__ = v;
|
|
67
|
+
}
|
|
68
|
+
getZenWidth() {
|
|
69
|
+
const flag = process.argv.find((a) => a.startsWith("--zen-width="));
|
|
70
|
+
if (!flag) return void 0;
|
|
71
|
+
const n = parseInt(flag.slice(12), 10);
|
|
72
|
+
return isNaN(n) ? void 0 : n;
|
|
73
|
+
}
|
|
74
|
+
getWindowId(win) {
|
|
75
|
+
for (const [id, w] of this.windows) if (w === win) return id;
|
|
76
|
+
}
|
|
77
|
+
createWindow(opts) {
|
|
78
|
+
const windowId = opts?.windowId ?? nanoid();
|
|
79
|
+
const zenWidth = this.getZenWidth();
|
|
80
|
+
const win = new BaseWindow({
|
|
81
|
+
width: opts?.width ?? zenWidth ?? 1100,
|
|
82
|
+
height: opts?.height ?? 750,
|
|
83
|
+
...opts?.x != null && opts?.y != null ? {
|
|
84
|
+
x: opts.x,
|
|
85
|
+
y: opts.y
|
|
86
|
+
} : {},
|
|
87
|
+
show: opts?.show ?? true,
|
|
88
|
+
titleBarStyle: "hidden",
|
|
89
|
+
trafficLightPosition: {
|
|
90
|
+
x: 14,
|
|
91
|
+
y: 10
|
|
92
|
+
},
|
|
93
|
+
backgroundColor: entrypointBgColor()
|
|
94
|
+
});
|
|
95
|
+
this.windows.set(windowId, win);
|
|
96
|
+
win.on("closed", () => this.windows.delete(windowId));
|
|
97
|
+
return {
|
|
98
|
+
win,
|
|
99
|
+
windowId
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
evaluate() {
|
|
103
|
+
if (this.windows.size === 0) if (this.bootWindows.length > 0) {
|
|
104
|
+
for (const boot of this.bootWindows) {
|
|
105
|
+
this.windows.set(boot.windowId, boot.win);
|
|
106
|
+
boot.win.on("closed", () => this.windows.delete(boot.windowId));
|
|
107
|
+
}
|
|
108
|
+
this.bootWindows = [];
|
|
109
|
+
} else {
|
|
110
|
+
const prefs = this.ctx.db.client.readRoot().plugin.core.windowPrefs;
|
|
111
|
+
this.createWindow({
|
|
112
|
+
windowId: MAIN_WINDOW_ID,
|
|
113
|
+
...prefs[MAIN_WINDOW_ID]?.lastKnownBounds
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
this.setup("window-cleanup", () => {
|
|
117
|
+
return () => {
|
|
118
|
+
const snapshot = [...this.windows.entries()].map(([windowId, win]) => ({
|
|
119
|
+
windowId,
|
|
120
|
+
bounds: win.getBounds()
|
|
121
|
+
}));
|
|
122
|
+
this.ctx.db.client.update((root) => {
|
|
123
|
+
const next = { ...root.plugin.core.windowPrefs };
|
|
124
|
+
for (const { windowId, bounds } of snapshot) next[windowId] = {
|
|
125
|
+
...next[windowId],
|
|
126
|
+
lastKnownBounds: bounds
|
|
127
|
+
};
|
|
128
|
+
root.plugin.core.windowPrefs = next;
|
|
129
|
+
});
|
|
130
|
+
for (const win of this.windows.values()) {
|
|
131
|
+
win.__zenbu_on_close = null;
|
|
132
|
+
win.__zenbu_on_closed = null;
|
|
133
|
+
win.close();
|
|
134
|
+
}
|
|
135
|
+
this.windows.clear();
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
log.verbose(`ready (${this.windows.size} windows)`);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
runtime.register(BaseWindowService, import.meta);
|
|
142
|
+
//#endregion
|
|
143
|
+
export { entrypointBgColor as i, MAIN_WINDOW_ID as n, base_window_exports as r, BaseWindowService as t };
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
//#region src/cli/lib/build-config.d.ts
|
|
2
|
+
interface BuildContext {
|
|
3
|
+
/** Absolute path to the source root (`build.source` resolved). */
|
|
4
|
+
sourceDir: string;
|
|
5
|
+
/** Absolute path to the staging output dir (`build.out` resolved). */
|
|
6
|
+
outDir: string;
|
|
7
|
+
/** Git HEAD of the source repo at build time, or `"uncommitted"`. */
|
|
8
|
+
sourceSha: string;
|
|
9
|
+
/** Absolute path to the `zenbu.config.ts` driving this build. */
|
|
10
|
+
configPath: string;
|
|
11
|
+
}
|
|
12
|
+
interface EmitContext extends BuildContext {
|
|
13
|
+
/**
|
|
14
|
+
* Write an additional file into `outDir`. Relative paths only — anything
|
|
15
|
+
* absolute or escaping `outDir` (via `..`) throws. Emitted files
|
|
16
|
+
* participate in the build's `.sha` content hash.
|
|
17
|
+
*/
|
|
18
|
+
emit(relPath: string, contents: string | Uint8Array): void;
|
|
19
|
+
}
|
|
20
|
+
interface BuildPlugin {
|
|
21
|
+
name: string;
|
|
22
|
+
/**
|
|
23
|
+
* Called once per text file after `include`/`ignore` filtering, before
|
|
24
|
+
* the file is written to `outDir`. Plugins run in declaration order;
|
|
25
|
+
* each plugin's return value (if any) feeds the next.
|
|
26
|
+
*
|
|
27
|
+
* Return:
|
|
28
|
+
* - a string → use it as the new contents
|
|
29
|
+
* - `null` → drop the file (short-circuits remaining plugins)
|
|
30
|
+
* - `void` → leave contents unchanged
|
|
31
|
+
*
|
|
32
|
+
* Binary files (anything outside the small text-extension allow-list)
|
|
33
|
+
* are not visible to `transform` — they're copied byte-for-byte.
|
|
34
|
+
*/
|
|
35
|
+
transform?(file: {
|
|
36
|
+
path: string;
|
|
37
|
+
contents: string;
|
|
38
|
+
}, ctx: BuildContext): string | null | void | Promise<string | null | void>;
|
|
39
|
+
/**
|
|
40
|
+
* Called once after every source file is written. Use `ctx.emit(...)` to
|
|
41
|
+
* write additional files (build manifests, generated artifacts, etc.)
|
|
42
|
+
* into `outDir`. Plugins run in declaration order.
|
|
43
|
+
*/
|
|
44
|
+
done?(ctx: EmitContext): void | Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
interface MirrorConfig {
|
|
47
|
+
target: string;
|
|
48
|
+
branch?: string;
|
|
49
|
+
}
|
|
50
|
+
interface BundleConfig {
|
|
51
|
+
extraResources?: string[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Which package manager the produced .app should bundle and use to install
|
|
55
|
+
* the cloned source's dependencies on first launch.
|
|
56
|
+
*
|
|
57
|
+
* Exactly one PM per .app. The `version` is honored verbatim across all four
|
|
58
|
+
* variants: it drives the download URL at build time and is recorded in
|
|
59
|
+
* `app-config.json` so the launcher knows which CI-mode codepath to take.
|
|
60
|
+
*
|
|
61
|
+
* `bun` is not special at the API layer — but internally the runtime bun and
|
|
62
|
+
* the PM bun are collapsed into a single binary at the user's chosen
|
|
63
|
+
* version (so picking bun yields one binary in the bundle, not two).
|
|
64
|
+
*/
|
|
65
|
+
type PackageManagerSpec = {
|
|
66
|
+
type: "pnpm";
|
|
67
|
+
version: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: "npm";
|
|
70
|
+
version: string;
|
|
71
|
+
} | {
|
|
72
|
+
type: "yarn";
|
|
73
|
+
version: string;
|
|
74
|
+
} | {
|
|
75
|
+
type: "bun";
|
|
76
|
+
version: string;
|
|
77
|
+
};
|
|
78
|
+
interface BuildConfig {
|
|
79
|
+
/**
|
|
80
|
+
* The .app's "host version" — the developer's product version for the
|
|
81
|
+
* Electron+core+toolchain bundle as a whole. Required, semver-shaped
|
|
82
|
+
* (e.g. `"0.0.6"`).
|
|
83
|
+
*
|
|
84
|
+
* This is NOT derived from `package.json#version` (which lives in the
|
|
85
|
+
* source tree and gets overwritten by `git pull`) or from
|
|
86
|
+
* `@zenbujs/core`'s installed version (a transitive dep, not the
|
|
87
|
+
* developer's product). Bump it whenever you ship a new .app build.
|
|
88
|
+
*
|
|
89
|
+
* `zen build:electron` writes this verbatim into `<bundle>/host.json`.
|
|
90
|
+
* The launcher and `UpdaterService` read that file to drive
|
|
91
|
+
* compatibility checks against each commit's `package.json#zenbu.host`
|
|
92
|
+
* range — the predicate is
|
|
93
|
+
* `semver.satisfies(hostVersion, commitPackageJson.zenbu.host)`.
|
|
94
|
+
*/
|
|
95
|
+
hostVersion: string;
|
|
96
|
+
source?: string;
|
|
97
|
+
out?: string;
|
|
98
|
+
include: string[];
|
|
99
|
+
ignore?: string[];
|
|
100
|
+
plugins?: BuildPlugin[];
|
|
101
|
+
mirror?: MirrorConfig;
|
|
102
|
+
bundle?: BundleConfig;
|
|
103
|
+
packageManager?: PackageManagerSpec;
|
|
104
|
+
}
|
|
105
|
+
declare function defineBuildConfig(config: BuildConfig): BuildConfig;
|
|
106
|
+
type ResolvedBuildConfig = Required<Omit<BuildConfig, "mirror" | "bundle">> & {
|
|
107
|
+
mirror?: MirrorConfig;
|
|
108
|
+
bundle?: BundleConfig;
|
|
109
|
+
packageManager: PackageManagerSpec;
|
|
110
|
+
};
|
|
111
|
+
declare function resolveBuildConfig(config: BuildConfig): ResolvedBuildConfig;
|
|
112
|
+
/**
|
|
113
|
+
* A Zenbu plugin's main-process surface. Plugins are pure main-process: they
|
|
114
|
+
* register services + side-effect modules (schema, preload, events). UI is
|
|
115
|
+
* handled exclusively at the outer config level via `uiEntrypoint` — there
|
|
116
|
+
* is exactly one HTML entrypoint per app.
|
|
117
|
+
*
|
|
118
|
+
* `services` is an array of glob patterns (relative to the plugin file's
|
|
119
|
+
* directory). `schema` / `preload` / `events` are optional file paths.
|
|
120
|
+
*/
|
|
121
|
+
interface Plugin {
|
|
122
|
+
name: string;
|
|
123
|
+
services: string[];
|
|
124
|
+
schema?: string;
|
|
125
|
+
migrations?: string;
|
|
126
|
+
preload?: string;
|
|
127
|
+
events?: string;
|
|
128
|
+
/**
|
|
129
|
+
* Plugin-author-defined SVG icons keyed by view type. Read by
|
|
130
|
+
* `view-registry` to decorate registered views. Optional.
|
|
131
|
+
*/
|
|
132
|
+
icons?: Record<string, string>;
|
|
133
|
+
}
|
|
134
|
+
declare function definePlugin(plugin: Plugin): Plugin;
|
|
135
|
+
/**
|
|
136
|
+
* A plugin manifest after path resolution. Every relative path has been made
|
|
137
|
+
* absolute against `dir` (the directory the manifest came from). Glob-form
|
|
138
|
+
* service entries stay as patterns (still anchored to `dir`).
|
|
139
|
+
*
|
|
140
|
+
* The runtime stores these in `runtime.getPlugins()`; consumers like
|
|
141
|
+
* `services/db.ts`, `services/advice-config.ts`, `vite-plugins.ts` read from
|
|
142
|
+
* there instead of walking the filesystem looking for `zenbu.plugin.json`.
|
|
143
|
+
*/
|
|
144
|
+
interface ResolvedPlugin {
|
|
145
|
+
name: string;
|
|
146
|
+
/** Absolute directory the plugin was loaded from. */
|
|
147
|
+
dir: string;
|
|
148
|
+
/** Glob patterns for service files. Anchored to `dir`. */
|
|
149
|
+
services: string[];
|
|
150
|
+
/** Absolute path to `schema.ts` (or undefined). */
|
|
151
|
+
schemaPath?: string;
|
|
152
|
+
/** Absolute path to migrations dir/file (or undefined). */
|
|
153
|
+
migrationsPath?: string;
|
|
154
|
+
/** Absolute path to `preload.ts` (or undefined). */
|
|
155
|
+
preloadPath?: string;
|
|
156
|
+
/** Absolute path to `events.ts` (or undefined). */
|
|
157
|
+
eventsPath?: string;
|
|
158
|
+
/** Plugin-author-defined SVG icons. */
|
|
159
|
+
icons?: Record<string, string>;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The whole-app `zenbu.config.ts` shape. Authored by user code; imported
|
|
163
|
+
* (and re-imported on every change) by the loader and CLI.
|
|
164
|
+
*
|
|
165
|
+
* - `db`: directory the kyju database lives in (relative to the config file).
|
|
166
|
+
* - `uiEntrypoint`: path to the boot-window's HTML file. Exactly one — there
|
|
167
|
+
* is no per-plugin UI (today's per-plugin `uiEntrypoint` was effectively a
|
|
168
|
+
* bug that the new shape disallows at the type level).
|
|
169
|
+
* - `plugins`: flat list. Each entry is either an inline `definePlugin({...})`
|
|
170
|
+
* or a path to a `zenbu.plugin.ts` whose default export is a plugin. The
|
|
171
|
+
* "host plugin" is just `plugins[0]` by convention; nothing structurally
|
|
172
|
+
* distinguishes it.
|
|
173
|
+
* - `build`: shipped as `defineBuildConfig({...})`. Drives `zen build:source`
|
|
174
|
+
* and `zen build:electron`.
|
|
175
|
+
*/
|
|
176
|
+
interface Config {
|
|
177
|
+
db: string;
|
|
178
|
+
uiEntrypoint: string;
|
|
179
|
+
plugins: Array<Plugin | string>;
|
|
180
|
+
build?: BuildConfig;
|
|
181
|
+
}
|
|
182
|
+
declare function defineConfig(config: Config): Config;
|
|
183
|
+
interface ResolvedConfig {
|
|
184
|
+
/** Absolute path to the `zenbu.config.ts` this came from. */
|
|
185
|
+
configPath: string;
|
|
186
|
+
/** Directory containing `zenbu.config.ts`. */
|
|
187
|
+
projectDir: string;
|
|
188
|
+
/** Absolute path to the database directory. */
|
|
189
|
+
dbPath: string;
|
|
190
|
+
/**
|
|
191
|
+
* Absolute path to the renderer's entrypoint directory. Vite's `root`
|
|
192
|
+
* resolves here; `index.html` inside it is served through Vite.
|
|
193
|
+
*/
|
|
194
|
+
uiEntrypointPath: string;
|
|
195
|
+
/**
|
|
196
|
+
* Absolute path to `splash.html` inside the entrypoint directory. Loaded
|
|
197
|
+
* raw (no Vite) into a transient BrowserView during the brief window
|
|
198
|
+
* between Electron `whenReady` and the renderer's first paint.
|
|
199
|
+
*/
|
|
200
|
+
splashPath: string;
|
|
201
|
+
/**
|
|
202
|
+
* Absolute path to `installing.html` inside the entrypoint directory, if
|
|
203
|
+
* the user provided one. Optional. Production launcher loads this raw
|
|
204
|
+
* during clone + first install (before the user's source even exists in
|
|
205
|
+
* the apps-dir). Receives IPC progress events via the framework's
|
|
206
|
+
* built-in `installing-preload.cjs`. Not used in dev mode — `pnpm dev`
|
|
207
|
+
* doesn't clone or install.
|
|
208
|
+
*/
|
|
209
|
+
installingPath?: string;
|
|
210
|
+
plugins: ResolvedPlugin[];
|
|
211
|
+
/** Resolved build config; defaults filled in even when user omits. */
|
|
212
|
+
build: ResolvedBuildConfig;
|
|
213
|
+
}
|
|
214
|
+
//#endregion
|
|
215
|
+
export { Config as a, PackageManagerSpec as c, ResolvedConfig as d, ResolvedPlugin as f, resolveBuildConfig as g, definePlugin as h, BundleConfig as i, Plugin as l, defineConfig as m, BuildContext as n, EmitContext as o, defineBuildConfig as p, BuildPlugin as r, MirrorConfig as s, BuildConfig as t, ResolvedBuildConfig as u };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/cli/lib/build-config.ts
|
|
2
|
+
/**
|
|
3
|
+
* Soft default when the user omits `build.packageManager` entirely. Existing
|
|
4
|
+
* apps scaffolded before this field existed pick this up. The version
|
|
5
|
+
* tracks whatever pnpm we'd otherwise have hardcoded in the toolchain.
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_PACKAGE_MANAGER = {
|
|
8
|
+
type: "pnpm",
|
|
9
|
+
version: "10.33.0"
|
|
10
|
+
};
|
|
11
|
+
function defineBuildConfig(config) {
|
|
12
|
+
return config;
|
|
13
|
+
}
|
|
14
|
+
const SEMVER_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
15
|
+
function validateHostVersion(value) {
|
|
16
|
+
if (typeof value !== "string" || value.trim().length === 0) throw new Error("zenbu build.hostVersion: required `string` (e.g. \"0.0.6\"). Set it on `defineBuildConfig({ hostVersion: \"...\" })`.");
|
|
17
|
+
const trimmed = value.trim();
|
|
18
|
+
if (!SEMVER_RE.test(trimmed)) throw new Error(`zenbu build.hostVersion: "${value}" is not a valid semver string (expected MAJOR.MINOR.PATCH with optional prerelease / build metadata).`);
|
|
19
|
+
return trimmed;
|
|
20
|
+
}
|
|
21
|
+
function validatePackageManager(spec) {
|
|
22
|
+
const allowed = [
|
|
23
|
+
"pnpm",
|
|
24
|
+
"npm",
|
|
25
|
+
"yarn",
|
|
26
|
+
"bun"
|
|
27
|
+
];
|
|
28
|
+
if (!allowed.includes(spec.type)) throw new Error(`zenbu build.packageManager: unknown type "${spec.type}". Expected one of: ${allowed.join(", ")}.`);
|
|
29
|
+
if (typeof spec.version !== "string" || spec.version.trim().length === 0) throw new Error(`zenbu build.packageManager.${spec.type}: \`version\` is required and must be a non-empty string.`);
|
|
30
|
+
return spec;
|
|
31
|
+
}
|
|
32
|
+
function resolveBuildConfig(config) {
|
|
33
|
+
const packageManager = validatePackageManager(config.packageManager ?? DEFAULT_PACKAGE_MANAGER);
|
|
34
|
+
return {
|
|
35
|
+
hostVersion: validateHostVersion(config.hostVersion),
|
|
36
|
+
source: config.source ?? ".",
|
|
37
|
+
out: config.out ?? ".zenbu/build/source",
|
|
38
|
+
include: config.include,
|
|
39
|
+
ignore: config.ignore ?? [],
|
|
40
|
+
plugins: config.plugins ?? [],
|
|
41
|
+
mirror: config.mirror,
|
|
42
|
+
bundle: config.bundle,
|
|
43
|
+
packageManager
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function definePlugin(plugin) {
|
|
47
|
+
return plugin;
|
|
48
|
+
}
|
|
49
|
+
function defineConfig(config) {
|
|
50
|
+
return config;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { resolveBuildConfig as i, defineConfig as n, definePlugin as r, defineBuildConfig as t };
|