@zenbujs/core 0.0.5 → 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-QYB2qEd_.mjs → advice-config-DXSIo0sg.mjs} +40 -39
- package/dist/advice.d.mts +8 -8
- package/dist/advice.mjs +2 -2
- package/dist/{base-window-BbFRRhKP.mjs → base-window-BxBZ2md_.mjs} +51 -7
- package/dist/{transforms-CuTODvDx.d.mts → build-config-Dzg2frpk.d.mts} +98 -28
- package/dist/build-config-pWdmLnrk.mjs +53 -0
- package/dist/{build-electron-CNJ0dLND.mjs → build-electron-Dsbb1EMl.mjs} +308 -120
- package/dist/{build-source-C2puqEVr.mjs → build-source-d1J3shV8.mjs} +62 -27
- 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 +1 -1
- package/dist/{cli-C3R1LBMY.mjs → cli-kL6mPgBE.mjs} +2 -2
- package/dist/config.d.mts +3 -3
- package/dist/config.mjs +2 -3
- package/dist/{db-xjvahRFJ.mjs → db-Bc292RYo.mjs} +2 -2
- package/dist/db.d.mts +1 -1
- package/dist/dev-B2emj0HZ.mjs +301 -0
- package/dist/env-bootstrap.d.mts +1 -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 +2 -2
- package/dist/installing-preload.cjs +60 -0
- package/dist/launcher.mjs +2615 -122
- package/dist/{link-c0_aLWQ3.mjs → link-glX89NV5.mjs} +215 -89
- package/dist/{load-config-xMf2wxH8.mjs → load-config-C4Oe2qZO.mjs} +5 -1
- package/dist/loaders/zenbu.mjs +102 -0
- package/dist/node-loader.mjs +1 -1
- package/dist/{publish-source-Dill72NS.mjs → publish-source-Dq2c0iOw.mjs} +2 -2
- package/dist/react.d.mts +55 -6
- package/dist/react.mjs +116 -5
- 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-DzEO8kJr.mjs → reloader-B22UiNA2.mjs} +2 -4
- package/dist/{renderer-host-Cau9JK0v.mjs → renderer-host-DD16MXhI.mjs} +152 -43
- package/dist/{rpc-JfGv-Wuw.mjs → rpc-C4_NQmpT.mjs} +5 -4
- package/dist/{runtime-pCeVzj--.d.mts → runtime-BQWntcOb.d.mts} +85 -48
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.mjs +139 -83
- package/dist/{schema-Dl85YjXW.d.mts → schema-CjrMVk36.d.mts} +3 -3
- package/dist/schema.d.mts +1 -1
- package/dist/schema.mjs +1 -1
- package/dist/{server-y3PPbh3l.mjs → server-CZLMF8Dj.mjs} +1 -3
- package/dist/services/default.d.mts +3 -3
- package/dist/services/default.mjs +14 -13
- package/dist/services/index.d.mts +2 -280
- package/dist/services/index.mjs +8 -7
- package/dist/setup-gate.d.mts +1 -1
- package/dist/setup-gate.mjs +117 -24
- package/dist/{transform-CmFYPmt8.mjs → transform-BzrwkEdf.mjs} +22 -916
- package/dist/updater-DCkz9M1c.mjs +1008 -0
- package/dist/{vite-plugins-Do7liKi_.mjs → vite-plugins-tt6KAtyE.mjs} +26 -25
- package/dist/vite.d.mts +3 -3
- package/dist/vite.mjs +1 -1
- package/dist/{window-o2NGUsIb.mjs → window-YFKvAM0l.mjs} +30 -16
- package/package.json +15 -2
- package/dist/build-config-C3a-o3_B.mjs +0 -23
- package/dist/dev-Dazhu66l.mjs +0 -85
- package/dist/registry-eX6e2oql.d.mts +0 -61
- package/dist/transforms-htxfTwsY.mjs +0 -47
- /package/dist/{config-DXRCDUxG.mjs → config-BK78JDRI.mjs} +0 -0
- /package/dist/{env-bootstrap-DW2hVhSO.d.mts → env-bootstrap-rTs8KR3-.d.mts} +0 -0
- /package/dist/{index-M_lSNBrq.d.mts → index-DeDxePAa.d.mts} +0 -0
- /package/dist/{mirror-sync-PDzxhf1w.mjs → mirror-sync-pYU6f3-c.mjs} +0 -0
- /package/dist/{monorepo-3avKJwzJ.mjs → monorepo-Dct-kkbQ.mjs} +0 -0
- /package/dist/{node-_8xShqxr.mjs → node-BhfLKYCi.mjs} +0 -0
- /package/dist/{setup-gate-Dcy8gGPJ.d.mts → setup-gate-BQq0QgZH.d.mts} +0 -0
|
@@ -5,9 +5,9 @@ import { fileURLToPath } from "node:url";
|
|
|
5
5
|
//#region src/services/advice-config.ts
|
|
6
6
|
var advice_config_exports = /* @__PURE__ */ __exportAll({
|
|
7
7
|
getAdvice: () => getAdvice,
|
|
8
|
-
|
|
8
|
+
getAllAdviceTypes: () => getAllAdviceTypes,
|
|
9
9
|
getAllContentScriptPaths: () => getAllContentScriptPaths,
|
|
10
|
-
|
|
10
|
+
getAllTypes: () => getAllTypes,
|
|
11
11
|
getContentScripts: () => getContentScripts,
|
|
12
12
|
registerAdvice: () => registerAdvice,
|
|
13
13
|
registerContentScript: () => registerContentScript
|
|
@@ -53,64 +53,65 @@ const RESOLVED_PREFIX = "\0@advice-prelude/";
|
|
|
53
53
|
const APP_RENDERER_RELOADER_ID = "app";
|
|
54
54
|
const adviceEntries = /* @__PURE__ */ new Map();
|
|
55
55
|
const contentScripts = /* @__PURE__ */ new Map();
|
|
56
|
-
function invalidatePrelude(
|
|
56
|
+
function invalidatePrelude(type) {
|
|
57
57
|
try {
|
|
58
58
|
const reloader = runtime.getSlot("reloader")?.instance;
|
|
59
59
|
if (!reloader) return;
|
|
60
60
|
const coreEntry = reloader.get(APP_RENDERER_RELOADER_ID);
|
|
61
61
|
if (!coreEntry?.viteServer) return;
|
|
62
62
|
const graph = coreEntry.viteServer.moduleGraph;
|
|
63
|
-
const
|
|
64
|
-
const prefix = RESOLVED_PREFIX + s;
|
|
63
|
+
const invalidateMatching = (test) => {
|
|
65
64
|
const ids = [];
|
|
66
65
|
for (const id of graph.idToModuleMap.keys()) {
|
|
67
66
|
if (typeof id !== "string") continue;
|
|
68
|
-
if (id
|
|
67
|
+
if (test(id)) ids.push(id);
|
|
69
68
|
}
|
|
70
69
|
for (const id of ids) {
|
|
71
70
|
const mod = graph.getModuleById(id);
|
|
72
71
|
if (mod) graph.invalidateModule(mod);
|
|
73
72
|
}
|
|
74
73
|
};
|
|
75
|
-
if (
|
|
76
|
-
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
|
+
}
|
|
77
79
|
} catch {}
|
|
78
80
|
}
|
|
79
|
-
function emitReload(
|
|
80
|
-
invalidatePrelude(
|
|
81
|
+
function emitReload(type) {
|
|
82
|
+
invalidatePrelude(type);
|
|
81
83
|
try {
|
|
82
84
|
const rpc = runtime.getSlot("rpc")?.instance;
|
|
83
85
|
if (!rpc) return;
|
|
84
|
-
|
|
85
|
-
else rpc.emit.advice.reload({ scope });
|
|
86
|
+
rpc.emit.advice.reload({ type });
|
|
86
87
|
} catch {}
|
|
87
88
|
}
|
|
88
|
-
function registerAdvice(
|
|
89
|
+
function registerAdvice(type, entry, meta) {
|
|
89
90
|
const resolvedEntry = {
|
|
90
91
|
...entry,
|
|
91
92
|
modulePath: resolvePluginPath(entry.modulePath, meta)
|
|
92
93
|
};
|
|
93
|
-
const list = adviceEntries.get(
|
|
94
|
+
const list = adviceEntries.get(type) ?? [];
|
|
94
95
|
list.push(resolvedEntry);
|
|
95
|
-
adviceEntries.set(
|
|
96
|
-
emitReload(
|
|
96
|
+
adviceEntries.set(type, list);
|
|
97
|
+
emitReload(type);
|
|
97
98
|
return () => {
|
|
98
|
-
const current = adviceEntries.get(
|
|
99
|
+
const current = adviceEntries.get(type);
|
|
99
100
|
if (!current) return;
|
|
100
101
|
const idx = current.indexOf(resolvedEntry);
|
|
101
102
|
if (idx >= 0) current.splice(idx, 1);
|
|
102
|
-
if (current.length === 0) adviceEntries.delete(
|
|
103
|
-
emitReload(
|
|
103
|
+
if (current.length === 0) adviceEntries.delete(type);
|
|
104
|
+
emitReload(type);
|
|
104
105
|
};
|
|
105
106
|
}
|
|
106
|
-
function getAdvice(
|
|
107
|
-
return adviceEntries.get(
|
|
107
|
+
function getAdvice(type) {
|
|
108
|
+
return adviceEntries.get(type) ?? [];
|
|
108
109
|
}
|
|
109
|
-
function
|
|
110
|
+
function getAllAdviceTypes() {
|
|
110
111
|
return [...adviceEntries.keys()];
|
|
111
112
|
}
|
|
112
113
|
/**
|
|
113
|
-
* Register a content script for the given
|
|
114
|
+
* Register a content script for the given view type. `modulePath` is normally
|
|
114
115
|
* a path relative to the plugin root (the folder with `zenbu.plugin.json`);
|
|
115
116
|
* pass `import.meta` so we can resolve it. Absolute paths are accepted as
|
|
116
117
|
* an escape hatch.
|
|
@@ -119,35 +120,35 @@ function getAllAdviceScopes() {
|
|
|
119
120
|
* registerContentScript("app", "src/content/clock.tsx", import.meta),
|
|
120
121
|
* )
|
|
121
122
|
*/
|
|
122
|
-
function registerContentScript(
|
|
123
|
+
function registerContentScript(type, modulePath, meta) {
|
|
123
124
|
const entry = { path: resolvePluginPath(modulePath, meta) };
|
|
124
|
-
const list = contentScripts.get(
|
|
125
|
+
const list = contentScripts.get(type) ?? [];
|
|
125
126
|
list.push(entry);
|
|
126
|
-
contentScripts.set(
|
|
127
|
-
emitReload(
|
|
127
|
+
contentScripts.set(type, list);
|
|
128
|
+
emitReload(type === "*" ? "*" : type);
|
|
128
129
|
return () => {
|
|
129
|
-
const current = contentScripts.get(
|
|
130
|
+
const current = contentScripts.get(type);
|
|
130
131
|
if (!current) return;
|
|
131
132
|
const idx = current.indexOf(entry);
|
|
132
133
|
if (idx >= 0) current.splice(idx, 1);
|
|
133
|
-
if (current.length === 0) contentScripts.delete(
|
|
134
|
-
emitReload(
|
|
134
|
+
if (current.length === 0) contentScripts.delete(type);
|
|
135
|
+
emitReload(type === "*" ? "*" : type);
|
|
135
136
|
};
|
|
136
137
|
}
|
|
137
|
-
function getContentScripts(
|
|
138
|
-
const scoped = (contentScripts.get(
|
|
139
|
-
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];
|
|
140
141
|
}
|
|
141
142
|
function getAllContentScriptPaths() {
|
|
142
143
|
const paths = [];
|
|
143
144
|
for (const list of contentScripts.values()) for (const entry of list) paths.push(entry.path);
|
|
144
145
|
return paths;
|
|
145
146
|
}
|
|
146
|
-
function
|
|
147
|
-
const
|
|
148
|
-
for (const k of adviceEntries.keys())
|
|
149
|
-
for (const k of contentScripts.keys()) if (k !== "*")
|
|
150
|
-
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];
|
|
151
152
|
}
|
|
152
153
|
//#endregion
|
|
153
|
-
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 };
|
|
@@ -1,9 +1,52 @@
|
|
|
1
1
|
import { n as __exportAll } from "./chunk-DsiFFCwN.mjs";
|
|
2
|
-
import { Service, runtime } from "./runtime.mjs";
|
|
2
|
+
import { Service, getAppEntrypoint, runtime } from "./runtime.mjs";
|
|
3
3
|
import { t as createLogger } from "./log-6rzaCV0I.mjs";
|
|
4
|
-
import { a as DbService } from "./renderer-host-
|
|
4
|
+
import { a as DbService } from "./renderer-host-DD16MXhI.mjs";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
5
7
|
import { nanoid } from "nanoid";
|
|
6
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
|
|
7
50
|
//#region src/services/base-window.ts
|
|
8
51
|
var base_window_exports = /* @__PURE__ */ __exportAll({
|
|
9
52
|
BaseWindowService: () => BaseWindowService,
|
|
@@ -11,9 +54,10 @@ var base_window_exports = /* @__PURE__ */ __exportAll({
|
|
|
11
54
|
});
|
|
12
55
|
const log = createLogger("base-window");
|
|
13
56
|
const MAIN_WINDOW_ID = "main";
|
|
14
|
-
var BaseWindowService = class extends Service
|
|
15
|
-
|
|
16
|
-
|
|
57
|
+
var BaseWindowService = class extends Service.create({
|
|
58
|
+
key: "base-window",
|
|
59
|
+
deps: { db: DbService }
|
|
60
|
+
}) {
|
|
17
61
|
windows = /* @__PURE__ */ new Map();
|
|
18
62
|
get bootWindows() {
|
|
19
63
|
return globalThis.__zenbu_boot_windows__ ?? [];
|
|
@@ -46,7 +90,7 @@ var BaseWindowService = class extends Service {
|
|
|
46
90
|
x: 14,
|
|
47
91
|
y: 10
|
|
48
92
|
},
|
|
49
|
-
backgroundColor:
|
|
93
|
+
backgroundColor: entrypointBgColor()
|
|
50
94
|
});
|
|
51
95
|
this.windows.set(windowId, win);
|
|
52
96
|
win.on("closed", () => this.windows.delete(windowId));
|
|
@@ -96,4 +140,4 @@ var BaseWindowService = class extends Service {
|
|
|
96
140
|
};
|
|
97
141
|
runtime.register(BaseWindowService, import.meta);
|
|
98
142
|
//#endregion
|
|
99
|
-
export { MAIN_WINDOW_ID as n, base_window_exports as r, BaseWindowService as t };
|
|
143
|
+
export { entrypointBgColor as i, MAIN_WINDOW_ID as n, base_window_exports as r, BaseWindowService as t };
|
|
@@ -1,13 +1,48 @@
|
|
|
1
1
|
//#region src/cli/lib/build-config.d.ts
|
|
2
|
-
interface
|
|
3
|
-
path
|
|
4
|
-
|
|
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;
|
|
5
19
|
}
|
|
6
|
-
interface
|
|
7
|
-
|
|
8
|
-
|
|
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>;
|
|
9
45
|
}
|
|
10
|
-
type Transform = (file: TransformInput) => TransformOutput | null | undefined | void;
|
|
11
46
|
interface MirrorConfig {
|
|
12
47
|
target: string;
|
|
13
48
|
branch?: string;
|
|
@@ -15,19 +50,63 @@ interface MirrorConfig {
|
|
|
15
50
|
interface BundleConfig {
|
|
16
51
|
extraResources?: string[];
|
|
17
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
|
+
};
|
|
18
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;
|
|
19
96
|
source?: string;
|
|
20
97
|
out?: string;
|
|
21
98
|
include: string[];
|
|
22
99
|
ignore?: string[];
|
|
23
|
-
|
|
100
|
+
plugins?: BuildPlugin[];
|
|
24
101
|
mirror?: MirrorConfig;
|
|
25
102
|
bundle?: BundleConfig;
|
|
103
|
+
packageManager?: PackageManagerSpec;
|
|
26
104
|
}
|
|
27
105
|
declare function defineBuildConfig(config: BuildConfig): BuildConfig;
|
|
28
106
|
type ResolvedBuildConfig = Required<Omit<BuildConfig, "mirror" | "bundle">> & {
|
|
29
107
|
mirror?: MirrorConfig;
|
|
30
108
|
bundle?: BundleConfig;
|
|
109
|
+
packageManager: PackageManagerSpec;
|
|
31
110
|
};
|
|
32
111
|
declare function resolveBuildConfig(config: BuildConfig): ResolvedBuildConfig;
|
|
33
112
|
/**
|
|
@@ -47,7 +126,7 @@ interface Plugin {
|
|
|
47
126
|
preload?: string;
|
|
48
127
|
events?: string;
|
|
49
128
|
/**
|
|
50
|
-
* Plugin-author-defined SVG icons keyed by view
|
|
129
|
+
* Plugin-author-defined SVG icons keyed by view type. Read by
|
|
51
130
|
* `view-registry` to decorate registered views. Optional.
|
|
52
131
|
*/
|
|
53
132
|
icons?: Record<string, string>;
|
|
@@ -119,27 +198,18 @@ interface ResolvedConfig {
|
|
|
119
198
|
* between Electron `whenReady` and the renderer's first paint.
|
|
120
199
|
*/
|
|
121
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;
|
|
122
210
|
plugins: ResolvedPlugin[];
|
|
123
211
|
/** Resolved build config; defaults filled in even when user omits. */
|
|
124
212
|
build: ResolvedBuildConfig;
|
|
125
213
|
}
|
|
126
214
|
//#endregion
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Marker-based feature-flag stripping. Removes lines between
|
|
130
|
-
* // @zenbu:strip-if FLAG (strip when FLAG is truthy)
|
|
131
|
-
* // @zenbu:strip-if !FLAG (strip when FLAG is falsy)
|
|
132
|
-
* ...
|
|
133
|
-
* // @zenbu:end
|
|
134
|
-
*
|
|
135
|
-
* Pure string/line ops — no AST, no compiler dep.
|
|
136
|
-
*/
|
|
137
|
-
declare function stripIfDisabled(flags: Record<string, boolean>): Transform;
|
|
138
|
-
/**
|
|
139
|
-
* Drop files whose path matches the given pattern (relative path from the
|
|
140
|
-
* source root, posix slashes). Also covered by `ignore` globs in the config;
|
|
141
|
-
* use this when a regex is more convenient than a glob.
|
|
142
|
-
*/
|
|
143
|
-
declare function dropFiles(pattern: RegExp | ((path: string) => boolean)): Transform;
|
|
144
|
-
//#endregion
|
|
145
|
-
export { resolveBuildConfig as _, Config as a, ResolvedBuildConfig as c, Transform as d, TransformInput as f, definePlugin as g, defineConfig as h, BundleConfig as i, ResolvedConfig as l, defineBuildConfig as m, stripIfDisabled as n, MirrorConfig as o, TransformOutput as p, BuildConfig as r, Plugin as s, dropFiles as t, ResolvedPlugin as u };
|
|
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 };
|