@zenbujs/core 0.0.9 → 0.0.12
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-BiYhyeTz.d.mts +41 -0
- package/dist/advice.d.mts +2 -36
- package/dist/advice.mjs +2 -2
- package/dist/{base-window-BxBZ2md_.mjs → base-window-4P-fVvC_.mjs} +37 -26
- package/dist/{build-config-Dzg2frpk.d.mts → build-config-GF0XzR_Y.d.mts} +42 -18
- package/dist/{build-config-pWdmLnrk.mjs → build-config-HMMqpXI1.mjs} +0 -8
- package/dist/{build-electron-Dsbb1EMl.mjs → build-electron-Di_FE62r.mjs} +10 -6
- package/dist/{build-source-d1J3shV8.mjs → build-source-BIaWpaxE.mjs} +2 -2
- package/dist/cli/bin.mjs +7 -7
- package/dist/cli/build.d.mts +1 -1
- package/dist/cli/build.mjs +1 -1
- package/dist/cli/resolve-config.mjs +6 -1
- package/dist/{cli-kL6mPgBE.mjs → cli-5jFDJWM4.mjs} +4 -4
- package/dist/config.d.mts +3 -3
- package/dist/config.mjs +2 -2
- package/dist/{db-Bc292RYo.mjs → db-MkOccvBS.mjs} +2 -2
- package/dist/db.d.mts +3 -2
- package/dist/db.mjs +2 -10
- package/dist/{dev-B2emj0HZ.mjs → dev-BSDyzO4j.mjs} +3 -9
- package/dist/env-bootstrap.d.mts +1 -1
- package/dist/events.d.mts +0 -9
- package/dist/{host-version-BIrF8tX7.mjs → host-version-Cog_odmD.mjs} +4 -3
- package/dist/{index-CVF768Xs.d.mts → index-C0mXKol5.d.mts} +188 -143
- package/dist/{index-DeDxePAa.d.mts → index-FaexRVl_.d.mts} +13 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +2 -2
- package/dist/launcher.mjs +64 -6
- package/dist/link-Bt3LB_NW.mjs +586 -0
- package/dist/{load-config-C4Oe2qZO.mjs → load-config-C2XloBaQ.mjs} +68 -5
- package/dist/node-loader.mjs +1 -1
- package/dist/{publish-source-Dq2c0iOw.mjs → publish-source-v93eB9kA.mjs} +6 -2
- package/dist/react.d.mts +6 -6
- package/dist/react.mjs +4 -4
- package/dist/registry-generated.d.mts +19 -14
- package/dist/registry-saQDMUhT.d.mts +13 -0
- package/dist/registry.d.mts +1 -1
- package/dist/{reloader-B22UiNA2.mjs → reloader-CFzxYa67.mjs} +3 -3
- package/dist/{renderer-host-DD16MXhI.mjs → renderer-host-Cw38dSDe.mjs} +35 -24
- package/dist/{rpc-C4_NQmpT.mjs → rpc-Dg9zwZ33.mjs} +4 -4
- package/dist/rpc.d.mts +1 -1
- package/dist/rpc.mjs +1 -1
- package/dist/runtime-DYUONc3S.mjs +861 -0
- package/dist/{runtime-BQWntcOb.d.mts → runtime-fnPDZFYM.d.mts} +100 -3
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.mjs +2 -578
- package/dist/{schema-CjrMVk36.d.mts → schema-brYpUjYO.d.mts} +13 -25
- package/dist/schema.d.mts +2 -2
- package/dist/schema.mjs +9 -2
- package/dist/{server-CZLMF8Dj.mjs → server-BJ2ZC2z2.mjs} +2 -2
- package/dist/services/default.d.mts +1 -5
- package/dist/services/default.mjs +12 -16
- package/dist/services/index.d.mts +1 -1
- package/dist/services/index.mjs +7 -7
- package/dist/setup-gate.d.mts +1 -1
- package/dist/setup-gate.mjs +20 -12
- package/dist/{transport-F2hv_OEm.mjs → transport-Bqlv9pmJ.mjs} +1 -1
- package/dist/updater-Bs1Jtem6.mjs +480 -0
- package/dist/{vite-plugins-tt6KAtyE.mjs → vite-plugins-Df-cfldF.mjs} +2 -49
- package/dist/vite.d.mts +0 -5
- package/dist/vite.mjs +1 -1
- package/dist/{window-YFKvAM0l.mjs → window-DgB70qeZ.mjs} +113 -22
- package/dist/{write-DgIRjo23.mjs → write-7IfKa_nq.mjs} +1 -1
- package/dist/zenbu-bg-parse-CIyPkJOY.mjs +46 -0
- package/package.json +19 -18
- package/LICENSE +0 -11
- package/dist/advice-config-DXSIo0sg.mjs +0 -154
- package/dist/link-glX89NV5.mjs +0 -673
- package/dist/registry-CMp8FYgS.d.mts +0 -47
- package/dist/updater-BtB_Ki1r.mjs +0 -1011
- /package/dist/{config-BK78JDRI.mjs → config-DfciRzDu.mjs} +0 -0
- /package/dist/{env-bootstrap-rTs8KR3-.d.mts → env-bootstrap-UBug-4Kw.d.mts} +0 -0
- /package/dist/{index-C-ALz_SH.d.mts → index-CSMHYi3u.d.mts} +0 -0
- /package/dist/{index-ClXLQ1fw.d.mts → index-DJOHDG5e.d.mts} +0 -0
- /package/dist/{log-6rzaCV0I.mjs → log-BkRqDwwB.mjs} +0 -0
- /package/dist/{mirror-sync-pYU6f3-c.mjs → mirror-sync-snqh9kEp.mjs} +0 -0
- /package/dist/{monorepo-Dct-kkbQ.mjs → monorepo-CBzK3l2i.mjs} +0 -0
- /package/dist/{node-BhfLKYCi.mjs → node-BuHlEsE4.mjs} +0 -0
- /package/dist/{schema-Ca7SxXgS.mjs → schema-C6k0SroY.mjs} +0 -0
- /package/dist/{setup-gate-BQq0QgZH.d.mts → setup-gate-DkysEZQO.d.mts} +0 -0
- /package/dist/{src-Cven45mq.mjs → src-BpZAt9zL.mjs} +0 -0
- /package/dist/{trace-BaVg0rnY.mjs → trace-BVcQSD59.mjs} +0 -0
- /package/dist/{transform-BzrwkEdf.mjs → transform-czrcGnVV.mjs} +0 -0
package/dist/vite.d.mts
CHANGED
|
@@ -51,11 +51,6 @@ declare function advicePreludePlugin(): Plugin;
|
|
|
51
51
|
*/
|
|
52
52
|
declare function zenbuAdviceTransform(): Plugin;
|
|
53
53
|
/**
|
|
54
|
-
* Returns the framework Vite plugins in the canonical order. Auto-injected
|
|
55
|
-
* by `ReloaderService` for every renderer; exported for advanced users who
|
|
56
|
-
* want to compose them into a custom Vite stack.
|
|
57
|
-
*
|
|
58
|
-
* Order matters:
|
|
59
54
|
* 1. `zenbuFrameworkResolve` — `enforce: "pre"`, runs first so it gets
|
|
60
55
|
* `react` / `@zenbujs/core/*` *before* Vite's default resolver walks
|
|
61
56
|
* up and finds plugin-local copies.
|
package/dist/vite.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as zenbuVitePlugins, i as zenbuFrameworkResolve, n as resolveAdviceRuntime, r as zenbuAdviceTransform, t as advicePreludePlugin } from "./vite-plugins-
|
|
1
|
+
import { a as zenbuVitePlugins, i as zenbuFrameworkResolve, n as resolveAdviceRuntime, r as zenbuAdviceTransform, t as advicePreludePlugin } from "./vite-plugins-Df-cfldF.mjs";
|
|
2
2
|
export { advicePreludePlugin, resolveAdviceRuntime, zenbuAdviceTransform, zenbuFrameworkResolve, zenbuVitePlugins };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as __exportAll } from "./chunk-DsiFFCwN.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { t as createLogger } from "./log-
|
|
4
|
-
import { r as ViewRegistryService, s as HttpService, t as RendererHostService } from "./renderer-host-
|
|
5
|
-
import { i as entrypointBgColor, t as BaseWindowService } from "./base-window-
|
|
2
|
+
import { f as runtime, n as Service } from "./runtime-DYUONc3S.mjs";
|
|
3
|
+
import { t as createLogger } from "./log-BkRqDwwB.mjs";
|
|
4
|
+
import { r as ViewRegistryService, s as HttpService, t as RendererHostService } from "./renderer-host-Cw38dSDe.mjs";
|
|
5
|
+
import { i as entrypointBgColor, t as BaseWindowService } from "./base-window-4P-fVvC_.mjs";
|
|
6
6
|
import { URLSearchParams } from "node:url";
|
|
7
|
-
import { WebContentsView, app, clipboard, dialog, shell } from "electron";
|
|
7
|
+
import { Menu, WebContentsView, app, clipboard, dialog, shell } from "electron";
|
|
8
8
|
import electronContextMenu from "electron-context-menu";
|
|
9
9
|
//#region src/services/window.ts
|
|
10
10
|
var window_exports = /* @__PURE__ */ __exportAll({ WindowService: () => WindowService });
|
|
@@ -48,7 +48,7 @@ var WindowService = class extends Service.create({
|
|
|
48
48
|
this.setup("activate-reopens-entrypoint", () => {
|
|
49
49
|
const onActivate = () => {
|
|
50
50
|
if (this.ctx.baseWindow.windows.size > 0) return;
|
|
51
|
-
this.openView({ type: "
|
|
51
|
+
this.openView({ type: "entrypoint" }).catch((err) => {
|
|
52
52
|
log.error("activate-reopens-entrypoint: openView failed:", err);
|
|
53
53
|
});
|
|
54
54
|
};
|
|
@@ -57,13 +57,76 @@ var WindowService = class extends Service.create({
|
|
|
57
57
|
app.removeListener("activate", onActivate);
|
|
58
58
|
};
|
|
59
59
|
});
|
|
60
|
+
this.setup("app-menu", () => this.installAppMenu());
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Walk every mounted WebContentsView and return the one currently
|
|
64
|
+
* focused, so application-menu actions (reload, devtools) hit the view
|
|
65
|
+
* the user is actually looking at instead of the wrong window.
|
|
66
|
+
*/
|
|
67
|
+
focusedMountedWebContents() {
|
|
68
|
+
for (const mounted of this.mounted.values()) {
|
|
69
|
+
const wc = mounted.view.webContents;
|
|
70
|
+
if (!wc.isDestroyed() && wc.isFocused()) return wc;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
installAppMenu() {
|
|
75
|
+
const isMac = process.platform === "darwin";
|
|
76
|
+
const focusedWc = () => this.focusedMountedWebContents();
|
|
77
|
+
const viewSubmenu = [
|
|
78
|
+
{
|
|
79
|
+
label: "Reload",
|
|
80
|
+
accelerator: "CmdOrCtrl+R",
|
|
81
|
+
click: () => focusedWc()?.reload()
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
label: "Force Reload",
|
|
85
|
+
accelerator: "Shift+CmdOrCtrl+R",
|
|
86
|
+
click: () => focusedWc()?.reloadIgnoringCache()
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
label: "Toggle Developer Tools",
|
|
90
|
+
accelerator: isMac ? "Alt+Cmd+I" : "Ctrl+Shift+I",
|
|
91
|
+
click: () => {
|
|
92
|
+
const wc = focusedWc();
|
|
93
|
+
if (!wc) return;
|
|
94
|
+
if (wc.isDevToolsOpened()) wc.closeDevTools();
|
|
95
|
+
else wc.openDevTools({ mode: "detach" });
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{ type: "separator" },
|
|
99
|
+
{ role: "resetZoom" },
|
|
100
|
+
{ role: "zoomIn" },
|
|
101
|
+
{ role: "zoomOut" },
|
|
102
|
+
{ type: "separator" },
|
|
103
|
+
{ role: "togglefullscreen" }
|
|
104
|
+
];
|
|
105
|
+
const template = [
|
|
106
|
+
...isMac ? [{ role: "appMenu" }] : [],
|
|
107
|
+
{ role: "fileMenu" },
|
|
108
|
+
{ role: "editMenu" },
|
|
109
|
+
{
|
|
110
|
+
label: "View",
|
|
111
|
+
submenu: viewSubmenu
|
|
112
|
+
},
|
|
113
|
+
{ role: "windowMenu" }
|
|
114
|
+
];
|
|
115
|
+
const previous = Menu.getApplicationMenu();
|
|
116
|
+
Menu.setApplicationMenu(Menu.buildFromTemplate(template));
|
|
117
|
+
return () => {
|
|
118
|
+
Menu.setApplicationMenu(previous);
|
|
119
|
+
};
|
|
60
120
|
}
|
|
61
121
|
async openView(args) {
|
|
62
122
|
const entry = this.ctx.viewRegistry.get(args.type);
|
|
63
123
|
if (!entry) throw new Error(`No registered view for type "${args.type}"`);
|
|
64
124
|
const windowId = args.windowId ?? "main";
|
|
65
125
|
let win = this.ctx.baseWindow.windows.get(windowId);
|
|
66
|
-
if (!win) win = this.ctx.baseWindow.createWindow({
|
|
126
|
+
if (!win) win = this.ctx.baseWindow.createWindow({
|
|
127
|
+
windowId,
|
|
128
|
+
baseWindow: args.baseWindow
|
|
129
|
+
}).win;
|
|
67
130
|
const existing = this.mounted.get(windowId);
|
|
68
131
|
if (existing) {
|
|
69
132
|
try {
|
|
@@ -75,25 +138,53 @@ var WindowService = class extends Service.create({
|
|
|
75
138
|
existing.view.webContents.close();
|
|
76
139
|
this.mounted.delete(windowId);
|
|
77
140
|
}
|
|
78
|
-
const view = new WebContentsView({
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
141
|
+
const view = new WebContentsView({
|
|
142
|
+
...args.webContentsView,
|
|
143
|
+
webPreferences: {
|
|
144
|
+
nodeIntegration: false,
|
|
145
|
+
contextIsolation: true,
|
|
146
|
+
sandbox: true,
|
|
147
|
+
...args.webContentsView?.webPreferences
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
view.setBackgroundColor(args.backgroundColor ?? entrypointBgColor());
|
|
85
151
|
win.contentView.addChildView(view);
|
|
86
|
-
const disposeContextMenu = electronContextMenu({
|
|
87
|
-
window: view,
|
|
152
|
+
const disposeContextMenu = args.contextMenu === false ? () => {} : electronContextMenu({
|
|
88
153
|
showInspectElement: true,
|
|
89
154
|
showSearchWithGoogle: false,
|
|
90
|
-
showSelectAll: true
|
|
155
|
+
showSelectAll: true,
|
|
156
|
+
prepend: (_defaults, _params, _win) => [
|
|
157
|
+
{
|
|
158
|
+
label: "Reload window",
|
|
159
|
+
click: () => {
|
|
160
|
+
try {
|
|
161
|
+
view.webContents.reload();
|
|
162
|
+
} catch (err) {
|
|
163
|
+
log.error("context menu: reload window failed:", err);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
label: "Reload main process",
|
|
169
|
+
click: () => {
|
|
170
|
+
runtime.reloadAll().catch((err) => {
|
|
171
|
+
log.error("context menu: reload main process failed:", err);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
{ type: "separator" }
|
|
176
|
+
],
|
|
177
|
+
...args.contextMenu,
|
|
178
|
+
window: view
|
|
91
179
|
});
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
180
|
+
if (args.devtoolsShortcut !== false) {
|
|
181
|
+
const handleInput = (_event, input) => {
|
|
182
|
+
if (input.key !== "F12") return;
|
|
183
|
+
if (view.webContents.isDevToolsOpened()) view.webContents.closeDevTools();
|
|
184
|
+
else view.webContents.openDevTools({ mode: "detach" });
|
|
185
|
+
};
|
|
186
|
+
view.webContents.on("before-input-event", handleInput);
|
|
187
|
+
}
|
|
97
188
|
const layout = () => {
|
|
98
189
|
const { width, height } = win.getContentBounds();
|
|
99
190
|
view.setBounds({
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//#region src/shared/zenbu-bg-parse.ts
|
|
2
|
+
const META_TAG_RE = /<meta\b([^>]*?)\/?>/gi;
|
|
3
|
+
const ATTR_RE = /([\w-]+)\s*=\s*["']([^"']+)["']/g;
|
|
4
|
+
/**
|
|
5
|
+
* Parse all `<meta name="zenbu-bg">` tags from `html`. Mirrors the W3C
|
|
6
|
+
* `<meta name="theme-color">` pattern: multiple tags carry a `media`
|
|
7
|
+
* attribute (typically `(prefers-color-scheme: light|dark)`), and an
|
|
8
|
+
* unmediated tag acts as the fallback.
|
|
9
|
+
*
|
|
10
|
+
* <meta name="zenbu-bg" content="#fafafa" media="(prefers-color-scheme: light)">
|
|
11
|
+
* <meta name="zenbu-bg" content="#09090b" media="(prefers-color-scheme: dark)">
|
|
12
|
+
* <meta name="zenbu-bg" content="#27272a"> <!-- default -->
|
|
13
|
+
*/
|
|
14
|
+
function parseZenbuBgEntries(html) {
|
|
15
|
+
const out = [];
|
|
16
|
+
for (const tag of html.matchAll(META_TAG_RE)) {
|
|
17
|
+
const body = tag[1] ?? "";
|
|
18
|
+
const attrs = {};
|
|
19
|
+
for (const a of body.matchAll(ATTR_RE)) attrs[a[1].toLowerCase()] = a[2];
|
|
20
|
+
if (attrs.name === "zenbu-bg" && attrs.content) out.push({
|
|
21
|
+
color: attrs.content,
|
|
22
|
+
media: attrs.media ?? null
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Pick the right entry given the current dark-mode preference. Search
|
|
29
|
+
* order:
|
|
30
|
+
* 1. First entry whose `media` matches `(prefers-color-scheme: <dark|light>)`.
|
|
31
|
+
* 2. First entry without a `media` attribute (the unconditional default).
|
|
32
|
+
* 3. The first entry, regardless of `media`.
|
|
33
|
+
*
|
|
34
|
+
* Returns `null` only when `entries` is empty.
|
|
35
|
+
*/
|
|
36
|
+
function pickZenbuBgEntry(entries, dark) {
|
|
37
|
+
for (const e of entries) {
|
|
38
|
+
if (!e.media) continue;
|
|
39
|
+
if (dark && /prefers-color-scheme:\s*dark/i.test(e.media)) return e.color;
|
|
40
|
+
if (!dark && /prefers-color-scheme:\s*light/i.test(e.media)) return e.color;
|
|
41
|
+
}
|
|
42
|
+
for (const e of entries) if (!e.media) return e.color;
|
|
43
|
+
return entries[0]?.color ?? null;
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { pickZenbuBgEntry as n, parseZenbuBgEntries as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenbujs/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -89,9 +89,19 @@
|
|
|
89
89
|
"migrations",
|
|
90
90
|
"package.json"
|
|
91
91
|
],
|
|
92
|
+
"scripts": {
|
|
93
|
+
"build": "node --max-old-space-size=8192 ./node_modules/tsdown/dist/run.mjs",
|
|
94
|
+
"prebuild": "pnpm link:types",
|
|
95
|
+
"dev": "tsdown --watch",
|
|
96
|
+
"link:types": "tsx ./src/cli/bin.ts link --types-config ./zenbu-types.config.json --out ./src/registry-generated.ts --augment-out ./types/zenbu-register.ts",
|
|
97
|
+
"db:generate": "node ./dist/cli/bin.mjs db generate --schema src/schema.ts --migrations ./migrations",
|
|
98
|
+
"test": "vitest run",
|
|
99
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
100
|
+
},
|
|
92
101
|
"peerDependencies": {
|
|
93
102
|
"electron": "^42.0.0",
|
|
94
|
-
"react": ">=18"
|
|
103
|
+
"react": ">=18",
|
|
104
|
+
"zod": "^4"
|
|
95
105
|
},
|
|
96
106
|
"peerDependenciesMeta": {
|
|
97
107
|
"react": {
|
|
@@ -101,6 +111,7 @@
|
|
|
101
111
|
"dependencies": {
|
|
102
112
|
"@parcel/watcher": "^2.5.0",
|
|
103
113
|
"@vitejs/plugin-react": "^5.0.0",
|
|
114
|
+
"@zenbujs/hmr": "workspace:*",
|
|
104
115
|
"dugite": "^3.2.1",
|
|
105
116
|
"effect": "^3.21.1",
|
|
106
117
|
"electron-context-menu": "^4.1.2",
|
|
@@ -109,30 +120,20 @@
|
|
|
109
120
|
"semver": "^7.8.0",
|
|
110
121
|
"tsx": "^4.21.0",
|
|
111
122
|
"vite": "^6.0.0",
|
|
112
|
-
"ws": "^8.18.0"
|
|
113
|
-
"zod": "^4.3.6",
|
|
114
|
-
"@zenbujs/hmr": "0.0.2"
|
|
123
|
+
"ws": "^8.18.0"
|
|
115
124
|
},
|
|
116
125
|
"devDependencies": {
|
|
117
126
|
"@types/node": "^22.0.0",
|
|
118
127
|
"@types/react": "^19.0.0",
|
|
119
128
|
"@types/semver": "^7.7.1",
|
|
120
129
|
"@types/ws": "^8.18.0",
|
|
130
|
+
"@zenbu/advice": "workspace:*",
|
|
131
|
+
"@zenbu/kyju": "workspace:*",
|
|
132
|
+
"@zenbu/zenrpc": "workspace:*",
|
|
121
133
|
"electron": "^42.0.0",
|
|
122
134
|
"tsdown": "^0.21.10",
|
|
123
135
|
"typescript": "^5.4.5",
|
|
124
136
|
"vitest": "^3.2.4",
|
|
125
|
-
"
|
|
126
|
-
"@zenbu/kyju": "0.0.0",
|
|
127
|
-
"@zenbu/zenrpc": "0.0.0"
|
|
128
|
-
},
|
|
129
|
-
"scripts": {
|
|
130
|
-
"build": "node --max-old-space-size=8192 ./node_modules/tsdown/dist/run.mjs",
|
|
131
|
-
"prebuild": "pnpm link:types",
|
|
132
|
-
"dev": "tsdown --watch",
|
|
133
|
-
"link:types": "tsx ./src/cli/bin.ts link --types-config ./zenbu-types.config.json --out ./src/registry-generated.ts --augment-out ./types/zenbu-register.ts",
|
|
134
|
-
"db:generate": "node ./dist/cli/bin.mjs db generate --schema src/schema.ts --migrations ./migrations",
|
|
135
|
-
"test": "vitest run",
|
|
136
|
-
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
137
|
+
"zod": "^4"
|
|
137
138
|
}
|
|
138
|
-
}
|
|
139
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
All Rights Reserved
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Zenbu Labs Inc.
|
|
4
|
-
|
|
5
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
6
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
7
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
8
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
9
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
10
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
11
|
-
THE SOFTWARE.
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import { n as __exportAll } from "./chunk-DsiFFCwN.mjs";
|
|
2
|
-
import { getPlugins, runtime } from "./runtime.mjs";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
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
|
-
});
|
|
15
|
-
/**
|
|
16
|
-
* Find the plugin whose `dir` contains the file at `metaUrl`. The runtime
|
|
17
|
-
* plugin registry (populated by the loader-emitted barrel) is the source
|
|
18
|
-
* of truth; this no longer walks the filesystem looking for
|
|
19
|
-
* `zenbu.plugin.json`. Returns the plugin's dir, used as the anchor for
|
|
20
|
-
* `registerContentScript` / `registerAdvice` relative-path resolution.
|
|
21
|
-
*
|
|
22
|
-
* Throws if no plugin matches, because a silent fallback to `process.cwd()`
|
|
23
|
-
* would attach a content script to a nonsensical location and you'd debug
|
|
24
|
-
* it by staring at empty iframes.
|
|
25
|
-
*/
|
|
26
|
-
function findPluginRoot(metaUrl) {
|
|
27
|
-
const file = fileURLToPath(metaUrl);
|
|
28
|
-
let bestMatch = null;
|
|
29
|
-
for (const plugin of getPlugins()) {
|
|
30
|
-
const rel = path.relative(plugin.dir, file);
|
|
31
|
-
if (rel.startsWith("..") || path.isAbsolute(rel)) continue;
|
|
32
|
-
const depth = plugin.dir.split(path.sep).length;
|
|
33
|
-
if (!bestMatch || depth > bestMatch.depth) bestMatch = {
|
|
34
|
-
dir: plugin.dir,
|
|
35
|
-
depth
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
if (bestMatch) return bestMatch.dir;
|
|
39
|
-
throw new Error(`Could not find owning plugin for ${metaUrl}. Pass an absolute path, or call this from a file inside a Zenbu plugin.`);
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Accepts either an absolute path (used as-is) or a path relative to the
|
|
43
|
-
* caller's plugin root. The `meta` argument is `import.meta` from the calling
|
|
44
|
-
* module; without it we can't compute the plugin root, so relative paths
|
|
45
|
-
* require it.
|
|
46
|
-
*/
|
|
47
|
-
function resolvePluginPath(modulePath, meta) {
|
|
48
|
-
if (path.isAbsolute(modulePath)) return modulePath;
|
|
49
|
-
if (!meta?.url) throw new Error(`registerContentScript/registerAdvice: relative path "${modulePath}" requires import.meta as the second argument so we can find the plugin root.`);
|
|
50
|
-
return path.resolve(findPluginRoot(meta.url), modulePath);
|
|
51
|
-
}
|
|
52
|
-
const RESOLVED_PREFIX = "\0@advice-prelude/";
|
|
53
|
-
const APP_RENDERER_RELOADER_ID = "app";
|
|
54
|
-
const adviceEntries = /* @__PURE__ */ new Map();
|
|
55
|
-
const contentScripts = /* @__PURE__ */ new Map();
|
|
56
|
-
function invalidatePrelude(type) {
|
|
57
|
-
try {
|
|
58
|
-
const reloader = runtime.getSlot("reloader")?.instance;
|
|
59
|
-
if (!reloader) return;
|
|
60
|
-
const coreEntry = reloader.get(APP_RENDERER_RELOADER_ID);
|
|
61
|
-
if (!coreEntry?.viteServer) return;
|
|
62
|
-
const graph = coreEntry.viteServer.moduleGraph;
|
|
63
|
-
const invalidateMatching = (test) => {
|
|
64
|
-
const ids = [];
|
|
65
|
-
for (const id of graph.idToModuleMap.keys()) {
|
|
66
|
-
if (typeof id !== "string") continue;
|
|
67
|
-
if (test(id)) ids.push(id);
|
|
68
|
-
}
|
|
69
|
-
for (const id of ids) {
|
|
70
|
-
const mod = graph.getModuleById(id);
|
|
71
|
-
if (mod) graph.invalidateModule(mod);
|
|
72
|
-
}
|
|
73
|
-
};
|
|
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
|
-
}
|
|
79
|
-
} catch {}
|
|
80
|
-
}
|
|
81
|
-
function emitReload(type) {
|
|
82
|
-
invalidatePrelude(type);
|
|
83
|
-
try {
|
|
84
|
-
const rpc = runtime.getSlot("rpc")?.instance;
|
|
85
|
-
if (!rpc) return;
|
|
86
|
-
rpc.emit.advice.reload({ type });
|
|
87
|
-
} catch {}
|
|
88
|
-
}
|
|
89
|
-
function registerAdvice(type, entry, meta) {
|
|
90
|
-
const resolvedEntry = {
|
|
91
|
-
...entry,
|
|
92
|
-
modulePath: resolvePluginPath(entry.modulePath, meta)
|
|
93
|
-
};
|
|
94
|
-
const list = adviceEntries.get(type) ?? [];
|
|
95
|
-
list.push(resolvedEntry);
|
|
96
|
-
adviceEntries.set(type, list);
|
|
97
|
-
emitReload(type);
|
|
98
|
-
return () => {
|
|
99
|
-
const current = adviceEntries.get(type);
|
|
100
|
-
if (!current) return;
|
|
101
|
-
const idx = current.indexOf(resolvedEntry);
|
|
102
|
-
if (idx >= 0) current.splice(idx, 1);
|
|
103
|
-
if (current.length === 0) adviceEntries.delete(type);
|
|
104
|
-
emitReload(type);
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
function getAdvice(type) {
|
|
108
|
-
return adviceEntries.get(type) ?? [];
|
|
109
|
-
}
|
|
110
|
-
function getAllAdviceTypes() {
|
|
111
|
-
return [...adviceEntries.keys()];
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Register a content script for the given view type. `modulePath` is normally
|
|
115
|
-
* a path relative to the plugin root (the folder with `zenbu.plugin.json`);
|
|
116
|
-
* pass `import.meta` so we can resolve it. Absolute paths are accepted as
|
|
117
|
-
* an escape hatch.
|
|
118
|
-
*
|
|
119
|
-
* this.setup("inject", () =>
|
|
120
|
-
* registerContentScript("app", "src/content/clock.tsx", import.meta),
|
|
121
|
-
* )
|
|
122
|
-
*/
|
|
123
|
-
function registerContentScript(type, modulePath, meta) {
|
|
124
|
-
const entry = { path: resolvePluginPath(modulePath, meta) };
|
|
125
|
-
const list = contentScripts.get(type) ?? [];
|
|
126
|
-
list.push(entry);
|
|
127
|
-
contentScripts.set(type, list);
|
|
128
|
-
emitReload(type === "*" ? "*" : type);
|
|
129
|
-
return () => {
|
|
130
|
-
const current = contentScripts.get(type);
|
|
131
|
-
if (!current) return;
|
|
132
|
-
const idx = current.indexOf(entry);
|
|
133
|
-
if (idx >= 0) current.splice(idx, 1);
|
|
134
|
-
if (current.length === 0) contentScripts.delete(type);
|
|
135
|
-
emitReload(type === "*" ? "*" : type);
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
function getContentScripts(type) {
|
|
139
|
-
const scoped = (contentScripts.get(type) ?? []).map((e) => e.path);
|
|
140
|
-
return [...type !== "*" ? (contentScripts.get("*") ?? []).map((e) => e.path) : [], ...scoped];
|
|
141
|
-
}
|
|
142
|
-
function getAllContentScriptPaths() {
|
|
143
|
-
const paths = [];
|
|
144
|
-
for (const list of contentScripts.values()) for (const entry of list) paths.push(entry.path);
|
|
145
|
-
return paths;
|
|
146
|
-
}
|
|
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];
|
|
152
|
-
}
|
|
153
|
-
//#endregion
|
|
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 };
|