@zenbujs/core 0.0.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.
- package/LICENSE +11 -0
- package/dist/advice-config-CjgkEf2E.mjs +135 -0
- package/dist/advice-config-Cy133IQP.mjs +2 -0
- package/dist/advice-runtime.d.mts +35 -0
- package/dist/advice-runtime.mjs +131 -0
- package/dist/advice.d.mts +36 -0
- package/dist/advice.mjs +2 -0
- package/dist/base-window-BUt8pwbw.mjs +94 -0
- package/dist/base-window-DEIAk618.mjs +2 -0
- package/dist/build-config-pbv0w4oN.mjs +17 -0
- package/dist/build-electron-B4Gd0Gi4.mjs +516 -0
- package/dist/build-source-_q1n1zTV.mjs +162 -0
- package/dist/chunk-Dm34NbLt.mjs +6 -0
- package/dist/cli/bin.d.mts +1 -0
- package/dist/cli/bin.mjs +88 -0
- package/dist/cli/build.d.mts +53 -0
- package/dist/cli/build.mjs +48 -0
- package/dist/cli-BLbQQIVB.mjs +8054 -0
- package/dist/config-CdVrW85P.mjs +59 -0
- package/dist/config-LK73dJmO.mjs +2 -0
- package/dist/db-ByKPbnP6.mjs +2 -0
- package/dist/db-DhuAJrye.mjs +531 -0
- package/dist/db.d.mts +16 -0
- package/dist/db.mjs +16 -0
- package/dist/dev-BuqklM0k.mjs +85 -0
- package/dist/env-bootstrap-BtVME-CU.d.mts +16 -0
- package/dist/env-bootstrap-rj7I-59x.mjs +53 -0
- package/dist/env-bootstrap.d.mts +2 -0
- package/dist/env-bootstrap.mjs +2 -0
- package/dist/http-IBcLzbYu.mjs +2 -0
- package/dist/index-Bhlbyrn7.d.mts +63 -0
- package/dist/index-CPZ5d6Hl.d.mts +442 -0
- package/dist/index-FtE8MXJ_.d.mts +1 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +5 -0
- package/dist/launcher.mjs +173 -0
- package/dist/link-6roQ7Cn6.mjs +580 -0
- package/dist/loaders/zenbu.d.mts +22 -0
- package/dist/loaders/zenbu.mjs +267 -0
- package/dist/log-CyKv8hQg.mjs +20 -0
- package/dist/mirror-sync-CodOnwkD.mjs +332 -0
- package/dist/monorepo-CmGPHsVm.mjs +119 -0
- package/dist/node-D4M19_mV.mjs +5 -0
- package/dist/node-loader.d.mts +17 -0
- package/dist/node-loader.mjs +33 -0
- package/dist/pause-DvAUNmKn.mjs +52 -0
- package/dist/publish-source-BVgB62Zj.mjs +131 -0
- package/dist/react.d.mts +76 -0
- package/dist/react.mjs +291 -0
- package/dist/registry-Dh_e7HU1.d.mts +61 -0
- package/dist/registry.d.mts +2 -0
- package/dist/registry.mjs +1 -0
- package/dist/reloader-BCkLjDhS.mjs +2 -0
- package/dist/reloader-lLAJ3lqg.mjs +164 -0
- package/dist/renderer-host-Bg8QdeeH.mjs +1508 -0
- package/dist/renderer-host-DpvBPTHJ.mjs +2 -0
- package/dist/rpc-BwwQK6hD.mjs +71 -0
- package/dist/rpc-CqitnyR4.mjs +2 -0
- package/dist/rpc.d.mts +2 -0
- package/dist/rpc.mjs +2 -0
- package/dist/runtime-CjqDr8Yf.d.mts +109 -0
- package/dist/runtime-DUFKDIe4.mjs +409 -0
- package/dist/runtime.d.mts +2 -0
- package/dist/runtime.mjs +2 -0
- package/dist/schema-CIg4GzHQ.mjs +100 -0
- package/dist/schema-DMoSkwUx.d.mts +62 -0
- package/dist/schema-dGK6qkfR.mjs +28 -0
- package/dist/schema.d.mts +2 -0
- package/dist/schema.mjs +2 -0
- package/dist/server-BXwZEQ-n.mjs +66 -0
- package/dist/server-DjrZUbbu.mjs +2 -0
- package/dist/services/default.d.mts +11 -0
- package/dist/services/default.mjs +22 -0
- package/dist/services/index.d.mts +276 -0
- package/dist/services/index.mjs +7 -0
- package/dist/setup-gate-BeD6WS6d.mjs +110 -0
- package/dist/setup-gate-BqOzm7zp.d.mts +4 -0
- package/dist/setup-gate.d.mts +2 -0
- package/dist/setup-gate.mjs +2 -0
- package/dist/src-pELM4_iH.mjs +376 -0
- package/dist/trace-DCB7qFzT.mjs +10 -0
- package/dist/transform-DJH3vN4b.mjs +84041 -0
- package/dist/transport-BMSzG2-F.mjs +1045 -0
- package/dist/view-registry-BualWgAf.mjs +2 -0
- package/dist/vite-plugins-Bh3SCOw-.mjs +331 -0
- package/dist/vite.d.mts +68 -0
- package/dist/vite.mjs +2 -0
- package/dist/window-CM2a9Kyc.mjs +2 -0
- package/dist/window-CmmpCVX6.mjs +156 -0
- package/dist/write-9dRFczGJ.mjs +1248 -0
- package/migrations/0000_migration.ts +34 -0
- package/migrations/meta/0000_snapshot.json +18 -0
- package/migrations/meta/_journal.json +10 -0
- package/package.json +124 -0
package/dist/react.mjs
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { i as dbStringify, r as dbParse, t as connectReplica } from "./transport-BMSzG2-F.mjs";
|
|
2
|
+
import { t as connectRpc } from "./src-pELM4_iH.mjs";
|
|
3
|
+
import { createContext, createElement, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
4
|
+
//#region ../kyju/src/v2/react/index.ts
|
|
5
|
+
function createKyjuReact() {
|
|
6
|
+
const KyjuContext = createContext(null);
|
|
7
|
+
function KyjuProvider({ client, replica, children }) {
|
|
8
|
+
const value = useMemo(() => ({
|
|
9
|
+
client,
|
|
10
|
+
replica
|
|
11
|
+
}), [client, replica]);
|
|
12
|
+
return createElement(KyjuContext.Provider, { value }, children);
|
|
13
|
+
}
|
|
14
|
+
function useKyjuContext() {
|
|
15
|
+
const ctx = useContext(KyjuContext);
|
|
16
|
+
if (!ctx) throw new Error("useDb/useCollection must be used inside KyjuProvider");
|
|
17
|
+
return ctx;
|
|
18
|
+
}
|
|
19
|
+
function useDb(selector, isEqual) {
|
|
20
|
+
const { replica } = useKyjuContext();
|
|
21
|
+
const selectorRef = useRef(selector);
|
|
22
|
+
selectorRef.current = selector;
|
|
23
|
+
const isEqualRef = useRef(isEqual);
|
|
24
|
+
isEqualRef.current = isEqual;
|
|
25
|
+
const cacheRef = useRef(null);
|
|
26
|
+
return useSyncExternalStore(useCallback((cb) => replica.subscribe(() => cb()), [replica]), useCallback(() => {
|
|
27
|
+
const state = replica.getState();
|
|
28
|
+
if (state.kind !== "connected") return void 0;
|
|
29
|
+
const root = state.root;
|
|
30
|
+
const sel = selectorRef.current;
|
|
31
|
+
if (!sel) return root;
|
|
32
|
+
const next = sel(root);
|
|
33
|
+
const cache = cacheRef.current;
|
|
34
|
+
if (cache != null) {
|
|
35
|
+
if ((isEqualRef.current ?? shallowEqual)(cache.output, next)) return cache.output;
|
|
36
|
+
}
|
|
37
|
+
cacheRef.current = { output: next };
|
|
38
|
+
return next;
|
|
39
|
+
}, [replica]));
|
|
40
|
+
}
|
|
41
|
+
function useCollection(ref) {
|
|
42
|
+
const { replica } = useKyjuContext();
|
|
43
|
+
const collectionId = ref?.collectionId || null;
|
|
44
|
+
const [state, setState] = useState({
|
|
45
|
+
items: [],
|
|
46
|
+
totalCount: 0,
|
|
47
|
+
collection: null
|
|
48
|
+
});
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (!collectionId) return;
|
|
51
|
+
const onData = (data) => {
|
|
52
|
+
setState({
|
|
53
|
+
items: data.collection.items,
|
|
54
|
+
totalCount: data.collection.totalCount,
|
|
55
|
+
collection: data.collection
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
replica.onCollectionConcat(collectionId, onData);
|
|
59
|
+
replica.postMessage({
|
|
60
|
+
kind: "subscribe-collection",
|
|
61
|
+
collectionId
|
|
62
|
+
}).then(() => {
|
|
63
|
+
const s = replica.getState();
|
|
64
|
+
if (s.kind === "connected") {
|
|
65
|
+
const col = s.collections.find((c) => c.id === collectionId);
|
|
66
|
+
if (col) onData({
|
|
67
|
+
collection: col,
|
|
68
|
+
newItems: []
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
return () => {
|
|
73
|
+
replica.offCollectionConcat(collectionId, onData);
|
|
74
|
+
replica.postMessage({
|
|
75
|
+
kind: "unsubscribe-collection",
|
|
76
|
+
collectionId
|
|
77
|
+
}).catch(() => {});
|
|
78
|
+
};
|
|
79
|
+
}, [collectionId, replica]);
|
|
80
|
+
const concat = useMemo(() => {
|
|
81
|
+
if (!collectionId) return (_items) => {};
|
|
82
|
+
return (items) => {
|
|
83
|
+
replica.postMessage({
|
|
84
|
+
kind: "write",
|
|
85
|
+
op: {
|
|
86
|
+
type: "collection.concat",
|
|
87
|
+
collectionId,
|
|
88
|
+
data: items
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
}, [collectionId, replica]);
|
|
93
|
+
return useMemo(() => ({
|
|
94
|
+
...state,
|
|
95
|
+
concat
|
|
96
|
+
}), [state, concat]);
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
KyjuProvider,
|
|
100
|
+
useDb,
|
|
101
|
+
useCollection
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function shallowEqual(a, b) {
|
|
105
|
+
if (Object.is(a, b)) return true;
|
|
106
|
+
if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) return false;
|
|
107
|
+
if (Array.isArray(a)) {
|
|
108
|
+
if (!Array.isArray(b) || a.length !== b.length) return false;
|
|
109
|
+
for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false;
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
if (Array.isArray(b)) return false;
|
|
113
|
+
const ao = a;
|
|
114
|
+
const bo = b;
|
|
115
|
+
const ka = Object.keys(ao);
|
|
116
|
+
const kb = Object.keys(bo);
|
|
117
|
+
if (ka.length !== kb.length) return false;
|
|
118
|
+
for (const k of ka) {
|
|
119
|
+
if (!Object.prototype.hasOwnProperty.call(bo, k)) return false;
|
|
120
|
+
if (!Object.is(ao[k], bo[k])) return false;
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/react.ts
|
|
126
|
+
/**
|
|
127
|
+
* Public renderer-side surface for plugin authors. Wraps the websocket
|
|
128
|
+
* lifecycle, RPC client, replica DB connection, and event subscription
|
|
129
|
+
* behind a single `<ZenbuProvider>` plus hooks.
|
|
130
|
+
*
|
|
131
|
+
* DB hooks (`useDb`, `useCollection`) are implemented in `@zenbu/kyju/react`
|
|
132
|
+
* and composed here via `KyjuProvider` mounted inside `ZenbuProvider`.
|
|
133
|
+
* Core only adds the websocket lifecycle (RPC/events) and the
|
|
134
|
+
* `ZenbuRegister`-driven type narrowing so call sites never need a generic.
|
|
135
|
+
*/
|
|
136
|
+
const ConnectionContext = createContext(null);
|
|
137
|
+
const kyjuReact = createKyjuReact();
|
|
138
|
+
function useDb(selector, isEqual) {
|
|
139
|
+
return kyjuReact.useDb(selector, isEqual);
|
|
140
|
+
}
|
|
141
|
+
const useCollection = kyjuReact.useCollection;
|
|
142
|
+
function ZenbuProvider({ wsUrl, fallback, errorFallback, children }) {
|
|
143
|
+
const [state, setState] = useState({ status: "connecting" });
|
|
144
|
+
const cleanupRef = useRef(null);
|
|
145
|
+
const retriesRef = useRef(0);
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
let cancelled = false;
|
|
148
|
+
let reconnectTimer = null;
|
|
149
|
+
const resolvedUrl = (() => {
|
|
150
|
+
if (wsUrl) return wsUrl;
|
|
151
|
+
const params = new URLSearchParams(window.location.search);
|
|
152
|
+
const port = params.get("wsPort");
|
|
153
|
+
const token = params.get("wsToken");
|
|
154
|
+
if (!port) return { error: "Missing ?wsPort= in URL" };
|
|
155
|
+
if (!token) return { error: "Missing ?wsToken= in URL" };
|
|
156
|
+
return `ws://127.0.0.1:${port}?token=${encodeURIComponent(token)}`;
|
|
157
|
+
})();
|
|
158
|
+
if (typeof resolvedUrl !== "string") {
|
|
159
|
+
setState({
|
|
160
|
+
status: "error",
|
|
161
|
+
error: resolvedUrl.error
|
|
162
|
+
});
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
function connect() {
|
|
166
|
+
if (cancelled) return;
|
|
167
|
+
setState({ status: "connecting" });
|
|
168
|
+
cleanupRef.current = null;
|
|
169
|
+
const ws = new WebSocket(resolvedUrl);
|
|
170
|
+
ws.onopen = async () => {
|
|
171
|
+
try {
|
|
172
|
+
retriesRef.current = 0;
|
|
173
|
+
const { server: rpc, events, disconnect: disconnectRpc } = await connectRpc({
|
|
174
|
+
version: "0",
|
|
175
|
+
send: (data) => {
|
|
176
|
+
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify({
|
|
177
|
+
ch: "rpc",
|
|
178
|
+
data
|
|
179
|
+
}));
|
|
180
|
+
},
|
|
181
|
+
subscribe: (cb) => {
|
|
182
|
+
const handler = (e) => {
|
|
183
|
+
const msg = JSON.parse(e.data);
|
|
184
|
+
if (msg.ch === "rpc") cb(msg.data);
|
|
185
|
+
};
|
|
186
|
+
ws.addEventListener("message", handler);
|
|
187
|
+
return () => ws.removeEventListener("message", handler);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
const { client: db, replica, disconnect: disconnectDb } = await connectReplica({
|
|
191
|
+
send: (event) => {
|
|
192
|
+
if (ws.readyState === WebSocket.OPEN) ws.send(dbStringify({
|
|
193
|
+
ch: "db",
|
|
194
|
+
data: event
|
|
195
|
+
}));
|
|
196
|
+
},
|
|
197
|
+
subscribe: (cb) => {
|
|
198
|
+
const handler = (e) => {
|
|
199
|
+
const msg = dbParse(e.data);
|
|
200
|
+
if (msg.ch === "db") cb(msg.data);
|
|
201
|
+
};
|
|
202
|
+
ws.addEventListener("message", handler);
|
|
203
|
+
return () => ws.removeEventListener("message", handler);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
if (cancelled) {
|
|
207
|
+
await disconnectDb();
|
|
208
|
+
disconnectRpc();
|
|
209
|
+
ws.close();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const viewMatch = window.location.pathname.match(/^\/views\/([^/]+)\//);
|
|
213
|
+
const viewScope = viewMatch ? viewMatch[1] : null;
|
|
214
|
+
let unsubReload = null;
|
|
215
|
+
if (viewScope) {
|
|
216
|
+
const adviceReload = events?.advice?.reload;
|
|
217
|
+
if (adviceReload?.subscribe) unsubReload = adviceReload.subscribe((data) => {
|
|
218
|
+
if (data?.scope === viewScope) location.reload();
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
cleanupRef.current = () => {
|
|
222
|
+
unsubReload?.();
|
|
223
|
+
disconnectDb();
|
|
224
|
+
disconnectRpc();
|
|
225
|
+
ws.close();
|
|
226
|
+
};
|
|
227
|
+
setState({
|
|
228
|
+
status: "connected",
|
|
229
|
+
conn: {
|
|
230
|
+
rpc,
|
|
231
|
+
events,
|
|
232
|
+
db,
|
|
233
|
+
replica
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
} catch (err) {
|
|
237
|
+
if (!cancelled) {
|
|
238
|
+
ws.close();
|
|
239
|
+
scheduleReconnect();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
ws.onerror = () => {};
|
|
244
|
+
ws.onclose = () => {
|
|
245
|
+
if (!cancelled) {
|
|
246
|
+
cleanupRef.current?.();
|
|
247
|
+
cleanupRef.current = null;
|
|
248
|
+
scheduleReconnect();
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
function scheduleReconnect() {
|
|
253
|
+
if (cancelled) return;
|
|
254
|
+
const delay = Math.min(300 * Math.pow(2, retriesRef.current), 3e3);
|
|
255
|
+
retriesRef.current++;
|
|
256
|
+
setState({ status: "connecting" });
|
|
257
|
+
reconnectTimer = setTimeout(connect, delay);
|
|
258
|
+
}
|
|
259
|
+
connect();
|
|
260
|
+
return () => {
|
|
261
|
+
cancelled = true;
|
|
262
|
+
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
263
|
+
cleanupRef.current?.();
|
|
264
|
+
cleanupRef.current = null;
|
|
265
|
+
};
|
|
266
|
+
}, [wsUrl]);
|
|
267
|
+
if (state.status === "connecting") return createElement("span", { "data-zenbu-connecting": true }, fallback ?? null);
|
|
268
|
+
if (state.status === "error") return createElement("span", { "data-zenbu-error": true }, errorFallback ? errorFallback(state.error) : null);
|
|
269
|
+
return createElement(ConnectionContext.Provider, { value: state }, createElement(kyjuReact.KyjuProvider, {
|
|
270
|
+
client: state.conn.db,
|
|
271
|
+
replica: state.conn.replica,
|
|
272
|
+
children
|
|
273
|
+
}));
|
|
274
|
+
}
|
|
275
|
+
function useConnection() {
|
|
276
|
+
const state = useContext(ConnectionContext);
|
|
277
|
+
if (!state) throw new Error("useDb/useRpc/useEvents must be used inside <ZenbuProvider>");
|
|
278
|
+
if (state.status !== "connected") throw new Error(`Zenbu connection is not ready (status: ${state.status}). Render a <ZenbuProvider fallback={...}> around your hooks.`);
|
|
279
|
+
return state.conn;
|
|
280
|
+
}
|
|
281
|
+
function useRpc() {
|
|
282
|
+
return useConnection().rpc;
|
|
283
|
+
}
|
|
284
|
+
function useDbClient() {
|
|
285
|
+
return useConnection().db;
|
|
286
|
+
}
|
|
287
|
+
function useEvents() {
|
|
288
|
+
return useConnection().events;
|
|
289
|
+
}
|
|
290
|
+
//#endregion
|
|
291
|
+
export { ZenbuProvider, useCollection, useDb, useDbClient, useEvents, useRpc };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { n as SchemaRoot } from "./schema-DMoSkwUx.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/registry.d.ts
|
|
4
|
+
type CoreEvents = {
|
|
5
|
+
advice: {
|
|
6
|
+
reload: {
|
|
7
|
+
scope: string;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
type Events = CoreEvents;
|
|
12
|
+
type CoreDbSections = {
|
|
13
|
+
core: SchemaRoot;
|
|
14
|
+
};
|
|
15
|
+
type CorePreloads = {};
|
|
16
|
+
type CoreServiceRouter = {};
|
|
17
|
+
/**
|
|
18
|
+
* Module-augmentation point for plugin authors. `zen link` generates
|
|
19
|
+
* `<app>/types/zenbu-register.ts` which declares:
|
|
20
|
+
*
|
|
21
|
+
* declare module "@zenbujs/core/registry" {
|
|
22
|
+
* interface ZenbuRegister {
|
|
23
|
+
* db: DbRoot
|
|
24
|
+
* rpc: ServiceRouter
|
|
25
|
+
* events: PluginEvents
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
*
|
|
29
|
+
* Server services (`DbService.client`, `RpcService.emit`) and renderer hooks
|
|
30
|
+
* (`useDb`, `useRpc`, `useEvents`) all read their types from this single
|
|
31
|
+
* registry, so the user's plugin types flow everywhere automatically.
|
|
32
|
+
*
|
|
33
|
+
* Mirrors the pattern TanStack Router uses for `Register`.
|
|
34
|
+
*/
|
|
35
|
+
interface ZenbuRegister {}
|
|
36
|
+
/**
|
|
37
|
+
* Resolve the DB-root type from `ZenbuRegister["db"]`, falling back to a
|
|
38
|
+
* core-only root when no augmentation has been declared (e.g. a plugin that
|
|
39
|
+
* only emits events / RPC and doesn't define its own DB sections).
|
|
40
|
+
*/
|
|
41
|
+
type ResolvedDbRoot = ZenbuRegister extends {
|
|
42
|
+
db: infer T;
|
|
43
|
+
} ? T : {
|
|
44
|
+
plugin: CoreDbSections;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Resolve the RPC router type from `ZenbuRegister["rpc"]`, falling back to
|
|
48
|
+
* the core router when no augmentation has been declared.
|
|
49
|
+
*/
|
|
50
|
+
type ResolvedServiceRouter = ZenbuRegister extends {
|
|
51
|
+
rpc: infer T;
|
|
52
|
+
} ? T : CoreServiceRouter;
|
|
53
|
+
/**
|
|
54
|
+
* Resolve the events tree from `ZenbuRegister["events"]`, falling back to
|
|
55
|
+
* `CoreEvents` when no augmentation has been declared.
|
|
56
|
+
*/
|
|
57
|
+
type ResolvedEvents = ZenbuRegister extends {
|
|
58
|
+
events: infer T;
|
|
59
|
+
} ? T : CoreEvents;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { Events as a, ResolvedServiceRouter as c, CoreServiceRouter as i, ZenbuRegister as l, CoreEvents as n, ResolvedDbRoot as o, CorePreloads as r, ResolvedEvents as s, CoreDbSections as t };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { a as Events, c as ResolvedServiceRouter, i as CoreServiceRouter, l as ZenbuRegister, n as CoreEvents, o as ResolvedDbRoot, r as CorePreloads, s as ResolvedEvents, t as CoreDbSections } from "./registry-Dh_e7HU1.mjs";
|
|
2
|
+
export { CoreDbSections, CoreEvents, CorePreloads, CoreServiceRouter, Events, ResolvedDbRoot, ResolvedEvents, ResolvedServiceRouter, ZenbuRegister };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { i as runtime, t as Service } from "./runtime-DUFKDIe4.mjs";
|
|
2
|
+
import { t as createLogger } from "./log-CyKv8hQg.mjs";
|
|
3
|
+
import { a as zenbuVitePlugins } from "./vite-plugins-Bh3SCOw-.mjs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path, { resolve } from "node:path";
|
|
6
|
+
import { createHash } from "node:crypto";
|
|
7
|
+
import { createServer } from "vite";
|
|
8
|
+
import { access, mkdir, readdir } from "node:fs/promises";
|
|
9
|
+
import { createServer as createServer$1 } from "node:net";
|
|
10
|
+
//#region src/shared/paths.ts
|
|
11
|
+
const ZENBU_HOME = path.join(os.homedir(), ".zenbu");
|
|
12
|
+
const INTERNAL_DIR = path.join(ZENBU_HOME, ".internal");
|
|
13
|
+
path.join(INTERNAL_DIR, "runtime.json");
|
|
14
|
+
const DB_CONFIG_JSON = path.join(INTERNAL_DIR, "db.json");
|
|
15
|
+
path.join(INTERNAL_DIR, "plugin-setup-state.json");
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/services/reloader.ts
|
|
18
|
+
const log = createLogger("reloader");
|
|
19
|
+
function safeCacheSegment(value) {
|
|
20
|
+
return value.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "renderer";
|
|
21
|
+
}
|
|
22
|
+
function resolveRendererCacheDir(options) {
|
|
23
|
+
const hash = createHash("sha256").update(options.id).update("\0").update(resolve(options.root)).update("\0").update(options.configFile ? resolve(options.configFile) : "no-config").digest("hex").slice(0, 12);
|
|
24
|
+
return resolve(INTERNAL_DIR, "vite-cache", `${safeCacheSegment(options.id)}-${hash}`);
|
|
25
|
+
}
|
|
26
|
+
async function fileExists(p) {
|
|
27
|
+
try {
|
|
28
|
+
await access(p);
|
|
29
|
+
return true;
|
|
30
|
+
} catch {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function rendererWarmupUrls(root) {
|
|
35
|
+
const urls = /* @__PURE__ */ new Set();
|
|
36
|
+
if (await fileExists(resolve(root, "main.tsx"))) urls.add("/main.tsx");
|
|
37
|
+
const viewsDir = resolve(root, "views");
|
|
38
|
+
try {
|
|
39
|
+
for (const entry of await readdir(viewsDir, { withFileTypes: true })) {
|
|
40
|
+
if (!entry.isDirectory()) continue;
|
|
41
|
+
if (await fileExists(resolve(viewsDir, entry.name, "main.tsx"))) urls.add(`/views/${entry.name}/main.tsx`);
|
|
42
|
+
}
|
|
43
|
+
} catch {}
|
|
44
|
+
return [...urls];
|
|
45
|
+
}
|
|
46
|
+
async function warmupRendererEntrypoints(server, root) {
|
|
47
|
+
try {
|
|
48
|
+
const urls = await rendererWarmupUrls(root);
|
|
49
|
+
await Promise.all(urls.map((url) => server.warmupRequest(url)));
|
|
50
|
+
} catch (e) {
|
|
51
|
+
log.warn("renderer warmup failed:", e);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function getEphemeralPort() {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
const srv = createServer$1();
|
|
57
|
+
srv.listen(0, () => {
|
|
58
|
+
const { port } = srv.address();
|
|
59
|
+
srv.close(() => resolve(port));
|
|
60
|
+
});
|
|
61
|
+
srv.on("error", reject);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async function startRendererServer(options) {
|
|
65
|
+
let server;
|
|
66
|
+
const port = options.port || await getEphemeralPort();
|
|
67
|
+
const cacheDir = options.cacheDir ?? resolveRendererCacheDir(options);
|
|
68
|
+
await mkdir(cacheDir, { recursive: true });
|
|
69
|
+
const sharedConfig = {
|
|
70
|
+
cacheDir,
|
|
71
|
+
server: {
|
|
72
|
+
port,
|
|
73
|
+
strictPort: true,
|
|
74
|
+
hmr: {
|
|
75
|
+
protocol: "ws",
|
|
76
|
+
host: "localhost"
|
|
77
|
+
},
|
|
78
|
+
fs: { strict: false }
|
|
79
|
+
},
|
|
80
|
+
logLevel: "warn"
|
|
81
|
+
};
|
|
82
|
+
const frameworkPlugins = zenbuVitePlugins();
|
|
83
|
+
if (options.configFile) server = await createServer({
|
|
84
|
+
...sharedConfig,
|
|
85
|
+
root: options.root,
|
|
86
|
+
configFile: options.configFile,
|
|
87
|
+
plugins: [...frameworkPlugins, ...options.plugins ?? []]
|
|
88
|
+
});
|
|
89
|
+
else {
|
|
90
|
+
const plugins = [...frameworkPlugins, ...options.plugins ?? []];
|
|
91
|
+
if (options.reactPlugin) plugins.unshift(options.reactPlugin());
|
|
92
|
+
else try {
|
|
93
|
+
const react = await import("@vitejs/plugin-react");
|
|
94
|
+
plugins.unshift(react.default());
|
|
95
|
+
} catch {}
|
|
96
|
+
server = await createServer({
|
|
97
|
+
...sharedConfig,
|
|
98
|
+
root: options.root,
|
|
99
|
+
plugins,
|
|
100
|
+
resolve: options.resolve,
|
|
101
|
+
configFile: false
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
await server.listen();
|
|
105
|
+
const addr = server.httpServer?.address();
|
|
106
|
+
const assignedPort = typeof addr === "object" && addr ? addr.port : 0;
|
|
107
|
+
if (assignedPort) {
|
|
108
|
+
const hmr = server.config.server.hmr;
|
|
109
|
+
if (typeof hmr === "object") hmr.clientPort = assignedPort;
|
|
110
|
+
}
|
|
111
|
+
await warmupRendererEntrypoints(server, options.root);
|
|
112
|
+
return server;
|
|
113
|
+
}
|
|
114
|
+
var ReloaderService = class extends Service {
|
|
115
|
+
static key = "reloader";
|
|
116
|
+
static deps = {};
|
|
117
|
+
servers = /* @__PURE__ */ new Map();
|
|
118
|
+
async create(id, root, configFile) {
|
|
119
|
+
if (this.servers.has(id)) return this.servers.get(id);
|
|
120
|
+
const viteServer = await startRendererServer({
|
|
121
|
+
id,
|
|
122
|
+
root,
|
|
123
|
+
configFile: configFile ?? false,
|
|
124
|
+
port: 0
|
|
125
|
+
});
|
|
126
|
+
const address = viteServer.httpServer?.address();
|
|
127
|
+
const port = typeof address === "object" && address ? address.port : 5173;
|
|
128
|
+
const entry = {
|
|
129
|
+
id,
|
|
130
|
+
root,
|
|
131
|
+
url: `http://localhost:${port}`,
|
|
132
|
+
port,
|
|
133
|
+
viteServer
|
|
134
|
+
};
|
|
135
|
+
this.servers.set(id, entry);
|
|
136
|
+
log.verbose(`${id} ready at ${entry.url}`);
|
|
137
|
+
return entry;
|
|
138
|
+
}
|
|
139
|
+
get(id) {
|
|
140
|
+
return this.servers.get(id);
|
|
141
|
+
}
|
|
142
|
+
async remove(id) {
|
|
143
|
+
const entry = this.servers.get(id);
|
|
144
|
+
if (entry) {
|
|
145
|
+
await entry.viteServer.close();
|
|
146
|
+
this.servers.delete(id);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
evaluate() {
|
|
150
|
+
this.setup("vite-cleanup", () => {
|
|
151
|
+
return async () => {
|
|
152
|
+
const entries = [...this.servers.values()];
|
|
153
|
+
this.servers.clear();
|
|
154
|
+
(await Promise.allSettled(entries.map((entry) => entry.viteServer.close()))).forEach((res, i) => {
|
|
155
|
+
if (res.status === "rejected") log.error(`viteServer.close failed for ${entries[i].id}:`, res.reason);
|
|
156
|
+
});
|
|
157
|
+
};
|
|
158
|
+
});
|
|
159
|
+
log.verbose(`service ready (${this.servers.size} servers)`);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
runtime.register(ReloaderService, import.meta);
|
|
163
|
+
//#endregion
|
|
164
|
+
export { DB_CONFIG_JSON as n, INTERNAL_DIR as r, ReloaderService as t };
|