@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
package/dist/react.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { f as CollectionRefBrand, h as InferCollectionItem, n as connectReplica, o as ClientProxy, p as CollectionRefValue, u as CollectionState, y as SchemaShape } from "./index-
|
|
2
|
-
import { c as ResolvedServiceRouter, l as ZenbuRegister, o as ResolvedDbRoot, s as ResolvedEvents } from "./registry-eX6e2oql.mjs";
|
|
1
|
+
import { f as CollectionRefBrand, h as InferCollectionItem, n as connectReplica, o as ClientProxy, p as CollectionRefValue, u as CollectionState, y as SchemaShape } from "./index-DeDxePAa.mjs";
|
|
3
2
|
import { n as EventProxy, r as RouterProxy } from "./index-C-ALz_SH.mjs";
|
|
3
|
+
import { i as ZenbuRegister, n as ResolvedEvents, r as ResolvedServiceRouter, t as ResolvedDbRoot } from "./registry-CMp8FYgS.mjs";
|
|
4
4
|
import * as _$react from "react";
|
|
5
|
-
import { ReactNode } from "react";
|
|
5
|
+
import { CSSProperties, ReactElement, ReactNode } from "react";
|
|
6
6
|
|
|
7
7
|
//#region ../kyju/src/v2/react/index.d.ts
|
|
8
8
|
type CollectionResult<Item> = {
|
|
@@ -57,9 +57,9 @@ declare function ZenbuProvider({
|
|
|
57
57
|
fallback,
|
|
58
58
|
errorFallback,
|
|
59
59
|
children
|
|
60
|
-
}: ZenbuProviderProps):
|
|
60
|
+
}: ZenbuProviderProps): ReactElement<{
|
|
61
61
|
"data-zenbu-connecting": boolean;
|
|
62
|
-
}, string | _$react.JSXElementConstructor<any>> |
|
|
62
|
+
}, string | _$react.JSXElementConstructor<any>> | ReactElement<{
|
|
63
63
|
"data-zenbu-error": boolean;
|
|
64
64
|
}, string | _$react.JSXElementConstructor<any>> | _$react.FunctionComponentElement<_$react.ProviderProps<ConnectionState | null>>;
|
|
65
65
|
declare function useRpc(): RouterProxy<RegisteredServiceRouter>;
|
|
@@ -72,5 +72,54 @@ type DbClient = {
|
|
|
72
72
|
};
|
|
73
73
|
declare function useDbClient(): DbClient;
|
|
74
74
|
declare function useEvents(): EventProxy<RegisteredEvents>;
|
|
75
|
+
/**
|
|
76
|
+
* Mounts a registered view (separate Vite root, registered via
|
|
77
|
+
* `ViewRegistryService.register(type, …)`) inside an `<iframe>` and:
|
|
78
|
+
*
|
|
79
|
+
* 1. **Auto-inherits auth from the parent iframe's URL.** Reads `wsPort` /
|
|
80
|
+
* `wsToken` from `window.location.search` and forwards them in the
|
|
81
|
+
* child URL so the child's `<ZenbuProvider>` connects without the
|
|
82
|
+
* consumer wiring anything.
|
|
83
|
+
* 2. **Mount-once src.** The iframe's `src` is set on first mount and
|
|
84
|
+
* *never updated*. Toggling `visible` only flips `style.display` —
|
|
85
|
+
* state inside the child (sockets, ghostty terminals, etc.) survives
|
|
86
|
+
* visibility changes.
|
|
87
|
+
* 3. **Initial args via URL.** `args` is encoded as base64 JSON in
|
|
88
|
+
* `?args=` on first paint so the child can render without waiting on
|
|
89
|
+
* a postMessage handshake. Use `useViewArgs<T>()` inside the child
|
|
90
|
+
* to read.
|
|
91
|
+
* 4. **Reactive args via postMessage.** When `args` changes after mount,
|
|
92
|
+
* we send `{ kind: "zenbu:view-args", args }` to the iframe's
|
|
93
|
+
* `contentWindow`. URL is *not* rewritten (iframe stays alive).
|
|
94
|
+
*
|
|
95
|
+
* Child sessions die on unmount. There is no cache: if the consumer
|
|
96
|
+
* unmounts the `<View>` element, any state inside it (e.g. PTY sockets)
|
|
97
|
+
* is gone. Caller is responsible for explicit teardown via RPC if
|
|
98
|
+
* needed.
|
|
99
|
+
*/
|
|
100
|
+
type ViewProps = {
|
|
101
|
+
/** Registered view type — first arg to `ViewRegistryService.register`. */type: string; /** Initial args; serialized into the child URL as base64-JSON. */
|
|
102
|
+
args?: Record<string, unknown>; /** When false, sets `style.display: none`. Iframe is NOT unmounted. */
|
|
103
|
+
visible?: boolean;
|
|
104
|
+
style?: CSSProperties;
|
|
105
|
+
className?: string;
|
|
106
|
+
onLoad?: () => void; /** Rendered while the view registry has not yet reported a URL for this type. */
|
|
107
|
+
fallback?: ReactNode;
|
|
108
|
+
};
|
|
109
|
+
declare function View({
|
|
110
|
+
type,
|
|
111
|
+
args,
|
|
112
|
+
visible,
|
|
113
|
+
style,
|
|
114
|
+
className,
|
|
115
|
+
onLoad,
|
|
116
|
+
fallback
|
|
117
|
+
}: ViewProps): ReactElement;
|
|
118
|
+
/**
|
|
119
|
+
* Read the current view args inside a child iframe rendered by `<View>`.
|
|
120
|
+
* Initial value comes from `?args=` in the iframe's URL; updates arrive
|
|
121
|
+
* via `postMessage` and re-render this hook's caller.
|
|
122
|
+
*/
|
|
123
|
+
declare function useViewArgs<T extends Record<string, unknown>>(): T;
|
|
75
124
|
//#endregion
|
|
76
|
-
export { type CollectionRefValue, DbClient, ZenbuProvider, ZenbuProviderProps, type ZenbuRegister, useCollection, useDb, useDbClient, useEvents, useRpc };
|
|
125
|
+
export { type CollectionRefValue, DbClient, View, ViewProps, ZenbuProvider, ZenbuProviderProps, type ZenbuRegister, useCollection, useDb, useDbClient, useEvents, useRpc, useViewArgs };
|
package/dist/react.mjs
CHANGED
|
@@ -209,13 +209,12 @@ function ZenbuProvider({ wsUrl, fallback, errorFallback, children }) {
|
|
|
209
209
|
ws.close();
|
|
210
210
|
return;
|
|
211
211
|
}
|
|
212
|
-
const
|
|
213
|
-
const viewScope = viewMatch ? viewMatch[1] : null;
|
|
212
|
+
const viewType = window.location.pathname.match(/^\/views\/([^/]+)\//)?.[1] ?? new URLSearchParams(window.location.search).get("type");
|
|
214
213
|
let unsubReload = null;
|
|
215
|
-
if (
|
|
214
|
+
if (viewType) {
|
|
216
215
|
const adviceReload = events?.advice?.reload;
|
|
217
216
|
if (adviceReload?.subscribe) unsubReload = adviceReload.subscribe((data) => {
|
|
218
|
-
if (data?.
|
|
217
|
+
if (data?.type === "*" || data?.type === viewType) location.reload();
|
|
219
218
|
});
|
|
220
219
|
}
|
|
221
220
|
cleanupRef.current = () => {
|
|
@@ -287,5 +286,117 @@ function useDbClient() {
|
|
|
287
286
|
function useEvents() {
|
|
288
287
|
return useConnection().events;
|
|
289
288
|
}
|
|
289
|
+
const VIEW_ARGS_MESSAGE_KIND = "zenbu:view-args";
|
|
290
|
+
const VIEW_ARGS_PARAM_LIMIT = 1500;
|
|
291
|
+
function encodeViewArgs(args) {
|
|
292
|
+
if (!args) return null;
|
|
293
|
+
try {
|
|
294
|
+
return btoa(unescape(encodeURIComponent(JSON.stringify(args))));
|
|
295
|
+
} catch (err) {
|
|
296
|
+
console.warn("[zenbu/View] failed to encode args:", err);
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function decodeViewArgs(encoded) {
|
|
301
|
+
if (!encoded) return {};
|
|
302
|
+
try {
|
|
303
|
+
return JSON.parse(decodeURIComponent(escape(atob(encoded))));
|
|
304
|
+
} catch (err) {
|
|
305
|
+
console.warn("[zenbu/View] failed to decode args:", err);
|
|
306
|
+
return {};
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function buildViewUrl(baseUrl, type, encodedArgs) {
|
|
310
|
+
const trimmed = baseUrl.replace(/\/$/, "");
|
|
311
|
+
const parentParams = new URLSearchParams(window.location.search);
|
|
312
|
+
const params = new URLSearchParams();
|
|
313
|
+
const wsPort = parentParams.get("wsPort");
|
|
314
|
+
const wsToken = parentParams.get("wsToken");
|
|
315
|
+
if (wsPort) params.set("wsPort", wsPort);
|
|
316
|
+
if (wsToken) params.set("wsToken", wsToken);
|
|
317
|
+
params.set("type", type);
|
|
318
|
+
if (encodedArgs) params.set("args", encodedArgs);
|
|
319
|
+
return `${trimmed}/?${params.toString()}`;
|
|
320
|
+
}
|
|
321
|
+
function shallowJSONEqual(a, b) {
|
|
322
|
+
try {
|
|
323
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
324
|
+
} catch {
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
function View({ type, args, visible = true, style, className, onLoad, fallback = null }) {
|
|
329
|
+
const url = useDb((root) => root.plugin.core.lastKnownViewRegistry.find((v) => v.type === type)?.url ?? null);
|
|
330
|
+
const iframeRef = useRef(null);
|
|
331
|
+
const initialUrlRef = useRef(null);
|
|
332
|
+
const lastArgsRef = useRef(null);
|
|
333
|
+
const loadedRef = useRef(false);
|
|
334
|
+
if (initialUrlRef.current === null && url) {
|
|
335
|
+
const encoded = encodeViewArgs(args);
|
|
336
|
+
if (encoded && encoded.length > VIEW_ARGS_PARAM_LIMIT) console.warn(`[zenbu/View] args for "${type}" exceed ${VIEW_ARGS_PARAM_LIMIT} chars in URL — consider postMessage-only updates.`);
|
|
337
|
+
lastArgsRef.current = encoded;
|
|
338
|
+
initialUrlRef.current = buildViewUrl(url, type, encoded);
|
|
339
|
+
}
|
|
340
|
+
useEffect(() => {
|
|
341
|
+
if (!iframeRef.current) return;
|
|
342
|
+
const encoded = encodeViewArgs(args);
|
|
343
|
+
if (shallowJSONEqual(encoded, lastArgsRef.current)) return;
|
|
344
|
+
lastArgsRef.current = encoded;
|
|
345
|
+
const send = () => {
|
|
346
|
+
iframeRef.current?.contentWindow?.postMessage({
|
|
347
|
+
kind: VIEW_ARGS_MESSAGE_KIND,
|
|
348
|
+
args: args ?? {}
|
|
349
|
+
}, "*");
|
|
350
|
+
};
|
|
351
|
+
if (loadedRef.current) send();
|
|
352
|
+
else {
|
|
353
|
+
const iframe = iframeRef.current;
|
|
354
|
+
const onceLoaded = () => {
|
|
355
|
+
send();
|
|
356
|
+
iframe.removeEventListener("load", onceLoaded);
|
|
357
|
+
};
|
|
358
|
+
iframe.addEventListener("load", onceLoaded);
|
|
359
|
+
return () => iframe.removeEventListener("load", onceLoaded);
|
|
360
|
+
}
|
|
361
|
+
}, [args]);
|
|
362
|
+
if (!initialUrlRef.current) return createElement("span", { "data-zenbu-view-pending": type }, fallback);
|
|
363
|
+
return createElement("iframe", {
|
|
364
|
+
ref: iframeRef,
|
|
365
|
+
src: initialUrlRef.current,
|
|
366
|
+
className,
|
|
367
|
+
style: {
|
|
368
|
+
border: "none",
|
|
369
|
+
...style,
|
|
370
|
+
display: visible ? style?.display ?? "block" : "none"
|
|
371
|
+
},
|
|
372
|
+
onLoad: () => {
|
|
373
|
+
loadedRef.current = true;
|
|
374
|
+
onLoad?.();
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Read the current view args inside a child iframe rendered by `<View>`.
|
|
380
|
+
* Initial value comes from `?args=` in the iframe's URL; updates arrive
|
|
381
|
+
* via `postMessage` and re-render this hook's caller.
|
|
382
|
+
*/
|
|
383
|
+
function useViewArgs() {
|
|
384
|
+
const [args, setArgs] = useState(() => {
|
|
385
|
+
return decodeViewArgs(new URLSearchParams(typeof window !== "undefined" ? window.location.search : "").get("args"));
|
|
386
|
+
});
|
|
387
|
+
useEffect(() => {
|
|
388
|
+
const handler = (event) => {
|
|
389
|
+
if (event.source !== window.parent) return;
|
|
390
|
+
const data = event.data;
|
|
391
|
+
if (!data || typeof data !== "object") return;
|
|
392
|
+
if (data.kind !== VIEW_ARGS_MESSAGE_KIND) return;
|
|
393
|
+
const next = data.args;
|
|
394
|
+
if (next && typeof next === "object") setArgs(next);
|
|
395
|
+
};
|
|
396
|
+
window.addEventListener("message", handler);
|
|
397
|
+
return () => window.removeEventListener("message", handler);
|
|
398
|
+
}, []);
|
|
399
|
+
return args;
|
|
400
|
+
}
|
|
290
401
|
//#endregion
|
|
291
|
-
export { ZenbuProvider, useCollection, useDb, useDbClient, useEvents, useRpc };
|
|
402
|
+
export { View, ZenbuProvider, useCollection, useDb, useDbClient, useEvents, useRpc, useViewArgs };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//#region src/registry.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The registry seam.
|
|
4
|
+
*
|
|
5
|
+
* `ZenbuRegister` is the empty interface that downstream apps (and
|
|
6
|
+
* core's own `pnpm link:types` output) augment via:
|
|
7
|
+
*
|
|
8
|
+
* declare module "@zenbujs/core/registry" {
|
|
9
|
+
* interface ZenbuRegister {
|
|
10
|
+
* db: DbRoot
|
|
11
|
+
* rpc: ServiceRouter
|
|
12
|
+
* events: PluginEvents
|
|
13
|
+
* }
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* Server services (`DbService.client`, `RpcService.emit`) and renderer
|
|
17
|
+
* hooks (`useDb`, `useRpc`, `useEvents`) all read their types from
|
|
18
|
+
* `ZenbuRegister` via the `Resolved*` aliases below, so each TS program
|
|
19
|
+
* sees its own merged surface without generics at the call site.
|
|
20
|
+
*
|
|
21
|
+
* Concrete types live elsewhere:
|
|
22
|
+
* - core's published surface: `@zenbujs/core/registry-generated`
|
|
23
|
+
* (regenerated by `pnpm link:types`, shipped via tsdown -> dist/)
|
|
24
|
+
* - downstream's user-side surface: `<app>/types/services.ts` etc.
|
|
25
|
+
* (regenerated by `zen link`)
|
|
26
|
+
*
|
|
27
|
+
* registry.ts itself stays minimal on purpose: only the augmentation
|
|
28
|
+
* target + plug-and-play fallbacks. Anything more would need to be
|
|
29
|
+
* hand-maintained, and we want the link generator to be the single
|
|
30
|
+
* source of truth.
|
|
31
|
+
*
|
|
32
|
+
* Mirrors the pattern TanStack Router uses for `Register`.
|
|
33
|
+
*/
|
|
34
|
+
interface ZenbuRegister {}
|
|
35
|
+
type ResolvedDbRoot = ZenbuRegister extends {
|
|
36
|
+
db: infer T;
|
|
37
|
+
} ? T : {
|
|
38
|
+
plugin: {};
|
|
39
|
+
};
|
|
40
|
+
type ResolvedServiceRouter = ZenbuRegister extends {
|
|
41
|
+
rpc: infer T;
|
|
42
|
+
} ? T : {};
|
|
43
|
+
type ResolvedEvents = ZenbuRegister extends {
|
|
44
|
+
events: infer T;
|
|
45
|
+
} ? T : {};
|
|
46
|
+
//#endregion
|
|
47
|
+
export { ZenbuRegister as i, ResolvedEvents as n, ResolvedServiceRouter as r, ResolvedDbRoot as t };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Events } from "./events.mjs";
|
|
2
|
+
import { n as SchemaRoot } from "./schema-CjrMVk36.mjs";
|
|
3
|
+
import { c as DbService, d as ServerService, i as BaseWindowService, l as HttpService, n as WindowService, o as RendererHostService, r as RpcService, s as ViewRegistryService, t as UpdaterService, u as ReloaderService } from "./index-w5QyDjuf.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/registry-generated.d.ts
|
|
6
|
+
type ServiceBase = "evaluate" | "shutdown" | "constructor" | "effect" | "__cleanupAllEffects" | "__effectCleanups" | "ctx";
|
|
7
|
+
type ExtractRpcMethods<T> = { [K in Exclude<keyof T, ServiceBase | `_${string}`> as T[K] extends ((...args: any[]) => any) ? K : never]: T[K] };
|
|
8
|
+
type CoreServiceRouter = {
|
|
9
|
+
"base-window": ExtractRpcMethods<BaseWindowService>;
|
|
10
|
+
db: ExtractRpcMethods<DbService>;
|
|
11
|
+
http: ExtractRpcMethods<HttpService>;
|
|
12
|
+
reloader: ExtractRpcMethods<ReloaderService>;
|
|
13
|
+
"renderer-host": ExtractRpcMethods<RendererHostService>;
|
|
14
|
+
rpc: ExtractRpcMethods<RpcService>;
|
|
15
|
+
server: ExtractRpcMethods<ServerService>;
|
|
16
|
+
updater: ExtractRpcMethods<UpdaterService>;
|
|
17
|
+
"view-registry": ExtractRpcMethods<ViewRegistryService>;
|
|
18
|
+
window: ExtractRpcMethods<WindowService>;
|
|
19
|
+
};
|
|
20
|
+
type CoreEvents = Events;
|
|
21
|
+
type CoreDbSections = {
|
|
22
|
+
core: SchemaRoot;
|
|
23
|
+
};
|
|
24
|
+
type CorePreloads = {};
|
|
25
|
+
//#endregion
|
|
26
|
+
export { CoreDbSections, CoreEvents, CorePreloads, CoreServiceRouter };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/registry.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { i as ZenbuRegister, n as ResolvedEvents, r as ResolvedServiceRouter, t as ResolvedDbRoot } from "./registry-CMp8FYgS.mjs";
|
|
2
|
+
export { ResolvedDbRoot, ResolvedEvents, ResolvedServiceRouter, ZenbuRegister };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as __exportAll } from "./chunk-DsiFFCwN.mjs";
|
|
2
2
|
import { Service, runtime } from "./runtime.mjs";
|
|
3
3
|
import { t as createLogger } from "./log-6rzaCV0I.mjs";
|
|
4
|
-
import { a as zenbuVitePlugins } from "./vite-plugins-
|
|
4
|
+
import { a as zenbuVitePlugins } from "./vite-plugins-tt6KAtyE.mjs";
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path, { resolve } from "node:path";
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
@@ -113,9 +113,7 @@ async function startRendererServer(options) {
|
|
|
113
113
|
await warmupRendererEntrypoints(server, options.root);
|
|
114
114
|
return server;
|
|
115
115
|
}
|
|
116
|
-
var ReloaderService = class extends Service {
|
|
117
|
-
static key = "reloader";
|
|
118
|
-
static deps = {};
|
|
116
|
+
var ReloaderService = class extends Service.create({ key: "reloader" }) {
|
|
119
117
|
servers = /* @__PURE__ */ new Map();
|
|
120
118
|
async create(id, root, configFile) {
|
|
121
119
|
if (this.servers.has(id)) return this.servers.get(id);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as __exportAll } from "./chunk-DsiFFCwN.mjs";
|
|
2
|
-
import { Service, getAppEntrypoint, getPlugins, runtime } from "./runtime.mjs";
|
|
2
|
+
import { Service, getAppEntrypoint, getPlugins, runtime, subscribeConfig } from "./runtime.mjs";
|
|
3
3
|
import { o as getZodDefault } from "./schema-Ca7SxXgS.mjs";
|
|
4
4
|
import { schema } from "./schema.mjs";
|
|
5
5
|
import { t as createLogger } from "./log-6rzaCV0I.mjs";
|
|
6
|
-
import { t as ServerService } from "./server-
|
|
7
|
-
import { i as INTERNAL_DIR, r as DB_CONFIG_JSON, t as ReloaderService } from "./reloader-
|
|
6
|
+
import { t as ServerService } from "./server-CZLMF8Dj.mjs";
|
|
7
|
+
import { i as INTERNAL_DIR, r as DB_CONFIG_JSON, t as ReloaderService } from "./reloader-B22UiNA2.mjs";
|
|
8
8
|
import { a as createBlob, c as makeErrorAck, g as layer$1, h as writeJsonFile, i as cleanupStaleTmpFiles, l as paths, m as validateSession, n as makeRootCache, o as createCollection, p as sendAck, r as broadcastDbUpdate, s as makeAck, t as handleWrite, u as readCollectionItemRange, v as FileSystem } from "./write-DgIRjo23.mjs";
|
|
9
9
|
import { t as traceKyju } from "./trace-BaVg0rnY.mjs";
|
|
10
10
|
import { a as createClient, i as dbStringify, n as createRouter, o as createEffectClient, r as dbParse, s as createReplica } from "./transport-F2hv_OEm.mjs";
|
|
@@ -15,6 +15,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
15
15
|
import http from "node:http";
|
|
16
16
|
import fsp from "node:fs/promises";
|
|
17
17
|
import * as Effect from "effect/Effect";
|
|
18
|
+
import { subscribe } from "@parcel/watcher";
|
|
18
19
|
import * as Ref from "effect/Ref";
|
|
19
20
|
import { nanoid } from "nanoid";
|
|
20
21
|
//#region ../../node_modules/.pnpm/@effect+platform-node@0.104.1_@effect+cluster@0.56.4_@effect+platform@0.94.5_effect@3.2_4dd4c94e7ca0ae112861b6965a5da5f4/node_modules/@effect/platform-node/dist/esm/NodeFileSystem.js
|
|
@@ -801,12 +802,13 @@ async function resolveDbPath(argv, app) {
|
|
|
801
802
|
//#region src/services/http.ts
|
|
802
803
|
var http_exports = /* @__PURE__ */ __exportAll({ HttpService: () => HttpService });
|
|
803
804
|
const log$3 = createLogger("http");
|
|
804
|
-
var HttpService = class extends Service
|
|
805
|
-
|
|
806
|
-
|
|
805
|
+
var HttpService = class extends Service.create({
|
|
806
|
+
key: "http",
|
|
807
|
+
deps: {
|
|
807
808
|
server: ServerService,
|
|
808
809
|
reloader: ReloaderService
|
|
809
|
-
}
|
|
810
|
+
}
|
|
811
|
+
}) {
|
|
810
812
|
connectedCallbacks = [];
|
|
811
813
|
disconnectedCallbacks = [];
|
|
812
814
|
activeConnections = /* @__PURE__ */ new Map();
|
|
@@ -1014,7 +1016,7 @@ function resolveConfigPath() {
|
|
|
1014
1016
|
* loader-emitted barrel before any service evaluates.
|
|
1015
1017
|
*/
|
|
1016
1018
|
async function loadAppDbField(configPath) {
|
|
1017
|
-
const { loadConfig } = await import("./load-config-
|
|
1019
|
+
const { loadConfig } = await import("./load-config-C4Oe2qZO.mjs").then((n) => n.n);
|
|
1018
1020
|
const { resolved } = await loadConfig(path.dirname(configPath));
|
|
1019
1021
|
return resolved.dbPath;
|
|
1020
1022
|
}
|
|
@@ -1104,9 +1106,10 @@ async function discoverSections() {
|
|
|
1104
1106
|
for (const ptm of sorted) log$2.verbose(` ${ptm.name.padEnd(28)} total=${String(ptm.totalMs).padStart(6)} resS=${String(ptm.resolveSchemaMs).padStart(5)} impS=${String(ptm.importSchemaMs).padStart(6)} resM=${String(ptm.resolveMigrationsMs).padStart(5)} impM=${String(ptm.importMigrationsMs).padStart(6)}`);
|
|
1105
1107
|
return sections;
|
|
1106
1108
|
}
|
|
1107
|
-
var DbService = class extends Service
|
|
1108
|
-
|
|
1109
|
-
|
|
1109
|
+
var DbService = class extends Service.create({
|
|
1110
|
+
key: "db",
|
|
1111
|
+
deps: { http: HttpService }
|
|
1112
|
+
}) {
|
|
1110
1113
|
db = null;
|
|
1111
1114
|
dbRouter = null;
|
|
1112
1115
|
sectionsHash = "";
|
|
@@ -1195,6 +1198,110 @@ var DbService = class extends Service {
|
|
|
1195
1198
|
this.setup("kyju-close-on-cleanup", () => async () => {
|
|
1196
1199
|
await this.close();
|
|
1197
1200
|
});
|
|
1201
|
+
this.setup("migrations-watcher", () => {
|
|
1202
|
+
const subs = [];
|
|
1203
|
+
let closed = false;
|
|
1204
|
+
let pendingTimer = null;
|
|
1205
|
+
let inFlight = null;
|
|
1206
|
+
let queued = false;
|
|
1207
|
+
const triggerReload = async () => {
|
|
1208
|
+
if (closed) return;
|
|
1209
|
+
if (inFlight) {
|
|
1210
|
+
queued = true;
|
|
1211
|
+
return;
|
|
1212
|
+
}
|
|
1213
|
+
inFlight = runtime.reload("db").catch((err) => {
|
|
1214
|
+
log$2.error("migrations-watcher reload failed:", err);
|
|
1215
|
+
});
|
|
1216
|
+
try {
|
|
1217
|
+
await inFlight;
|
|
1218
|
+
} finally {
|
|
1219
|
+
inFlight = null;
|
|
1220
|
+
if (queued && !closed) {
|
|
1221
|
+
queued = false;
|
|
1222
|
+
scheduleReload();
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
};
|
|
1226
|
+
const scheduleReload = () => {
|
|
1227
|
+
if (closed) return;
|
|
1228
|
+
if (pendingTimer) clearTimeout(pendingTimer);
|
|
1229
|
+
pendingTimer = setTimeout(() => {
|
|
1230
|
+
pendingTimer = null;
|
|
1231
|
+
triggerReload();
|
|
1232
|
+
}, 100);
|
|
1233
|
+
};
|
|
1234
|
+
(async () => {
|
|
1235
|
+
for (const plugin of getPlugins()) {
|
|
1236
|
+
const migPath = plugin.migrationsPath;
|
|
1237
|
+
if (!migPath) continue;
|
|
1238
|
+
let isDir = false;
|
|
1239
|
+
try {
|
|
1240
|
+
isDir = (await fsp.stat(migPath)).isDirectory();
|
|
1241
|
+
} catch {
|
|
1242
|
+
continue;
|
|
1243
|
+
}
|
|
1244
|
+
if (!isDir) continue;
|
|
1245
|
+
const journalPath = path.join(migPath, "meta", "_journal.json");
|
|
1246
|
+
try {
|
|
1247
|
+
const sub = await subscribe(migPath, (err, events) => {
|
|
1248
|
+
if (err || closed) return;
|
|
1249
|
+
for (const event of events) {
|
|
1250
|
+
if (event.path === journalPath) {
|
|
1251
|
+
scheduleReload();
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
if (path.dirname(event.path) !== migPath) continue;
|
|
1255
|
+
if (event.type === "update") continue;
|
|
1256
|
+
const ext = path.extname(event.path);
|
|
1257
|
+
if (ext === ".ts" || ext === ".js" || ext === ".mjs") {
|
|
1258
|
+
scheduleReload();
|
|
1259
|
+
return;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
});
|
|
1263
|
+
if (closed) {
|
|
1264
|
+
await sub.unsubscribe().catch(() => {});
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1267
|
+
subs.push(sub);
|
|
1268
|
+
} catch (err) {
|
|
1269
|
+
log$2.error(`migrations-watcher subscribe failed for ${plugin.name}: ${err instanceof Error ? err.message : String(err)}`);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
})().catch((err) => {
|
|
1273
|
+
log$2.error("migrations-watcher setup failed:", err);
|
|
1274
|
+
});
|
|
1275
|
+
return async () => {
|
|
1276
|
+
closed = true;
|
|
1277
|
+
if (pendingTimer) {
|
|
1278
|
+
clearTimeout(pendingTimer);
|
|
1279
|
+
pendingTimer = null;
|
|
1280
|
+
}
|
|
1281
|
+
const toClose = subs.splice(0);
|
|
1282
|
+
await Promise.all(toClose.map((s) => s.unsubscribe().catch(() => {})));
|
|
1283
|
+
};
|
|
1284
|
+
});
|
|
1285
|
+
this.setup("plugin-set-watcher", () => {
|
|
1286
|
+
const fingerprint = (snap) => JSON.stringify([...snap.plugins].map((p) => ({
|
|
1287
|
+
name: p.name,
|
|
1288
|
+
schemaPath: p.schemaPath ?? null,
|
|
1289
|
+
migrationsPath: p.migrationsPath ?? null
|
|
1290
|
+
})).sort((a, b) => a.name.localeCompare(b.name)));
|
|
1291
|
+
let lastHash = null;
|
|
1292
|
+
return subscribeConfig((snap) => {
|
|
1293
|
+
const hash = fingerprint(snap);
|
|
1294
|
+
if (lastHash === null) {
|
|
1295
|
+
lastHash = hash;
|
|
1296
|
+
return;
|
|
1297
|
+
}
|
|
1298
|
+
if (hash === lastHash) return;
|
|
1299
|
+
lastHash = hash;
|
|
1300
|
+
runtime.reload("db").catch((err) => {
|
|
1301
|
+
log$2.error("plugin-set-watcher reload failed:", err);
|
|
1302
|
+
});
|
|
1303
|
+
});
|
|
1304
|
+
});
|
|
1198
1305
|
this.setup("ws-transport", () => {
|
|
1199
1306
|
const onConnected = (id, ws) => {
|
|
1200
1307
|
const dbConn = this.dbRouter.connection({
|
|
@@ -1236,68 +1343,69 @@ runtime.register(DbService, import.meta);
|
|
|
1236
1343
|
//#region src/services/view-registry.ts
|
|
1237
1344
|
var view_registry_exports = /* @__PURE__ */ __exportAll({ ViewRegistryService: () => ViewRegistryService });
|
|
1238
1345
|
const log$1 = createLogger("view-registry");
|
|
1239
|
-
var ViewRegistryService = class extends Service
|
|
1240
|
-
|
|
1241
|
-
|
|
1346
|
+
var ViewRegistryService = class extends Service.create({
|
|
1347
|
+
key: "view-registry",
|
|
1348
|
+
deps: {
|
|
1242
1349
|
reloader: ReloaderService,
|
|
1243
1350
|
db: DbService
|
|
1244
|
-
}
|
|
1351
|
+
}
|
|
1352
|
+
}) {
|
|
1245
1353
|
views = /* @__PURE__ */ new Map();
|
|
1246
1354
|
manifestIcons = /* @__PURE__ */ new Map();
|
|
1247
|
-
async register(
|
|
1248
|
-
log$1.verbose(`register("${
|
|
1249
|
-
const existing = this.views.get(
|
|
1355
|
+
async register(type, root, configFile, meta) {
|
|
1356
|
+
log$1.verbose(`register("${type}", root="${root}", config="${configFile}")`);
|
|
1357
|
+
const existing = this.views.get(type);
|
|
1250
1358
|
if (existing) {
|
|
1251
|
-
log$1.verbose(`"${
|
|
1359
|
+
log$1.verbose(`"${type}" already exists at ${existing.url}`);
|
|
1252
1360
|
return existing;
|
|
1253
1361
|
}
|
|
1254
|
-
log$1.verbose(`creating reloader for "${
|
|
1255
|
-
const reloaderEntry = await this.ctx.reloader.create(
|
|
1362
|
+
log$1.verbose(`creating reloader for "${type}"...`);
|
|
1363
|
+
const reloaderEntry = await this.ctx.reloader.create(type, root, configFile);
|
|
1256
1364
|
log$1.verbose(`reloader created: ${reloaderEntry.url} (port ${reloaderEntry.port})`);
|
|
1257
1365
|
const entry = {
|
|
1258
|
-
|
|
1366
|
+
type,
|
|
1259
1367
|
url: reloaderEntry.url,
|
|
1260
1368
|
port: reloaderEntry.port,
|
|
1261
1369
|
ownsServer: true,
|
|
1262
1370
|
meta
|
|
1263
1371
|
};
|
|
1264
|
-
this.views.set(
|
|
1372
|
+
this.views.set(type, entry);
|
|
1265
1373
|
await this.syncToDb();
|
|
1266
|
-
log$1.verbose(`"${
|
|
1374
|
+
log$1.verbose(`"${type}" registered at ${entry.url}`);
|
|
1267
1375
|
return entry;
|
|
1268
1376
|
}
|
|
1269
|
-
registerAlias(
|
|
1270
|
-
const existing = this.views.get(
|
|
1377
|
+
registerAlias(type, reloaderId, pathPrefix, meta) {
|
|
1378
|
+
const existing = this.views.get(type);
|
|
1271
1379
|
if (existing) return existing;
|
|
1272
1380
|
const reloaderEntry = this.ctx.reloader.get(reloaderId);
|
|
1273
|
-
if (!reloaderEntry) throw new Error(`Reloader "${reloaderId}" not found for alias "${
|
|
1381
|
+
if (!reloaderEntry) throw new Error(`Reloader "${reloaderId}" not found for alias "${type}"`);
|
|
1274
1382
|
const entry = {
|
|
1275
|
-
|
|
1383
|
+
type,
|
|
1276
1384
|
url: `${reloaderEntry.url}${pathPrefix}`,
|
|
1277
1385
|
port: reloaderEntry.port,
|
|
1278
1386
|
ownsServer: false,
|
|
1279
1387
|
meta
|
|
1280
1388
|
};
|
|
1281
|
-
this.views.set(
|
|
1389
|
+
this.views.set(type, entry);
|
|
1282
1390
|
this.syncToDb();
|
|
1283
1391
|
return entry;
|
|
1284
1392
|
}
|
|
1285
|
-
async unregister(
|
|
1286
|
-
const entry = this.views.get(
|
|
1393
|
+
async unregister(type) {
|
|
1394
|
+
const entry = this.views.get(type);
|
|
1287
1395
|
if (!entry) return;
|
|
1288
|
-
if (entry.ownsServer) await this.ctx.reloader.remove(
|
|
1289
|
-
this.views.delete(
|
|
1396
|
+
if (entry.ownsServer) await this.ctx.reloader.remove(type);
|
|
1397
|
+
this.views.delete(type);
|
|
1290
1398
|
await this.syncToDb();
|
|
1291
1399
|
}
|
|
1292
|
-
get(
|
|
1293
|
-
return this.views.get(
|
|
1400
|
+
get(type) {
|
|
1401
|
+
return this.views.get(type);
|
|
1294
1402
|
}
|
|
1295
1403
|
evaluate() {
|
|
1296
1404
|
this.loadManifestIcons();
|
|
1297
1405
|
this.syncToDb();
|
|
1298
1406
|
this.setup("view-registry-cleanup", () => {
|
|
1299
1407
|
return async () => {
|
|
1300
|
-
for (const [
|
|
1408
|
+
for (const [type, entry] of this.views) if (entry.ownsServer) await this.ctx.reloader.remove(type);
|
|
1301
1409
|
this.views.clear();
|
|
1302
1410
|
await this.syncToDb();
|
|
1303
1411
|
};
|
|
@@ -1307,16 +1415,16 @@ var ViewRegistryService = class extends Service {
|
|
|
1307
1415
|
this.manifestIcons.clear();
|
|
1308
1416
|
for (const plugin of getPlugins()) {
|
|
1309
1417
|
if (!plugin.icons) continue;
|
|
1310
|
-
for (const [
|
|
1418
|
+
for (const [type, svg] of Object.entries(plugin.icons)) this.manifestIcons.set(type, svg);
|
|
1311
1419
|
}
|
|
1312
1420
|
}
|
|
1313
1421
|
async syncToDb() {
|
|
1314
1422
|
const client = this.ctx.db.effectClient;
|
|
1315
1423
|
const snapshot = [...this.views.values()].map((e) => ({
|
|
1316
|
-
|
|
1424
|
+
type: e.type,
|
|
1317
1425
|
url: e.url,
|
|
1318
1426
|
port: e.port,
|
|
1319
|
-
icon: this.manifestIcons.get(e.
|
|
1427
|
+
icon: this.manifestIcons.get(e.type),
|
|
1320
1428
|
meta: e.meta
|
|
1321
1429
|
}));
|
|
1322
1430
|
await Effect.runPromise(client.update((root) => {
|
|
@@ -1361,12 +1469,13 @@ async function resolveRendererRoot() {
|
|
|
1361
1469
|
configFile: await pathExists(viteConfig) ? viteConfig : false
|
|
1362
1470
|
};
|
|
1363
1471
|
}
|
|
1364
|
-
var RendererHostService = class extends Service
|
|
1365
|
-
|
|
1366
|
-
|
|
1472
|
+
var RendererHostService = class extends Service.create({
|
|
1473
|
+
key: "renderer-host",
|
|
1474
|
+
deps: {
|
|
1367
1475
|
reloader: ReloaderService,
|
|
1368
1476
|
viewRegistry: ViewRegistryService
|
|
1369
|
-
}
|
|
1477
|
+
}
|
|
1478
|
+
}) {
|
|
1370
1479
|
url = "";
|
|
1371
1480
|
port = 0;
|
|
1372
1481
|
async evaluate() {
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { n as __exportAll } from "./chunk-DsiFFCwN.mjs";
|
|
2
2
|
import { Service, runtime } from "./runtime.mjs";
|
|
3
3
|
import { t as createLogger } from "./log-6rzaCV0I.mjs";
|
|
4
|
-
import { s as HttpService } from "./renderer-host-
|
|
4
|
+
import { s as HttpService } from "./renderer-host-DD16MXhI.mjs";
|
|
5
5
|
import { n as createRpcRouter, r as createServer } from "./src-Cven45mq.mjs";
|
|
6
6
|
//#region src/services/rpc.ts
|
|
7
7
|
var rpc_exports = /* @__PURE__ */ __exportAll({ RpcService: () => RpcService });
|
|
8
8
|
const log = createLogger("rpc");
|
|
9
|
-
var RpcService = class extends Service
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
var RpcService = class extends Service.create({
|
|
10
|
+
key: "rpc",
|
|
11
|
+
deps: { http: HttpService }
|
|
12
|
+
}) {
|
|
12
13
|
_emit = null;
|
|
13
14
|
get emit() {
|
|
14
15
|
if (!this._emit) throw new Error("RpcService not yet evaluated");
|