jazz-tools 0.18.5 → 0.18.6

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 (59) hide show
  1. package/.turbo/turbo-build.log +53 -53
  2. package/CHANGELOG.md +16 -0
  3. package/dist/better-auth/auth/client.d.ts.map +1 -1
  4. package/dist/better-auth/auth/client.js +7 -1
  5. package/dist/better-auth/auth/client.js.map +1 -1
  6. package/dist/better-auth/auth/react.d.ts +0 -2145
  7. package/dist/better-auth/auth/react.d.ts.map +1 -1
  8. package/dist/better-auth/auth/react.js +2 -14
  9. package/dist/better-auth/auth/react.js.map +1 -1
  10. package/dist/better-auth/auth/server.d.ts.map +1 -1
  11. package/dist/better-auth/auth/server.js +73 -22
  12. package/dist/better-auth/auth/server.js.map +1 -1
  13. package/dist/better-auth/auth/tests/react.test.d.ts +2 -0
  14. package/dist/better-auth/auth/tests/react.test.d.ts.map +1 -0
  15. package/dist/{chunk-3LE7N6TH.js → chunk-45VKEOXG.js} +123 -81
  16. package/dist/chunk-45VKEOXG.js.map +1 -0
  17. package/dist/index.js +1 -1
  18. package/dist/inspector/{custom-element-WCY6D3QJ.js → custom-element-IBHKHN27.js} +19 -69
  19. package/dist/inspector/custom-element-IBHKHN27.js.map +1 -0
  20. package/dist/inspector/index.d.ts +5 -1
  21. package/dist/inspector/index.d.ts.map +1 -1
  22. package/dist/inspector/index.js +18 -17
  23. package/dist/inspector/index.js.map +1 -1
  24. package/dist/inspector/register-custom-element.js +1 -1
  25. package/dist/inspector/viewer/new-app.d.ts +0 -3
  26. package/dist/inspector/viewer/new-app.d.ts.map +1 -1
  27. package/dist/react-core/index.js +3 -1
  28. package/dist/react-core/index.js.map +1 -1
  29. package/dist/testing.js +2 -2
  30. package/dist/testing.js.map +1 -1
  31. package/dist/tools/coValues/inbox.d.ts +5 -5
  32. package/dist/tools/coValues/inbox.d.ts.map +1 -1
  33. package/dist/worker/index.d.ts +8 -2
  34. package/dist/worker/index.d.ts.map +1 -1
  35. package/dist/worker/index.js +7 -3
  36. package/dist/worker/index.js.map +1 -1
  37. package/package.json +4 -4
  38. package/src/better-auth/auth/client.ts +8 -2
  39. package/src/better-auth/auth/react.tsx +2 -51
  40. package/src/better-auth/auth/server.ts +94 -24
  41. package/src/better-auth/auth/tests/client.test.ts +92 -4
  42. package/src/better-auth/auth/tests/react.test.tsx +43 -0
  43. package/src/better-auth/auth/tests/server.test.ts +276 -98
  44. package/src/inspector/custom-element.tsx +1 -1
  45. package/src/inspector/index.tsx +44 -0
  46. package/src/inspector/viewer/new-app.tsx +0 -18
  47. package/src/tools/coValues/inbox.ts +190 -108
  48. package/src/tools/testing.ts +1 -1
  49. package/src/tools/tests/coFeed.test.ts +33 -22
  50. package/src/tools/tests/coList.test.ts +6 -4
  51. package/src/tools/tests/coMap.test.ts +13 -5
  52. package/src/tools/tests/exportImport.test.ts +3 -1
  53. package/src/tools/tests/groupsAndAccounts.test.ts +56 -44
  54. package/src/tools/tests/inbox.test.ts +293 -31
  55. package/src/worker/index.ts +15 -5
  56. package/tsup.config.ts +1 -1
  57. package/dist/chunk-3LE7N6TH.js.map +0 -1
  58. package/dist/inspector/custom-element-WCY6D3QJ.js.map +0 -1
  59. package/src/inspector/index.ts +0 -23
@@ -1,9 +1,9 @@
1
1
  import { WasmCrypto } from "cojson/crypto/WasmCrypto";
2
2
  import { assert, beforeEach, describe, expect, test } from "vitest";
3
3
  import { CoMap, Group, z } from "../exports.js";
4
- import { Loaded, Ref, co } from "../internal.js";
4
+ import { Account, Loaded, Ref, co } from "../internal.js";
5
5
  import { createJazzTestAccount, setupJazzTestSync } from "../testing.js";
6
- import { setupTwoNodes, waitFor } from "./utils.js";
6
+ import { loadCoValueOrFail, setupTwoNodes, waitFor } from "./utils.js";
7
7
 
8
8
  const Crypto = await WasmCrypto.create();
9
9
 
@@ -272,14 +272,20 @@ describe("Group inheritance", () => {
272
272
  const bob = await createJazzTestAccount({});
273
273
  await bob.$jazz.waitForAllCoValuesSync();
274
274
 
275
+ const loadedAlice = await Account.load(alice.$jazz.id);
276
+ const loadedBob = await Account.load(bob.$jazz.id);
277
+
278
+ assert(loadedBob);
279
+ assert(loadedAlice);
280
+
275
281
  const parentGroup = Group.create();
276
282
  // `parentGroup` has `alice` as a writer
277
- parentGroup.addMember(alice, "writer");
283
+ parentGroup.addMember(loadedAlice, "writer");
278
284
  expect(parentGroup.getRoleOf(alice.$jazz.id)).toBe("writer");
279
285
 
280
286
  const group = Group.create();
281
287
  // `group` has `bob` as a reader
282
- group.addMember(bob, "reader");
288
+ group.addMember(loadedBob, "reader");
283
289
  expect(group.getRoleOf(bob.$jazz.id)).toBe("reader");
284
290
 
285
291
  group.addMember(parentGroup);
@@ -817,24 +823,26 @@ describe("Group.members", () => {
817
823
  childGroup.addMember(bob, "reader");
818
824
  expect(childGroup.getRoleOf(bob.$jazz.id)).toBe("reader");
819
825
 
820
- expect(childGroup.members).toEqual([
821
- expect.objectContaining({
822
- account: expect.objectContaining({
823
- $jazz: expect.objectContaining({
824
- id: co.account().getMe().$jazz.id,
826
+ await waitFor(() => {
827
+ expect(childGroup.members).toEqual([
828
+ expect.objectContaining({
829
+ account: expect.objectContaining({
830
+ $jazz: expect.objectContaining({
831
+ id: co.account().getMe().$jazz.id,
832
+ }),
825
833
  }),
834
+ role: "admin",
826
835
  }),
827
- role: "admin",
828
- }),
829
- expect.objectContaining({
830
- account: expect.objectContaining({
831
- $jazz: expect.objectContaining({
832
- id: bob.$jazz.id,
836
+ expect.objectContaining({
837
+ account: expect.objectContaining({
838
+ $jazz: expect.objectContaining({
839
+ id: bob.$jazz.id,
840
+ }),
833
841
  }),
842
+ role: "reader",
834
843
  }),
835
- role: "reader",
836
- }),
837
- ]);
844
+ ]);
845
+ });
838
846
  });
839
847
 
840
848
  test("should return the members of the parent group", async () => {
@@ -849,24 +857,26 @@ describe("Group.members", () => {
849
857
 
850
858
  expect(childGroup.getRoleOf(bob.$jazz.id)).toBe("reader");
851
859
 
852
- expect(childGroup.members).toEqual([
853
- expect.objectContaining({
854
- account: expect.objectContaining({
855
- $jazz: expect.objectContaining({
856
- id: co.account().getMe().$jazz.id,
860
+ await waitFor(() => {
861
+ expect(childGroup.members).toEqual([
862
+ expect.objectContaining({
863
+ account: expect.objectContaining({
864
+ $jazz: expect.objectContaining({
865
+ id: co.account().getMe().$jazz.id,
866
+ }),
857
867
  }),
868
+ role: "admin",
858
869
  }),
859
- role: "admin",
860
- }),
861
- expect.objectContaining({
862
- account: expect.objectContaining({
863
- $jazz: expect.objectContaining({
864
- id: bob.$jazz.id,
870
+ expect.objectContaining({
871
+ account: expect.objectContaining({
872
+ $jazz: expect.objectContaining({
873
+ id: bob.$jazz.id,
874
+ }),
865
875
  }),
876
+ role: "reader",
866
877
  }),
867
- role: "reader",
868
- }),
869
- ]);
878
+ ]);
879
+ });
870
880
  });
871
881
 
872
882
  test("should not return everyone", async () => {
@@ -926,22 +936,24 @@ describe("Group.getDirectMembers", () => {
926
936
  childGroup.addMember(parentGroup);
927
937
 
928
938
  // Child group should inherit bob through parent, but bob is not a direct member
929
- expect(childGroup.members).toEqual([
930
- expect.objectContaining({
931
- account: expect.objectContaining({
932
- $jazz: expect.objectContaining({
933
- id: co.account().getMe().$jazz.id,
939
+ await waitFor(() => {
940
+ expect(childGroup.members).toEqual([
941
+ expect.objectContaining({
942
+ account: expect.objectContaining({
943
+ $jazz: expect.objectContaining({
944
+ id: co.account().getMe().$jazz.id,
945
+ }),
934
946
  }),
935
947
  }),
936
- }),
937
- expect.objectContaining({
938
- account: expect.objectContaining({
939
- $jazz: expect.objectContaining({
940
- id: bob.$jazz.id,
948
+ expect.objectContaining({
949
+ account: expect.objectContaining({
950
+ $jazz: expect.objectContaining({
951
+ id: bob.$jazz.id,
952
+ }),
941
953
  }),
942
954
  }),
943
- }),
944
- ]);
955
+ ]);
956
+ });
945
957
 
946
958
  // directMembers should only show the admin, not the inherited bob
947
959
  expect(childGroup.getDirectMembers()).toEqual([
@@ -1,12 +1,29 @@
1
- import { describe, expect, it, vi } from "vitest";
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
2
  import { Group, Inbox, InboxSender, z } from "../exports";
3
- import { Loaded, co, coValueClassFromCoValueClassOrSchema } from "../internal";
3
+ import {
4
+ Account,
5
+ Loaded,
6
+ co,
7
+ coValueClassFromCoValueClassOrSchema,
8
+ } from "../internal";
4
9
  import { setupTwoNodes, waitFor } from "./utils";
10
+ import {
11
+ createJazzTestAccount,
12
+ getPeerConnectedToTestSyncServer,
13
+ setupJazzTestSync,
14
+ } from "../testing";
15
+ import { cojsonInternals, LocalNode } from "cojson";
16
+ import { WasmCrypto } from "cojson/crypto/WasmCrypto";
5
17
 
6
18
  const Message = co.map({
7
19
  text: z.string(),
8
20
  });
9
21
 
22
+ beforeEach(async () => {
23
+ await setupJazzTestSync();
24
+ vi.useRealTimers();
25
+ });
26
+
10
27
  describe("Inbox", () => {
11
28
  describe("Private profile", () => {
12
29
  it("Should throw if the inbox owner profile is private", async () => {
@@ -211,10 +228,7 @@ describe("Inbox", () => {
211
228
 
212
229
  unsubscribe();
213
230
 
214
- expect(errorLogSpy).toHaveBeenCalledWith(
215
- "Error processing inbox message",
216
- expect.any(Error),
217
- );
231
+ expect(errorLogSpy).toHaveBeenCalledWith(new Error("Failed"));
218
232
 
219
233
  errorLogSpy.mockRestore();
220
234
  });
@@ -298,7 +312,7 @@ describe("Inbox", () => {
298
312
  expect(receivedMessages[0]?.text).toBe("Hello");
299
313
  });
300
314
 
301
- it("should retry failed messages", async () => {
315
+ it("should not retry failed messages", async () => {
302
316
  const { clientAccount: sender, serverAccount: receiver } =
303
317
  await setupTwoNodes();
304
318
 
@@ -320,25 +334,18 @@ describe("Inbox", () => {
320
334
  let failures = 0;
321
335
 
322
336
  // Subscribe to inbox messages
323
- const unsubscribe = receiverInbox.subscribe(
324
- Message,
325
- async () => {
326
- failures++;
327
- throw new Error("Failed");
328
- },
329
- { retries: 2 },
330
- );
337
+ const unsubscribe = receiverInbox.subscribe(Message, async () => {
338
+ failures++;
339
+ throw new Error("Failed");
340
+ });
331
341
 
332
342
  await expect(promise).rejects.toThrow();
333
- expect(failures).toBe(3);
343
+ expect(failures).toBe(1);
334
344
  const [failed] = Object.values(receiverInbox.failed.items).flat();
335
- expect(failed?.value.errors.length).toBe(3);
345
+ expect(failed?.value.errors.length).toBe(1);
336
346
  unsubscribe();
337
347
 
338
- expect(errorLogSpy).toHaveBeenCalledWith(
339
- "Error processing inbox message",
340
- expect.any(Error),
341
- );
348
+ expect(errorLogSpy).toHaveBeenCalledWith(new Error("Failed"));
342
349
 
343
350
  errorLogSpy.mockRestore();
344
351
  });
@@ -357,28 +364,283 @@ describe("Inbox", () => {
357
364
  const errorLogSpy = vi.spyOn(console, "error").mockImplementation(() => {});
358
365
 
359
366
  // Subscribe to inbox messages
360
- const unsubscribe = receiverInbox.subscribe(
361
- Message,
362
- async () => {
363
- spy();
364
- },
365
- { retries: 2 },
366
- );
367
+ const unsubscribe = receiverInbox.subscribe(Message, async () => {
368
+ spy();
369
+ });
367
370
 
368
371
  await waitFor(() => {
369
372
  const [failed] = Object.values(receiverInbox.failed.items).flat();
370
373
 
371
- expect(failed?.value.errors.length).toBe(3);
374
+ expect(failed?.value.errors.length).toBe(1);
372
375
  });
373
376
 
374
377
  expect(spy).not.toHaveBeenCalled();
375
378
  unsubscribe();
376
379
 
377
380
  expect(errorLogSpy).toHaveBeenCalledWith(
378
- "Error processing inbox message",
379
- expect.any(Error),
381
+ new Error("Inbox: message co_z123234 is unavailable"),
380
382
  );
381
383
 
382
384
  errorLogSpy.mockRestore();
383
385
  });
386
+
387
+ it("should skip processed messages when a large inbox is restarted", async () => {
388
+ cojsonInternals.setMaxRecommendedTxSize(100);
389
+
390
+ const sender = await createJazzTestAccount();
391
+ const receiver = await createJazzTestAccount();
392
+
393
+ await receiver.$jazz.waitForAllCoValuesSync();
394
+
395
+ const receiverInbox = await Inbox.load(receiver);
396
+ const inboxSender = await InboxSender.load(receiver.$jazz.id, sender);
397
+
398
+ const group = Group.create({ owner: receiver });
399
+
400
+ // This generates 4 chunks on the processed stream
401
+ for (let i = 0; i < 5; i++) {
402
+ inboxSender.sendMessage(Message.create({ text: `Hello ${i}` }, group));
403
+ }
404
+
405
+ inboxSender.sendMessage(Message.create({ text: `done` }, group));
406
+
407
+ await new Promise((resolve) => {
408
+ const unsubscribe = receiverInbox.subscribe(Message, async (message) => {
409
+ if (message.text === "done") {
410
+ resolve(true);
411
+ unsubscribe();
412
+ }
413
+ });
414
+ });
415
+
416
+ const accountId = receiver.$jazz.id;
417
+ const accountSecret =
418
+ receiver.$jazz.localNode.getCurrentAgent().agentSecret;
419
+ const sessionID = receiver.$jazz.localNode.currentSessionID;
420
+
421
+ await receiver.$jazz.waitForAllCoValuesSync();
422
+ await receiver.$jazz.localNode.gracefulShutdown();
423
+
424
+ const node = await LocalNode.withLoadedAccount({
425
+ accountID: accountId as any,
426
+ accountSecret: accountSecret,
427
+ peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
428
+ crypto: receiver.$jazz.localNode.crypto,
429
+ sessionID: sessionID,
430
+ });
431
+
432
+ const reloadedInbox = await Inbox.load(Account.fromNode(node));
433
+
434
+ const subscribeEmitted = await new Promise((resolve) => {
435
+ const unsubscribe = reloadedInbox.subscribe(Message, async (message) => {
436
+ // Got a message
437
+ resolve(true);
438
+ });
439
+ setTimeout(() => {
440
+ resolve(false);
441
+ unsubscribe();
442
+ }, 100);
443
+ });
444
+
445
+ expect(subscribeEmitted).toBe(false);
446
+ });
447
+
448
+ it("should skip failed messages when a large inbox is restarted", async () => {
449
+ cojsonInternals.setMaxRecommendedTxSize(100);
450
+
451
+ const sender = await createJazzTestAccount();
452
+ const receiver = await createJazzTestAccount();
453
+
454
+ await receiver.$jazz.waitForAllCoValuesSync();
455
+
456
+ const receiverInbox = await Inbox.load(receiver);
457
+ const inboxSender = await InboxSender.load(receiver.$jazz.id, sender);
458
+
459
+ const group = Group.create({ owner: receiver });
460
+
461
+ // This generates 4 chunks on the processed stream
462
+ for (let i = 0; i < 5; i++) {
463
+ inboxSender
464
+ .sendMessage(Message.create({ text: `Hello ${i}` }, group))
465
+ .catch(() => {});
466
+ }
467
+
468
+ inboxSender
469
+ .sendMessage(Message.create({ text: `done` }, group))
470
+ .catch(() => {});
471
+
472
+ await new Promise((resolve) => {
473
+ const unsubscribe = receiverInbox.subscribe(Message, async (message) => {
474
+ if (message.text === "done") {
475
+ resolve(true);
476
+ unsubscribe();
477
+ }
478
+
479
+ throw new Error("Failed");
480
+ });
481
+ });
482
+
483
+ await waitFor(() => {
484
+ expect(Object.values(receiverInbox.processed.items).length).toBe(1);
485
+ });
486
+
487
+ const accountId = receiver.$jazz.id;
488
+ const accountSecret =
489
+ receiver.$jazz.localNode.getCurrentAgent().agentSecret;
490
+ const sessionID = receiver.$jazz.localNode.currentSessionID;
491
+
492
+ await receiver.$jazz.waitForAllCoValuesSync();
493
+ await receiver.$jazz.localNode.gracefulShutdown();
494
+
495
+ const node = await LocalNode.withLoadedAccount({
496
+ accountID: accountId as any,
497
+ accountSecret: accountSecret,
498
+ peersToLoadFrom: [getPeerConnectedToTestSyncServer()],
499
+ crypto: receiver.$jazz.localNode.crypto,
500
+ sessionID: sessionID,
501
+ });
502
+
503
+ const reloadedInbox = await Inbox.load(Account.fromNode(node));
504
+
505
+ const subscribeEmitted = await new Promise((resolve) => {
506
+ const unsubscribe = reloadedInbox.subscribe(Message, async (message) => {
507
+ // Got a message
508
+ resolve(true);
509
+ });
510
+ setTimeout(() => {
511
+ resolve(false);
512
+ unsubscribe();
513
+ }, 100);
514
+ });
515
+
516
+ expect(subscribeEmitted).toBe(false);
517
+ });
518
+
519
+ describe("Concurrency control", () => {
520
+ it("should respect concurrency limit of 1", async () => {
521
+ const { clientAccount: sender, serverAccount: receiver } =
522
+ await setupTwoNodes();
523
+
524
+ const receiverInbox = await Inbox.load(receiver);
525
+ const inboxSender = await InboxSender.load(receiver.$jazz.id, sender);
526
+
527
+ const group = Group.create({ owner: sender });
528
+
529
+ const processingOrder: string[] = [];
530
+
531
+ const Message = co.map({
532
+ text: z.string(),
533
+ value: z.number(),
534
+ });
535
+
536
+ // Create messages that take time to process
537
+ const messages = Array.from({ length: 5 }, (_, i) =>
538
+ Message.create({ text: `Message ${i}`, value: i }, group),
539
+ );
540
+
541
+ // Subscribe with concurrency limit of 1
542
+ const unsubscribe = receiverInbox.subscribe(
543
+ Message,
544
+ async (message) => {
545
+ const messageText = message.text;
546
+ processingOrder.push(`start-${messageText}`);
547
+
548
+ // Simulate processing time
549
+ await new Promise((resolve) =>
550
+ setTimeout(resolve, 20 - message.value * 10),
551
+ );
552
+
553
+ processingOrder.push(`end-${messageText}`);
554
+ },
555
+ { concurrencyLimit: 1 },
556
+ );
557
+
558
+ // Send all messages at once
559
+ messages.forEach((message) => {
560
+ inboxSender.sendMessage(message);
561
+ });
562
+
563
+ // Wait for all messages to be processed
564
+ await waitFor(() => processingOrder.length === 10); // 5 start + 5 end
565
+
566
+ expect(processingOrder).toMatchInlineSnapshot(`
567
+ [
568
+ "start-Message 0",
569
+ "end-Message 0",
570
+ "start-Message 1",
571
+ "end-Message 1",
572
+ "start-Message 2",
573
+ "end-Message 2",
574
+ "start-Message 3",
575
+ "end-Message 3",
576
+ "start-Message 4",
577
+ "end-Message 4",
578
+ ]
579
+ `);
580
+ unsubscribe();
581
+ });
582
+
583
+ it("should allow concurrent processing with higher concurrency limit", async () => {
584
+ const { clientAccount: sender, serverAccount: receiver } =
585
+ await setupTwoNodes();
586
+
587
+ const receiverInbox = await Inbox.load(receiver);
588
+ const inboxSender = await InboxSender.load(receiver.$jazz.id, sender);
589
+
590
+ const group = Group.create({ owner: sender });
591
+
592
+ // Track processing order and timing
593
+ const processingOrder: string[] = [];
594
+
595
+ const Message = co.map({
596
+ text: z.string(),
597
+ value: z.number(),
598
+ });
599
+
600
+ // Create messages that take time to process
601
+ const messages = Array.from({ length: 5 }, (_, i) =>
602
+ Message.create({ text: `Message ${i}`, value: i }, group),
603
+ );
604
+
605
+ // Subscribe with concurrency limit of 1
606
+ const unsubscribe = receiverInbox.subscribe(
607
+ Message,
608
+ async (message) => {
609
+ const messageText = message.text;
610
+ processingOrder.push(`start-${messageText}`);
611
+
612
+ // Simulate processing time
613
+ await new Promise((resolve) =>
614
+ setTimeout(resolve, 20 - message.value * 10),
615
+ );
616
+
617
+ processingOrder.push(`end-${messageText}`);
618
+ },
619
+ { concurrencyLimit: 3 },
620
+ );
621
+
622
+ // Send all messages at once
623
+ messages.forEach((message) => {
624
+ inboxSender.sendMessage(message);
625
+ });
626
+
627
+ await waitFor(() => processingOrder.length === 10);
628
+
629
+ expect(processingOrder).toMatchInlineSnapshot(`
630
+ [
631
+ "start-Message 0",
632
+ "start-Message 1",
633
+ "start-Message 2",
634
+ "end-Message 2",
635
+ "start-Message 3",
636
+ "end-Message 3",
637
+ "start-Message 4",
638
+ "end-Message 4",
639
+ "end-Message 1",
640
+ "end-Message 0",
641
+ ]
642
+ `);
643
+ unsubscribe();
644
+ });
645
+ });
384
646
  });
@@ -11,6 +11,7 @@ import {
11
11
  CoValueFromRaw,
12
12
  Inbox,
13
13
  InstanceOfSchema,
14
+ Loaded,
14
15
  createJazzContextFromExistingCredentials,
15
16
  randomSessionProvider,
16
17
  } from "jazz-tools";
@@ -26,6 +27,10 @@ type WorkerOptions<
26
27
  WebSocket?: AnyWebSocketConstructor;
27
28
  AccountSchema?: S;
28
29
  crypto?: CryptoProvider;
30
+ /**
31
+ * If true, the inbox will not be loaded.
32
+ */
33
+ skipInboxLoad?: boolean;
29
34
  };
30
35
 
31
36
  /** @category Context Creation */
@@ -39,6 +44,7 @@ export async function startWorker<
39
44
  accountSecret = process.env.JAZZ_WORKER_SECRET,
40
45
  syncServer = "wss://cloud.jazz.tools",
41
46
  AccountSchema = Account as unknown as S,
47
+ skipInboxLoad = false,
42
48
  } = options;
43
49
 
44
50
  let node: LocalNode | undefined = undefined;
@@ -93,7 +99,7 @@ export async function startWorker<
93
99
  throw new Error("Account has no profile");
94
100
  }
95
101
 
96
- const inbox = await Inbox.load(account);
102
+ const inbox = skipInboxLoad ? undefined : await Inbox.load(account);
97
103
 
98
104
  async function done() {
99
105
  await context.account.$jazz.waitForAllCoValuesSync();
@@ -102,12 +108,16 @@ export async function startWorker<
102
108
  context.done();
103
109
  }
104
110
 
105
- const inboxPublicApi = {
106
- subscribe: inbox.subscribe.bind(inbox) as Inbox["subscribe"],
107
- };
111
+ const inboxPublicApi = inbox
112
+ ? {
113
+ subscribe: inbox.subscribe.bind(inbox) as Inbox["subscribe"],
114
+ }
115
+ : {
116
+ subscribe: () => {},
117
+ };
108
118
 
109
119
  return {
110
- worker: context.account as InstanceOfSchema<S>,
120
+ worker: context.account as Loaded<S>,
111
121
  experimental: {
112
122
  inbox: inboxPublicApi,
113
123
  },
package/tsup.config.ts CHANGED
@@ -48,7 +48,7 @@ export default defineConfig([
48
48
  {
49
49
  ...cfg,
50
50
  entry: {
51
- index: "src/inspector/index.ts",
51
+ index: "src/inspector/index.tsx",
52
52
  },
53
53
  outDir: "dist/inspector",
54
54
  esbuildOptions: (options) => {