@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.
Files changed (94) hide show
  1. package/LICENSE +11 -0
  2. package/dist/advice-config-CjgkEf2E.mjs +135 -0
  3. package/dist/advice-config-Cy133IQP.mjs +2 -0
  4. package/dist/advice-runtime.d.mts +35 -0
  5. package/dist/advice-runtime.mjs +131 -0
  6. package/dist/advice.d.mts +36 -0
  7. package/dist/advice.mjs +2 -0
  8. package/dist/base-window-BUt8pwbw.mjs +94 -0
  9. package/dist/base-window-DEIAk618.mjs +2 -0
  10. package/dist/build-config-pbv0w4oN.mjs +17 -0
  11. package/dist/build-electron-B4Gd0Gi4.mjs +516 -0
  12. package/dist/build-source-_q1n1zTV.mjs +162 -0
  13. package/dist/chunk-Dm34NbLt.mjs +6 -0
  14. package/dist/cli/bin.d.mts +1 -0
  15. package/dist/cli/bin.mjs +88 -0
  16. package/dist/cli/build.d.mts +53 -0
  17. package/dist/cli/build.mjs +48 -0
  18. package/dist/cli-BLbQQIVB.mjs +8054 -0
  19. package/dist/config-CdVrW85P.mjs +59 -0
  20. package/dist/config-LK73dJmO.mjs +2 -0
  21. package/dist/db-ByKPbnP6.mjs +2 -0
  22. package/dist/db-DhuAJrye.mjs +531 -0
  23. package/dist/db.d.mts +16 -0
  24. package/dist/db.mjs +16 -0
  25. package/dist/dev-BuqklM0k.mjs +85 -0
  26. package/dist/env-bootstrap-BtVME-CU.d.mts +16 -0
  27. package/dist/env-bootstrap-rj7I-59x.mjs +53 -0
  28. package/dist/env-bootstrap.d.mts +2 -0
  29. package/dist/env-bootstrap.mjs +2 -0
  30. package/dist/http-IBcLzbYu.mjs +2 -0
  31. package/dist/index-Bhlbyrn7.d.mts +63 -0
  32. package/dist/index-CPZ5d6Hl.d.mts +442 -0
  33. package/dist/index-FtE8MXJ_.d.mts +1 -0
  34. package/dist/index.d.mts +6 -0
  35. package/dist/index.mjs +5 -0
  36. package/dist/launcher.mjs +173 -0
  37. package/dist/link-6roQ7Cn6.mjs +580 -0
  38. package/dist/loaders/zenbu.d.mts +22 -0
  39. package/dist/loaders/zenbu.mjs +267 -0
  40. package/dist/log-CyKv8hQg.mjs +20 -0
  41. package/dist/mirror-sync-CodOnwkD.mjs +332 -0
  42. package/dist/monorepo-CmGPHsVm.mjs +119 -0
  43. package/dist/node-D4M19_mV.mjs +5 -0
  44. package/dist/node-loader.d.mts +17 -0
  45. package/dist/node-loader.mjs +33 -0
  46. package/dist/pause-DvAUNmKn.mjs +52 -0
  47. package/dist/publish-source-BVgB62Zj.mjs +131 -0
  48. package/dist/react.d.mts +76 -0
  49. package/dist/react.mjs +291 -0
  50. package/dist/registry-Dh_e7HU1.d.mts +61 -0
  51. package/dist/registry.d.mts +2 -0
  52. package/dist/registry.mjs +1 -0
  53. package/dist/reloader-BCkLjDhS.mjs +2 -0
  54. package/dist/reloader-lLAJ3lqg.mjs +164 -0
  55. package/dist/renderer-host-Bg8QdeeH.mjs +1508 -0
  56. package/dist/renderer-host-DpvBPTHJ.mjs +2 -0
  57. package/dist/rpc-BwwQK6hD.mjs +71 -0
  58. package/dist/rpc-CqitnyR4.mjs +2 -0
  59. package/dist/rpc.d.mts +2 -0
  60. package/dist/rpc.mjs +2 -0
  61. package/dist/runtime-CjqDr8Yf.d.mts +109 -0
  62. package/dist/runtime-DUFKDIe4.mjs +409 -0
  63. package/dist/runtime.d.mts +2 -0
  64. package/dist/runtime.mjs +2 -0
  65. package/dist/schema-CIg4GzHQ.mjs +100 -0
  66. package/dist/schema-DMoSkwUx.d.mts +62 -0
  67. package/dist/schema-dGK6qkfR.mjs +28 -0
  68. package/dist/schema.d.mts +2 -0
  69. package/dist/schema.mjs +2 -0
  70. package/dist/server-BXwZEQ-n.mjs +66 -0
  71. package/dist/server-DjrZUbbu.mjs +2 -0
  72. package/dist/services/default.d.mts +11 -0
  73. package/dist/services/default.mjs +22 -0
  74. package/dist/services/index.d.mts +276 -0
  75. package/dist/services/index.mjs +7 -0
  76. package/dist/setup-gate-BeD6WS6d.mjs +110 -0
  77. package/dist/setup-gate-BqOzm7zp.d.mts +4 -0
  78. package/dist/setup-gate.d.mts +2 -0
  79. package/dist/setup-gate.mjs +2 -0
  80. package/dist/src-pELM4_iH.mjs +376 -0
  81. package/dist/trace-DCB7qFzT.mjs +10 -0
  82. package/dist/transform-DJH3vN4b.mjs +84041 -0
  83. package/dist/transport-BMSzG2-F.mjs +1045 -0
  84. package/dist/view-registry-BualWgAf.mjs +2 -0
  85. package/dist/vite-plugins-Bh3SCOw-.mjs +331 -0
  86. package/dist/vite.d.mts +68 -0
  87. package/dist/vite.mjs +2 -0
  88. package/dist/window-CM2a9Kyc.mjs +2 -0
  89. package/dist/window-CmmpCVX6.mjs +156 -0
  90. package/dist/write-9dRFczGJ.mjs +1248 -0
  91. package/migrations/0000_migration.ts +34 -0
  92. package/migrations/meta/0000_snapshot.json +18 -0
  93. package/migrations/meta/_journal.json +10 -0
  94. 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,2 @@
1
+ import "./reloader-lLAJ3lqg.mjs";
2
+ 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 };