@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
@@ -0,0 +1,1045 @@
1
+ import { t as traceKyju } from "./trace-DCB7qFzT.mjs";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Ref from "effect/Ref";
4
+ import * as Context from "effect/Context";
5
+ import * as Stream from "effect/Stream";
6
+ import { nanoid } from "nanoid";
7
+ import * as Fiber from "effect/Fiber";
8
+ import * as SubscriptionRef from "effect/SubscriptionRef";
9
+ //#region ../kyju/src/v2/shared.ts
10
+ const SendContext = Context.GenericTag("SendContext");
11
+ const ClientStateRef = Context.GenericTag("ClientStateRef");
12
+ const MaxPageSizeContext = Context.GenericTag("MaxPageSizeContext");
13
+ //#endregion
14
+ //#region ../kyju/src/v2/replica/helpers.ts
15
+ const makeRequestAwaiter = () => {
16
+ const pending = /* @__PURE__ */ new Map();
17
+ return {
18
+ resolve: (ack) => {
19
+ const entry = pending.get(ack.requestId);
20
+ if (entry) {
21
+ pending.delete(ack.requestId);
22
+ entry.resolve(ack);
23
+ }
24
+ },
25
+ await: (requestId) => new Promise((resolve) => {
26
+ pending.set(requestId, {
27
+ requestId,
28
+ resolve
29
+ });
30
+ })
31
+ };
32
+ };
33
+ const setAtPath = ({ root, path, value }) => {
34
+ if (path.length === 0) return value;
35
+ const [head, ...rest] = path;
36
+ const isIndex = /^\d+$/.test(head);
37
+ if (Array.isArray(root)) {
38
+ /**
39
+ * so react observes a new reference
40
+ */
41
+ const arr = [...root];
42
+ const index = Number(head);
43
+ if (rest.length === 0) {
44
+ arr[index] = value;
45
+ return arr;
46
+ }
47
+ arr[index] = setAtPath({
48
+ root: arr[index] ?? (/^\d+$/.test(rest[0] ?? "") ? [] : {}),
49
+ path: rest,
50
+ value
51
+ });
52
+ return arr;
53
+ }
54
+ if (typeof root !== "object" || root === null) root = isIndex ? [] : {};
55
+ if (Array.isArray(root)) {
56
+ const arr = [...root];
57
+ const index = Number(head);
58
+ if (rest.length === 0) {
59
+ arr[index] = value;
60
+ return arr;
61
+ }
62
+ arr[index] = setAtPath({
63
+ root: arr[index] ?? (/^\d+$/.test(rest[0] ?? "") ? [] : {}),
64
+ path: rest,
65
+ value
66
+ });
67
+ return arr;
68
+ }
69
+ const obj = { ...root };
70
+ if (rest.length === 0) {
71
+ obj[head] = value;
72
+ return obj;
73
+ }
74
+ obj[head] = setAtPath({
75
+ root: obj[head] ?? (/^\d+$/.test(rest[0] ?? "") ? [] : {}),
76
+ path: rest,
77
+ value
78
+ });
79
+ return obj;
80
+ };
81
+ const requireConnected = ({ ref }) => Effect.gen(function* () {
82
+ const state = yield* Ref.get(ref);
83
+ if (state.kind === "disconnected") return yield* Effect.die("Cannot process event: not connected");
84
+ return state;
85
+ });
86
+ const applyState = ({ ref, fn }) => Ref.update(ref, (current) => {
87
+ if (current.kind === "disconnected") return current;
88
+ return fn(current);
89
+ });
90
+ //#endregion
91
+ //#region ../kyju/src/v2/replica/replica.ts
92
+ const concatToCollection = (col, items) => {
93
+ if (items.length === 0) return col;
94
+ return {
95
+ ...col,
96
+ items: [...col.items, ...items],
97
+ totalCount: col.totalCount + items.length
98
+ };
99
+ };
100
+ const applyRootSet = (ref, op) => applyState({
101
+ ref,
102
+ fn: (state) => ({
103
+ ...state,
104
+ root: setAtPath({
105
+ root: state.root,
106
+ path: op.path,
107
+ value: op.value
108
+ })
109
+ })
110
+ });
111
+ const applyCollectionCreate = (ref, op) => {
112
+ const collection = {
113
+ id: op.collectionId,
114
+ totalCount: op.data?.length ?? 0,
115
+ items: op.data ?? []
116
+ };
117
+ return applyState({
118
+ ref,
119
+ fn: (state) => ({
120
+ ...state,
121
+ collections: [...state.collections, collection]
122
+ })
123
+ });
124
+ };
125
+ const applyCollectionDelete = (ref, op) => applyState({
126
+ ref,
127
+ fn: (state) => ({
128
+ ...state,
129
+ collections: state.collections.filter((col) => col.id !== op.collectionId)
130
+ })
131
+ });
132
+ const applyBlobCreate = (ref, op) => {
133
+ const blob = {
134
+ id: op.blobId,
135
+ data: op.hot ? {
136
+ kind: "hot",
137
+ value: op.data
138
+ } : { kind: "cold" },
139
+ fileSize: 0
140
+ };
141
+ return applyState({
142
+ ref,
143
+ fn: (state) => ({
144
+ ...state,
145
+ blobs: [...state.blobs, blob]
146
+ })
147
+ });
148
+ };
149
+ const applyBlobSet = (ref, op) => applyState({
150
+ ref,
151
+ fn: (state) => ({
152
+ ...state,
153
+ blobs: state.blobs.map((blob) => {
154
+ if (blob.id !== op.blobId) return blob;
155
+ if (blob.data.kind === "hot") return {
156
+ ...blob,
157
+ data: {
158
+ kind: "hot",
159
+ value: op.data
160
+ }
161
+ };
162
+ return blob;
163
+ })
164
+ })
165
+ });
166
+ const applyBlobDelete = (ref, op) => applyState({
167
+ ref,
168
+ fn: (state) => ({
169
+ ...state,
170
+ blobs: state.blobs.filter((blob) => blob.id !== op.blobId)
171
+ })
172
+ });
173
+ const applyWrite = ({ stateRef, op }) => {
174
+ switch (op.type) {
175
+ case "root.set": return applyRootSet(stateRef, op);
176
+ case "collection.create": return applyCollectionCreate(stateRef, op);
177
+ case "collection.concat": return applyState({
178
+ ref: stateRef,
179
+ fn: (state) => ({
180
+ ...state,
181
+ collections: state.collections.map((col) => col.id === op.collectionId ? concatToCollection(col, op.data) : col)
182
+ })
183
+ });
184
+ case "collection.delete": return applyCollectionDelete(stateRef, op);
185
+ case "blob.create": return applyBlobCreate(stateRef, op);
186
+ case "blob.set": return applyBlobSet(stateRef, op);
187
+ case "blob.delete": return applyBlobDelete(stateRef, op);
188
+ }
189
+ };
190
+ const applyReplicatedWrite = ({ stateRef, op }) => {
191
+ switch (op.type) {
192
+ case "root.set": return applyRootSet(stateRef, op);
193
+ case "collection.create": return applyCollectionCreate(stateRef, op);
194
+ case "collection.concat": return applyState({
195
+ ref: stateRef,
196
+ fn: (state) => ({
197
+ ...state,
198
+ collections: state.collections.map((col) => {
199
+ if (col.id !== op.collectionId) return col;
200
+ return concatToCollection(col, op.data);
201
+ })
202
+ })
203
+ });
204
+ case "collection.delete": return applyCollectionDelete(stateRef, op);
205
+ case "blob.create": return applyBlobCreate(stateRef, op);
206
+ case "blob.set": return applyBlobSet(stateRef, op);
207
+ case "blob.delete": return applyBlobDelete(stateRef, op);
208
+ }
209
+ };
210
+ const createReplicaEffect = (replicaId, collectionCallbacks) => Effect.gen(function* () {
211
+ const awaiter = makeRequestAwaiter();
212
+ const stateRef = yield* ClientStateRef;
213
+ const sendToServer = (event, requestId) => Effect.gen(function* () {
214
+ const { send } = yield* SendContext;
215
+ const promise = awaiter.await(requestId);
216
+ send(event);
217
+ return yield* Effect.promise(() => promise);
218
+ });
219
+ const mergeSubscribeAck = (ack, collectionId) => applyState({
220
+ ref: stateRef,
221
+ fn: (state) => {
222
+ const entry = {
223
+ id: collectionId,
224
+ totalCount: ack.totalCount,
225
+ items: ack.items
226
+ };
227
+ const exists = state.collections.some((col) => col.id === collectionId);
228
+ return {
229
+ ...state,
230
+ collections: exists ? state.collections.map((col) => col.id === collectionId ? entry : col) : [...state.collections, entry]
231
+ };
232
+ }
233
+ });
234
+ const notifyConcatCallbacks = (op) => Effect.gen(function* () {
235
+ if (op.type !== "collection.concat") return;
236
+ const cbs = collectionCallbacks.get(op.collectionId);
237
+ if (!cbs || cbs.size === 0) return;
238
+ const currentState = yield* Ref.get(stateRef);
239
+ if (currentState.kind !== "connected") return;
240
+ const col = currentState.collections.find((c) => c.id === op.collectionId);
241
+ if (!col) return;
242
+ for (const cb of cbs) cb({
243
+ collectionId: op.collectionId,
244
+ newItems: op.data,
245
+ collection: col
246
+ });
247
+ });
248
+ const postMessage = (event) => Effect.gen(function* () {
249
+ switch (event.kind) {
250
+ case "connect": {
251
+ const requestId = nanoid();
252
+ const ack = yield* sendToServer({
253
+ kind: "connect",
254
+ message: {
255
+ type: "connect",
256
+ version: event.version,
257
+ requestId,
258
+ replicaId
259
+ }
260
+ }, requestId);
261
+ if (ack.error) return yield* Effect.fail(ack.error);
262
+ yield* Ref.set(stateRef, {
263
+ kind: "connected",
264
+ sessionId: ack.sessionId,
265
+ root: ack.root,
266
+ collections: [],
267
+ blobs: []
268
+ });
269
+ return;
270
+ }
271
+ case "disconnect": {
272
+ const state = yield* requireConnected({ ref: stateRef });
273
+ const requestId = nanoid();
274
+ const ack = yield* sendToServer({
275
+ kind: "disconnect",
276
+ replicaId,
277
+ message: {
278
+ type: "disconnect",
279
+ sessionId: state.sessionId,
280
+ requestId
281
+ }
282
+ }, requestId);
283
+ if (ack.error) return yield* Effect.fail(ack.error);
284
+ yield* Ref.set(stateRef, { kind: "disconnected" });
285
+ return;
286
+ }
287
+ case "subscribe-collection": {
288
+ const state = yield* requireConnected({ ref: stateRef });
289
+ const requestId = nanoid();
290
+ const ack = yield* sendToServer({
291
+ kind: "subscribe-collection",
292
+ collectionId: event.collectionId,
293
+ sessionId: state.sessionId,
294
+ requestId,
295
+ replicaId
296
+ }, requestId);
297
+ if (ack.error) return yield* Effect.fail(ack.error);
298
+ yield* mergeSubscribeAck(ack, event.collectionId);
299
+ return;
300
+ }
301
+ case "unsubscribe-collection": {
302
+ const state = yield* requireConnected({ ref: stateRef });
303
+ const requestId = nanoid();
304
+ yield* sendToServer({
305
+ kind: "unsubscribe-collection",
306
+ collectionId: event.collectionId,
307
+ sessionId: state.sessionId,
308
+ requestId,
309
+ replicaId
310
+ }, requestId);
311
+ yield* applyState({
312
+ ref: stateRef,
313
+ fn: (s) => ({
314
+ ...s,
315
+ collections: s.collections.filter((col) => col.id !== event.collectionId)
316
+ })
317
+ });
318
+ return;
319
+ }
320
+ case "write": {
321
+ const state = yield* requireConnected({ ref: stateRef });
322
+ yield* traceKyju("kyju:replica.applyWrite", applyWrite({
323
+ stateRef,
324
+ op: event.op
325
+ }), { op: event.op.type });
326
+ yield* notifyConcatCallbacks(event.op);
327
+ const writeRequestId = nanoid();
328
+ const writeAck = yield* traceKyju("kyju:replica.sendToServer", sendToServer({
329
+ kind: "write",
330
+ op: event.op,
331
+ sessionId: state.sessionId,
332
+ requestId: writeRequestId,
333
+ replicaId
334
+ }, writeRequestId), { op: event.op.type });
335
+ if (writeAck.error) return yield* Effect.fail(writeAck.error);
336
+ return;
337
+ }
338
+ case "replicated-write":
339
+ yield* requireConnected({ ref: stateRef });
340
+ yield* applyReplicatedWrite({
341
+ stateRef,
342
+ op: event.op
343
+ });
344
+ yield* notifyConcatCallbacks(event.op);
345
+ return;
346
+ case "read": {
347
+ const readState = yield* requireConnected({ ref: stateRef });
348
+ const readRequestId = nanoid();
349
+ const readOp = event.op;
350
+ switch (readOp.type) {
351
+ case "collection.fetch-range":
352
+ yield* sendToServer({
353
+ kind: "read",
354
+ op: readOp,
355
+ sessionId: readState.sessionId,
356
+ requestId: readRequestId,
357
+ replicaId
358
+ }, readRequestId);
359
+ return;
360
+ case "blob.read": {
361
+ const ack = yield* sendToServer({
362
+ kind: "read",
363
+ op: readOp,
364
+ sessionId: readState.sessionId,
365
+ requestId: readRequestId,
366
+ replicaId
367
+ }, readRequestId);
368
+ if (ack.error) return yield* Effect.fail(ack.error);
369
+ yield* applyState({
370
+ ref: stateRef,
371
+ fn: (state) => {
372
+ const entry = {
373
+ id: readOp.blobId,
374
+ data: {
375
+ kind: "hot",
376
+ value: ack.data
377
+ },
378
+ fileSize: 0
379
+ };
380
+ const exists = state.blobs.some((b) => b.id === readOp.blobId);
381
+ return {
382
+ ...state,
383
+ blobs: exists ? state.blobs.map((b) => b.id === readOp.blobId ? entry : b) : [...state.blobs, entry]
384
+ };
385
+ }
386
+ });
387
+ return;
388
+ }
389
+ }
390
+ }
391
+ case "db-update": {
392
+ const msg = event.message;
393
+ if (msg.type === "ack") {
394
+ awaiter.resolve(msg);
395
+ return;
396
+ }
397
+ yield* requireConnected({ ref: stateRef });
398
+ switch (msg.type) {
399
+ case "blob.metadataUpdate":
400
+ yield* applyState({
401
+ ref: stateRef,
402
+ fn: (state) => ({
403
+ ...state,
404
+ blobs: state.blobs.map((blob) => blob.id === msg.blobId ? {
405
+ ...blob,
406
+ fileSize: msg.fileSize
407
+ } : blob)
408
+ })
409
+ });
410
+ return;
411
+ case "reconnect": {
412
+ const reconState = yield* requireConnected({ ref: stateRef });
413
+ const disconnectId = nanoid();
414
+ const disconnectAck = yield* sendToServer({
415
+ kind: "disconnect",
416
+ replicaId,
417
+ message: {
418
+ type: "disconnect",
419
+ sessionId: reconState.sessionId,
420
+ requestId: disconnectId
421
+ }
422
+ }, disconnectId);
423
+ if (disconnectAck.error) return yield* Effect.fail(disconnectAck.error);
424
+ yield* Ref.set(stateRef, { kind: "disconnected" });
425
+ const connectId = nanoid();
426
+ const connectAck = yield* sendToServer({
427
+ kind: "connect",
428
+ message: {
429
+ type: "connect",
430
+ version: 0,
431
+ requestId: connectId,
432
+ replicaId
433
+ }
434
+ }, connectId);
435
+ if (connectAck.error) return yield* Effect.fail(connectAck.error);
436
+ yield* Ref.set(stateRef, {
437
+ kind: "connected",
438
+ sessionId: connectAck.sessionId,
439
+ root: connectAck.root,
440
+ collections: [],
441
+ blobs: []
442
+ });
443
+ return;
444
+ }
445
+ }
446
+ }
447
+ }
448
+ });
449
+ return { postMessage };
450
+ });
451
+ const createReplica = (args) => {
452
+ const replicaId = args.replicaId ?? nanoid();
453
+ const stateRef = Effect.runSync(SubscriptionRef.make({ kind: "disconnected" }));
454
+ const collectionCallbacks = /* @__PURE__ */ new Map();
455
+ const provide = (effect) => effect.pipe(Effect.provideService(SendContext, { send: args.send }), Effect.provideService(ClientStateRef, stateRef), Effect.provideService(MaxPageSizeContext, { maxPageSizeBytes: args.maxPageSizeBytes }));
456
+ const { postMessage: rawPostMessageEffect } = Effect.runSync(provide(createReplicaEffect(replicaId, collectionCallbacks)));
457
+ const postMessageEffect = (event) => provide(rawPostMessageEffect(event));
458
+ const postMessage = (event) => Effect.runPromise(postMessageEffect(event).pipe(Effect.catchAll(() => Effect.void)));
459
+ const onCollectionConcat = (collectionId, cb) => {
460
+ let cbs = collectionCallbacks.get(collectionId);
461
+ if (!cbs) {
462
+ cbs = /* @__PURE__ */ new Set();
463
+ collectionCallbacks.set(collectionId, cbs);
464
+ }
465
+ cbs.add(cb);
466
+ };
467
+ const offCollectionConcat = (collectionId, cb) => {
468
+ const cbs = collectionCallbacks.get(collectionId);
469
+ if (cbs) {
470
+ cbs.delete(cb);
471
+ if (cbs.size === 0) collectionCallbacks.delete(collectionId);
472
+ }
473
+ };
474
+ const getState = () => Effect.runSync(Ref.get(stateRef));
475
+ const _forceState = (state) => {
476
+ Effect.runSync(Ref.set(stateRef, state));
477
+ };
478
+ const subscribe = (cb) => {
479
+ const fiber = Effect.runFork(Stream.runForEach(stateRef.changes, (state) => Effect.sync(() => cb(state))));
480
+ return () => {
481
+ Effect.runFork(Fiber.interrupt(fiber));
482
+ };
483
+ };
484
+ return {
485
+ postMessage,
486
+ postMessageEffect,
487
+ getState,
488
+ _forceState,
489
+ subscribe,
490
+ replicaId,
491
+ onCollectionConcat,
492
+ offCollectionConcat
493
+ };
494
+ };
495
+ //#endregion
496
+ //#region ../kyju/src/v2/client/proxy.ts
497
+ /**
498
+ *
499
+ * we are recording the set of operations performed on a proxy object,
500
+ * so that we can later play them over and convert them into events
501
+ * to the kyju db
502
+ *
503
+ */
504
+ const createRecordingProxy = (target) => {
505
+ const operations = [];
506
+ const dirtyArrayPaths = /* @__PURE__ */ new Map();
507
+ const markArrayDirty = (arrayPath, arr) => {
508
+ const key = arrayPath.join("\0");
509
+ if (!dirtyArrayPaths.has(key)) dirtyArrayPaths.set(key, {
510
+ path: arrayPath,
511
+ arr
512
+ });
513
+ };
514
+ const makeProxy = (obj, currentPath) => {
515
+ return new Proxy(obj, {
516
+ get(t, prop, receiver) {
517
+ if (typeof prop === "symbol") return Reflect.get(t, prop, receiver);
518
+ const value = t[prop];
519
+ if (value !== null && typeof value === "object") return makeProxy(value, [...currentPath, prop]);
520
+ return value;
521
+ },
522
+ set(t, prop, value) {
523
+ if (typeof prop === "symbol") {
524
+ t[prop] = value;
525
+ return true;
526
+ }
527
+ t[prop] = value;
528
+ if (Array.isArray(t)) markArrayDirty(currentPath, t);
529
+ else operations.push({
530
+ path: [...currentPath, prop],
531
+ value
532
+ });
533
+ return true;
534
+ }
535
+ });
536
+ };
537
+ const snapshot = JSON.parse(JSON.stringify(target));
538
+ return {
539
+ proxy: makeProxy(snapshot, []),
540
+ getOperations: () => {
541
+ const result = [...operations];
542
+ for (const { path, arr } of dirtyArrayPaths.values()) result.push({
543
+ path,
544
+ value: arr
545
+ });
546
+ return result;
547
+ },
548
+ snapshot
549
+ };
550
+ };
551
+ //#endregion
552
+ //#region ../kyju/src/v2/client/client.ts
553
+ function createClientCore(send, replica) {
554
+ const subscriberCounts = /* @__PURE__ */ new Map();
555
+ const subscribePromises = /* @__PURE__ */ new Map();
556
+ const getConnectedState = () => {
557
+ const state = replica.getState();
558
+ if (state.kind === "disconnected") throw new Error("Cannot read state: not connected");
559
+ return state;
560
+ };
561
+ const getRoot = () => getConnectedState().root;
562
+ const getAtPath = (obj, path) => {
563
+ let current = obj;
564
+ for (const key of path) {
565
+ if (current == null) return void 0;
566
+ current = current[key];
567
+ }
568
+ return current;
569
+ };
570
+ const isCollectionValue = (val) => val != null && typeof val === "object" && "collectionId" in val;
571
+ const isBlobValue = (val) => val != null && typeof val === "object" && "blobId" in val;
572
+ const subscribeToPath = (path, cb) => {
573
+ let prev;
574
+ let initialized = false;
575
+ return replica.subscribe((state) => {
576
+ if (state.kind === "disconnected") return;
577
+ const value = getAtPath(state.root, path);
578
+ if (!initialized || !Object.is(prev, value)) {
579
+ prev = value;
580
+ initialized = true;
581
+ cb(value);
582
+ }
583
+ });
584
+ };
585
+ const makeCollectionNode = (fieldKey) => {
586
+ const getCollectionId = () => {
587
+ return getAtPath(getRoot(), [fieldKey])?.collectionId;
588
+ };
589
+ return {
590
+ concat: (items) => {
591
+ return send({
592
+ kind: "write",
593
+ op: {
594
+ type: "collection.concat",
595
+ collectionId: getCollectionId(),
596
+ data: items
597
+ }
598
+ });
599
+ },
600
+ read: (range) => send({
601
+ kind: "read",
602
+ op: {
603
+ type: "collection.fetch-range",
604
+ collectionId: getCollectionId(),
605
+ range: range ?? {
606
+ start: 0,
607
+ end: Number.MAX_SAFE_INTEGER
608
+ }
609
+ }
610
+ }),
611
+ create: (data) => Effect.gen(function* () {
612
+ const collectionId = nanoid();
613
+ yield* send({
614
+ kind: "write",
615
+ op: {
616
+ type: "collection.create",
617
+ collectionId,
618
+ data
619
+ }
620
+ });
621
+ yield* send({
622
+ kind: "write",
623
+ op: {
624
+ type: "root.set",
625
+ path: [fieldKey],
626
+ value: {
627
+ collectionId,
628
+ debugName: fieldKey
629
+ }
630
+ }
631
+ });
632
+ }),
633
+ delete: () => send({
634
+ kind: "write",
635
+ op: {
636
+ type: "collection.delete",
637
+ collectionId: getCollectionId()
638
+ }
639
+ }),
640
+ subscribe: (cb) => subscribeToPath([fieldKey], cb),
641
+ subscribeData: (cb) => makeCollectionNodeAtPath([fieldKey]).subscribeData(cb)
642
+ };
643
+ };
644
+ const makeCollectionNodeAtPath = (path) => {
645
+ const getCollectionId = () => {
646
+ return getAtPath(getRoot(), path)?.collectionId;
647
+ };
648
+ return {
649
+ concat: (items) => send({
650
+ kind: "write",
651
+ op: {
652
+ type: "collection.concat",
653
+ collectionId: getCollectionId(),
654
+ data: items
655
+ }
656
+ }),
657
+ read: (range) => send({
658
+ kind: "read",
659
+ op: {
660
+ type: "collection.fetch-range",
661
+ collectionId: getCollectionId(),
662
+ range: range ?? {
663
+ start: 0,
664
+ end: Number.MAX_SAFE_INTEGER
665
+ }
666
+ }
667
+ }),
668
+ create: (data) => Effect.gen(function* () {
669
+ const collectionId = nanoid();
670
+ yield* send({
671
+ kind: "write",
672
+ op: {
673
+ type: "collection.create",
674
+ collectionId,
675
+ data
676
+ }
677
+ });
678
+ yield* send({
679
+ kind: "write",
680
+ op: {
681
+ type: "root.set",
682
+ path,
683
+ value: {
684
+ collectionId,
685
+ debugName: path[path.length - 1] ?? ""
686
+ }
687
+ }
688
+ });
689
+ }),
690
+ delete: () => send({
691
+ kind: "write",
692
+ op: {
693
+ type: "collection.delete",
694
+ collectionId: getCollectionId()
695
+ }
696
+ }),
697
+ subscribe: (cb) => subscribeToPath(path, cb),
698
+ subscribeData: (cb) => {
699
+ const collectionId = getCollectionId();
700
+ const count = subscriberCounts.get(collectionId) ?? 0;
701
+ subscriberCounts.set(collectionId, count + 1);
702
+ const wrappedCb = (data) => {
703
+ cb({
704
+ collection: data.collection,
705
+ newItems: data.newItems
706
+ });
707
+ };
708
+ replica.onCollectionConcat(collectionId, wrappedCb);
709
+ const deliverInitial = () => {
710
+ const state = replica.getState();
711
+ if (state.kind === "connected") {
712
+ const col = state.collections.find((c) => c.id === collectionId);
713
+ if (col) cb({
714
+ collection: col,
715
+ newItems: col.items
716
+ });
717
+ }
718
+ };
719
+ if (count === 0) {
720
+ const p = Effect.runPromise(send({
721
+ kind: "subscribe-collection",
722
+ collectionId
723
+ }).pipe(Effect.catchAll(() => Effect.void))).then(deliverInitial);
724
+ subscribePromises.set(collectionId, p);
725
+ } else {
726
+ const existing = subscribePromises.get(collectionId);
727
+ if (existing) existing.then(deliverInitial);
728
+ else deliverInitial();
729
+ }
730
+ let unsubscribed = false;
731
+ return () => {
732
+ if (unsubscribed) return;
733
+ unsubscribed = true;
734
+ replica.offCollectionConcat(collectionId, wrappedCb);
735
+ const current = subscriberCounts.get(collectionId) ?? 1;
736
+ if (current <= 1) {
737
+ subscriberCounts.delete(collectionId);
738
+ subscribePromises.delete(collectionId);
739
+ Effect.runPromise(send({
740
+ kind: "unsubscribe-collection",
741
+ collectionId
742
+ }).pipe(Effect.catchAll(() => Effect.void)));
743
+ } else subscriberCounts.set(collectionId, current - 1);
744
+ };
745
+ }
746
+ };
747
+ };
748
+ const makeBlobNode = (fieldKey) => {
749
+ const getBlobId = () => {
750
+ return getAtPath(getRoot(), [fieldKey])?.blobId;
751
+ };
752
+ return {
753
+ read: () => send({
754
+ kind: "read",
755
+ op: {
756
+ type: "blob.read",
757
+ blobId: getBlobId()
758
+ }
759
+ }),
760
+ set: (data) => send({
761
+ kind: "write",
762
+ op: {
763
+ type: "blob.set",
764
+ blobId: getBlobId(),
765
+ data
766
+ }
767
+ }),
768
+ create: (data, hot) => Effect.gen(function* () {
769
+ const blobId = nanoid();
770
+ yield* send({
771
+ kind: "write",
772
+ op: {
773
+ type: "blob.create",
774
+ blobId,
775
+ data,
776
+ hot
777
+ }
778
+ });
779
+ yield* send({
780
+ kind: "write",
781
+ op: {
782
+ type: "root.set",
783
+ path: [fieldKey],
784
+ value: {
785
+ blobId,
786
+ debugName: fieldKey
787
+ }
788
+ }
789
+ });
790
+ }),
791
+ delete: () => send({
792
+ kind: "write",
793
+ op: {
794
+ type: "blob.delete",
795
+ blobId: getBlobId()
796
+ }
797
+ })
798
+ };
799
+ };
800
+ const ARRAY_READ_METHODS = new Set([
801
+ "map",
802
+ "filter",
803
+ "slice",
804
+ "flatMap",
805
+ "reduce",
806
+ "reduceRight",
807
+ "forEach",
808
+ "some",
809
+ "every",
810
+ "indexOf",
811
+ "includes",
812
+ "join",
813
+ "findIndex",
814
+ "keys",
815
+ "values",
816
+ "entries",
817
+ "flat",
818
+ "toString"
819
+ ]);
820
+ const makeFieldNode = (path) => new Proxy({}, { get(_, prop) {
821
+ if (typeof prop === "symbol") {
822
+ const val = getAtPath(getRoot(), path);
823
+ if (Array.isArray(val) && prop === Symbol.iterator) return val[Symbol.iterator].bind(val);
824
+ return;
825
+ }
826
+ const val = getAtPath(getRoot(), path);
827
+ if (isCollectionValue(val)) {
828
+ const node = makeCollectionNodeAtPath(path);
829
+ if (prop in node || prop === "concat" || prop === "subscribeData" || prop === "read" || prop === "create" || prop === "delete" || prop === "subscribe") return node[prop];
830
+ }
831
+ if (Array.isArray(val)) switch (prop) {
832
+ case "read": return () => val;
833
+ case "set": return (value) => send({
834
+ kind: "write",
835
+ op: {
836
+ type: "root.set",
837
+ path,
838
+ value
839
+ }
840
+ });
841
+ case "subscribe": return (cb) => subscribeToPath(path, cb);
842
+ case "length": return val.length;
843
+ case "find": return (predicate) => {
844
+ const index = val.findIndex(predicate);
845
+ if (index < 0) return void 0;
846
+ return makeFieldNode([...path, String(index)]);
847
+ };
848
+ case "at": return (i) => {
849
+ const resolved = i < 0 ? val.length + i : i;
850
+ if (resolved < 0 || resolved >= val.length) return void 0;
851
+ return makeFieldNode([...path, String(resolved)]);
852
+ };
853
+ default:
854
+ if (ARRAY_READ_METHODS.has(prop)) return Array.prototype[prop].bind(val);
855
+ if (/^\d+$/.test(prop)) return makeFieldNode([...path, prop]);
856
+ return makeFieldNode([...path, prop]);
857
+ }
858
+ switch (prop) {
859
+ case "read": return () => val;
860
+ case "set": return (value) => send({
861
+ kind: "write",
862
+ op: {
863
+ type: "root.set",
864
+ path,
865
+ value
866
+ }
867
+ });
868
+ case "subscribe": return (cb) => subscribeToPath(path, cb);
869
+ default: return makeFieldNode([...path, prop]);
870
+ }
871
+ } });
872
+ const readRootFn = () => getRoot();
873
+ const updateFn = (fn) => traceKyju("kyju:client.update", Effect.gen(function* () {
874
+ const { proxy, getOperations } = createRecordingProxy(getRoot());
875
+ const result = fn(proxy);
876
+ if (result !== void 0) yield* send({
877
+ kind: "write",
878
+ op: {
879
+ type: "root.set",
880
+ path: [],
881
+ value: result
882
+ }
883
+ });
884
+ else {
885
+ const ops = getOperations();
886
+ for (const op of ops) yield* send({
887
+ kind: "write",
888
+ op: {
889
+ type: "root.set",
890
+ path: op.path,
891
+ value: op.value
892
+ }
893
+ });
894
+ }
895
+ }));
896
+ const createBlobFn = (data, hot) => Effect.gen(function* () {
897
+ const blobId = nanoid();
898
+ yield* send({
899
+ kind: "write",
900
+ op: {
901
+ type: "blob.create",
902
+ blobId,
903
+ data,
904
+ hot
905
+ }
906
+ });
907
+ return blobId;
908
+ });
909
+ const deleteBlobFn = (blobId) => send({
910
+ kind: "write",
911
+ op: {
912
+ type: "blob.delete",
913
+ blobId
914
+ }
915
+ });
916
+ const getBlobDataFn = (blobId) => Effect.gen(function* () {
917
+ const state = replica.getState();
918
+ if (state.kind !== "connected") return null;
919
+ const blob = state.blobs.find((b) => b.id === blobId);
920
+ if (blob && blob.data.kind === "hot") return blob.data.value;
921
+ yield* send({
922
+ kind: "read",
923
+ op: {
924
+ type: "blob.read",
925
+ blobId
926
+ }
927
+ }).pipe(Effect.catchAll(() => Effect.succeed(void 0)));
928
+ const newState = replica.getState();
929
+ if (newState.kind !== "connected") return null;
930
+ const warmed = newState.blobs.find((b) => b.id === blobId);
931
+ if (!warmed || warmed.data.kind !== "hot") return null;
932
+ return warmed.data.value;
933
+ });
934
+ return new Proxy({}, { get(_, prop) {
935
+ if (typeof prop === "symbol") return void 0;
936
+ if (prop === "readRoot") return readRootFn;
937
+ if (prop === "update") return updateFn;
938
+ if (prop === "createBlob") return createBlobFn;
939
+ if (prop === "deleteBlob") return deleteBlobFn;
940
+ if (prop === "getBlobData") return getBlobDataFn;
941
+ const rootVal = getAtPath(getRoot(), [prop]);
942
+ if (isCollectionValue(rootVal)) return makeCollectionNode(prop);
943
+ if (isBlobValue(rootVal)) return makeBlobNode(prop);
944
+ return makeFieldNode([prop]);
945
+ } });
946
+ }
947
+ const createEffectClient = (replica) => createClientCore(replica.postMessageEffect, replica);
948
+ function wrapEffectProxy(target) {
949
+ return new Proxy(target, { get(t, prop) {
950
+ if (typeof prop === "symbol") return Reflect.get(t, prop);
951
+ const val = t[prop];
952
+ if (typeof val === "function") return (...args) => {
953
+ const result = val(...args);
954
+ if (Effect.isEffect(result)) return Effect.runPromise(result.pipe(Effect.catchAll(() => Effect.void)));
955
+ if (result != null && typeof result === "object" && !Array.isArray(result)) return wrapEffectProxy(result);
956
+ return result;
957
+ };
958
+ if (val != null && typeof val === "object" && !Array.isArray(val)) return wrapEffectProxy(val);
959
+ return val;
960
+ } });
961
+ }
962
+ const createClient = (replica) => {
963
+ return wrapEffectProxy(createEffectClient("postMessageEffect" in replica ? replica : {
964
+ ...replica,
965
+ postMessageEffect: (event) => Effect.promise(() => replica.postMessage(event))
966
+ }));
967
+ };
968
+ //#endregion
969
+ //#region ../kyju/src/v2/transport.ts
970
+ const UINT8_TAG = "__$u8";
971
+ function dbStringify(value) {
972
+ return JSON.stringify(value, (_key, val) => {
973
+ if (val instanceof Uint8Array) {
974
+ let binary = "";
975
+ for (let i = 0; i < val.length; i++) binary += String.fromCharCode(val[i]);
976
+ return { [UINT8_TAG]: btoa(binary) };
977
+ }
978
+ return val;
979
+ });
980
+ }
981
+ function dbParse(text) {
982
+ return JSON.parse(text, (_key, val) => {
983
+ if (val !== null && typeof val === "object") {
984
+ if (UINT8_TAG in val) {
985
+ const binary = atob(val[UINT8_TAG]);
986
+ const bytes = new Uint8Array(binary.length);
987
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
988
+ return bytes;
989
+ }
990
+ if (val.type === "Buffer" && Array.isArray(val.data)) return new Uint8Array(val.data);
991
+ }
992
+ return val;
993
+ });
994
+ }
995
+ function extractReplicaId(event) {
996
+ if (event.kind === "connect") return event.message.replicaId;
997
+ if ("replicaId" in event) return event.replicaId;
998
+ }
999
+ function createRouter() {
1000
+ const routes = /* @__PURE__ */ new Map();
1001
+ return {
1002
+ send(event) {
1003
+ routes.get(event.replicaId)?.(event);
1004
+ },
1005
+ connection(opts) {
1006
+ let replicaId;
1007
+ return {
1008
+ receive(event) {
1009
+ const rid = extractReplicaId(event);
1010
+ if (rid && !replicaId) {
1011
+ replicaId = rid;
1012
+ routes.set(rid, opts.send);
1013
+ }
1014
+ return opts.postMessage(event);
1015
+ },
1016
+ close() {
1017
+ if (replicaId) routes.delete(replicaId);
1018
+ }
1019
+ };
1020
+ }
1021
+ };
1022
+ }
1023
+ async function connectReplica(opts) {
1024
+ const replica = createReplica({
1025
+ send: opts.send,
1026
+ maxPageSizeBytes: opts.maxPageSizeBytes ?? 1024 * 1024
1027
+ });
1028
+ const unsub = opts.subscribe((event) => {
1029
+ if (event.replicaId === replica.replicaId) replica.postMessage(event);
1030
+ });
1031
+ await replica.postMessage({
1032
+ kind: "connect",
1033
+ version: 0
1034
+ });
1035
+ return {
1036
+ client: createClient(replica),
1037
+ replica,
1038
+ disconnect: async () => {
1039
+ await replica.postMessage({ kind: "disconnect" }).catch(() => {});
1040
+ unsub();
1041
+ }
1042
+ };
1043
+ }
1044
+ //#endregion
1045
+ export { createClient as a, dbStringify as i, createRouter as n, createEffectClient as o, dbParse as r, createReplica as s, connectReplica as t };