jazz-tools 0.11.7 → 0.12.0

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 (62) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/CHANGELOG.md +23 -0
  3. package/dist/auth/DemoAuth.d.ts.map +1 -1
  4. package/dist/auth/PassphraseAuth.d.ts.map +1 -1
  5. package/dist/{chunk-HH3Z4JSB.js → chunk-QJNU65NK.js} +414 -275
  6. package/dist/chunk-QJNU65NK.js.map +1 -0
  7. package/dist/coValues/account.d.ts +15 -17
  8. package/dist/coValues/account.d.ts.map +1 -1
  9. package/dist/coValues/coFeed.d.ts +23 -18
  10. package/dist/coValues/coFeed.d.ts.map +1 -1
  11. package/dist/coValues/coList.d.ts +14 -7
  12. package/dist/coValues/coList.d.ts.map +1 -1
  13. package/dist/coValues/coMap.d.ts +36 -33
  14. package/dist/coValues/coMap.d.ts.map +1 -1
  15. package/dist/coValues/coPlainText.d.ts +7 -5
  16. package/dist/coValues/coPlainText.d.ts.map +1 -1
  17. package/dist/coValues/deepLoading.d.ts +36 -19
  18. package/dist/coValues/deepLoading.d.ts.map +1 -1
  19. package/dist/coValues/group.d.ts +14 -7
  20. package/dist/coValues/group.d.ts.map +1 -1
  21. package/dist/coValues/inbox.d.ts.map +1 -1
  22. package/dist/coValues/interfaces.d.ts +45 -11
  23. package/dist/coValues/interfaces.d.ts.map +1 -1
  24. package/dist/exports.d.ts +1 -1
  25. package/dist/exports.d.ts.map +1 -1
  26. package/dist/implementation/refs.d.ts +3 -0
  27. package/dist/implementation/refs.d.ts.map +1 -1
  28. package/dist/index.js +1 -1
  29. package/dist/testing.d.ts +1 -1
  30. package/dist/testing.d.ts.map +1 -1
  31. package/dist/testing.js +4 -2
  32. package/dist/testing.js.map +1 -1
  33. package/package.json +2 -2
  34. package/src/auth/DemoAuth.ts +3 -1
  35. package/src/auth/PassphraseAuth.ts +3 -1
  36. package/src/coValues/account.ts +43 -49
  37. package/src/coValues/coFeed.ts +74 -146
  38. package/src/coValues/coList.ts +47 -54
  39. package/src/coValues/coMap.ts +47 -54
  40. package/src/coValues/coPlainText.ts +23 -40
  41. package/src/coValues/deepLoading.ts +233 -102
  42. package/src/coValues/group.ts +44 -54
  43. package/src/coValues/inbox.ts +3 -6
  44. package/src/coValues/interfaces.ts +216 -105
  45. package/src/exports.ts +7 -1
  46. package/src/implementation/refs.ts +45 -7
  47. package/src/testing.ts +4 -1
  48. package/src/tests/ContextManager.test.ts +20 -6
  49. package/src/tests/PassphraseAuth.test.ts +3 -1
  50. package/src/tests/account.test.ts +26 -2
  51. package/src/tests/coFeed.test.ts +26 -19
  52. package/src/tests/coList.test.ts +18 -18
  53. package/src/tests/coMap.test.ts +67 -19
  54. package/src/tests/coPlainText.test.ts +8 -4
  55. package/src/tests/coRichText.test.ts +10 -8
  56. package/src/tests/deepLoading.test.ts +321 -80
  57. package/src/tests/groupsAndAccounts.test.ts +10 -12
  58. package/src/tests/inbox.test.ts +1 -1
  59. package/src/tests/schemaUnion.test.ts +8 -18
  60. package/src/tests/subscribe.test.ts +52 -33
  61. package/src/tests/testing.test.ts +1 -1
  62. package/dist/chunk-HH3Z4JSB.js.map +0 -1
@@ -124,15 +124,16 @@ describe("CoFeed resolution", async () => {
124
124
  crypto: Crypto,
125
125
  });
126
126
 
127
- const loadedStream = await TestStream.load(stream.id, meOnSecondPeer, []);
127
+ const loadedStream = await TestStream.load(stream.id, {
128
+ loadAs: meOnSecondPeer,
129
+ });
128
130
 
129
131
  expect(loadedStream?.[me.id]?.value).toEqual(null);
130
132
  expect(loadedStream?.[me.id]?.ref?.id).toEqual(stream[me.id]?.value?.id);
131
133
 
132
134
  const loadedNestedStream = await NestedStream.load(
133
135
  stream[me.id]!.value!.id,
134
- meOnSecondPeer,
135
- [],
136
+ { loadAs: meOnSecondPeer },
136
137
  );
137
138
 
138
139
  // expect(loadedStream?.[me.id]?.value).toEqual(loadedNestedStream);
@@ -148,8 +149,7 @@ describe("CoFeed resolution", async () => {
148
149
 
149
150
  const loadedTwiceNestedStream = await TwiceNestedStream.load(
150
151
  stream[me.id]!.value![me.id]!.value!.id,
151
- meOnSecondPeer,
152
- [],
152
+ { loadAs: meOnSecondPeer },
153
153
  );
154
154
 
155
155
  // expect(loadedStream?.[me.id]?.value?.[me.id]?.value).toEqual(
@@ -212,9 +212,13 @@ describe("CoFeed resolution", async () => {
212
212
 
213
213
  const queue = new cojsonInternals.Channel();
214
214
 
215
- TestStream.subscribe(stream.id, meOnSecondPeer, [], (subscribedStream) => {
216
- void queue.push(subscribedStream);
217
- });
215
+ TestStream.subscribe(
216
+ stream.id,
217
+ { loadAs: meOnSecondPeer },
218
+ (subscribedStream) => {
219
+ void queue.push(subscribedStream);
220
+ },
221
+ );
218
222
 
219
223
  const update1 = (await queue.next()).value;
220
224
  expect(update1[me.id]?.value).toEqual(null);
@@ -330,7 +334,9 @@ describe("FileStream loading & Subscription", async () => {
330
334
  crypto: Crypto,
331
335
  });
332
336
 
333
- const loadedStream = await FileStream.load(stream.id, meOnSecondPeer, []);
337
+ const loadedStream = await FileStream.load(stream.id, {
338
+ loadAs: meOnSecondPeer,
339
+ });
334
340
 
335
341
  expect(loadedStream?.getChunks()).toEqual({
336
342
  mimeType: "text/plain",
@@ -364,9 +370,13 @@ describe("FileStream loading & Subscription", async () => {
364
370
 
365
371
  const queue = new cojsonInternals.Channel();
366
372
 
367
- FileStream.subscribe(stream.id, meOnSecondPeer, [], (subscribedStream) => {
368
- void queue.push(subscribedStream);
369
- });
373
+ FileStream.subscribe(
374
+ stream.id,
375
+ { loadAs: meOnSecondPeer },
376
+ (subscribedStream) => {
377
+ void queue.push(subscribedStream);
378
+ },
379
+ );
370
380
 
371
381
  const update1 = (await queue.next()).value;
372
382
  expect(update1.getChunks()).toBe(undefined);
@@ -435,9 +445,7 @@ describe("FileStream.loadAsBlob", async () => {
435
445
  const { stream, me } = await setup();
436
446
  stream.push(new Uint8Array([1]));
437
447
 
438
- const promise = FileStream.loadAsBlob(stream.id, me);
439
-
440
- await stream.ensureLoaded([]);
448
+ const promise = FileStream.loadAsBlob(stream.id, { loadAs: me });
441
449
 
442
450
  stream.push(new Uint8Array([2]));
443
451
  stream.end();
@@ -453,17 +461,16 @@ describe("FileStream.loadAsBlob", async () => {
453
461
  const { stream, me } = await setup();
454
462
  stream.push(new Uint8Array([1]));
455
463
 
456
- const promise = FileStream.loadAsBlob(stream.id, me, {
464
+ const promise = FileStream.loadAsBlob(stream.id, {
465
+ loadAs: me,
457
466
  allowUnfinished: true,
458
467
  });
459
468
 
460
- await stream.ensureLoaded([]);
469
+ const blob = await promise;
461
470
 
462
471
  stream.push(new Uint8Array([2]));
463
472
  stream.end();
464
473
 
465
- const blob = await promise;
466
-
467
474
  // The promise resolves before the stream is ended
468
475
  // so we get a blob only with the first chunk
469
476
  expect(blob?.size).toBe(1);
@@ -508,16 +508,14 @@ describe("CoList resolution", async () => {
508
508
  crypto: Crypto,
509
509
  });
510
510
 
511
- const loadedList = await TestList.load(list.id, meOnSecondPeer, []);
511
+ const loadedList = await TestList.load(list.id, { loadAs: meOnSecondPeer });
512
512
 
513
513
  expect(loadedList?.[0]).toBe(null);
514
514
  expect(loadedList?._refs[0]?.id).toEqual(list[0]!.id);
515
515
 
516
- const loadedNestedList = await NestedList.load(
517
- list[0]!.id,
518
- meOnSecondPeer,
519
- [],
520
- );
516
+ const loadedNestedList = await NestedList.load(list[0]!.id, {
517
+ loadAs: meOnSecondPeer,
518
+ });
521
519
 
522
520
  expect(loadedList?.[0]).toBeDefined();
523
521
  expect(loadedList?.[0]?.[0]).toBe(null);
@@ -528,11 +526,9 @@ describe("CoList resolution", async () => {
528
526
  loadedNestedList?.toJSON(),
529
527
  );
530
528
 
531
- const loadedTwiceNestedList = await TwiceNestedList.load(
532
- list[0]![0]!.id,
533
- meOnSecondPeer,
534
- [],
535
- );
529
+ const loadedTwiceNestedList = await TwiceNestedList.load(list[0]![0]!.id, {
530
+ loadAs: meOnSecondPeer,
531
+ });
536
532
 
537
533
  expect(loadedList?.[0]?.[0]).toBeDefined();
538
534
  expect(loadedList?.[0]?.[0]?.[0]).toBe("a");
@@ -582,13 +578,17 @@ describe("CoList resolution", async () => {
582
578
 
583
579
  const queue = new cojsonInternals.Channel();
584
580
 
585
- TestList.subscribe(list.id, meOnSecondPeer, [], (subscribedList) => {
586
- console.log(
587
- "subscribedList?.[0]?.[0]?.[0]",
588
- subscribedList?.[0]?.[0]?.[0],
589
- );
590
- void queue.push(subscribedList);
591
- });
581
+ TestList.subscribe(
582
+ list.id,
583
+ { loadAs: meOnSecondPeer },
584
+ (subscribedList) => {
585
+ console.log(
586
+ "subscribedList?.[0]?.[0]?.[0]",
587
+ subscribedList?.[0]?.[0]?.[0],
588
+ );
589
+ void queue.push(subscribedList);
590
+ },
591
+ );
592
592
 
593
593
  const update1 = (await queue.next()).value;
594
594
  expect(update1?.[0]).toBe(null);
@@ -12,7 +12,7 @@ import {
12
12
  } from "../index.js";
13
13
  import { setupTwoNodes } from "./utils.js";
14
14
 
15
- const connectedPeers = cojsonInternals.connectedPeers;
15
+ const { connectedPeers } = cojsonInternals;
16
16
 
17
17
  const Crypto = await WasmCrypto.create();
18
18
 
@@ -444,7 +444,7 @@ describe("CoMap resolution", async () => {
444
444
  crypto: Crypto,
445
445
  });
446
446
 
447
- const loadedMap = await TestMap.load(map.id, meOnSecondPeer, {});
447
+ const loadedMap = await TestMap.load(map.id, { loadAs: meOnSecondPeer });
448
448
 
449
449
  expect(loadedMap?.color).toEqual("red");
450
450
  expect(loadedMap?.height).toEqual(10);
@@ -452,11 +452,9 @@ describe("CoMap resolution", async () => {
452
452
  expect(loadedMap?._refs.nested?.id).toEqual(map.nested?.id);
453
453
  expect(loadedMap?._refs.nested?.value).toEqual(null);
454
454
 
455
- const loadedNestedMap = await NestedMap.load(
456
- map.nested!.id,
457
- meOnSecondPeer,
458
- {},
459
- );
455
+ const loadedNestedMap = await NestedMap.load(map.nested!.id, {
456
+ loadAs: meOnSecondPeer,
457
+ });
460
458
 
461
459
  expect(loadedMap?.nested?.name).toEqual("nested");
462
460
  expect(loadedMap?.nested?._fancyName).toEqual("Sir nested");
@@ -465,8 +463,7 @@ describe("CoMap resolution", async () => {
465
463
 
466
464
  const loadedTwiceNestedMap = await TwiceNestedMap.load(
467
465
  map.nested!.twiceNested!.id,
468
- meOnSecondPeer,
469
- {},
466
+ { loadAs: meOnSecondPeer },
470
467
  );
471
468
 
472
469
  expect(loadedMap?.nested?.twiceNested?.taste).toEqual("sour");
@@ -493,7 +490,7 @@ describe("CoMap resolution", async () => {
493
490
  expect(loadedMap?.nested?._refs.twiceNested?.value).toBeDefined();
494
491
  });
495
492
 
496
- test("Subscription & auto-resolution", async () => {
493
+ async function setupTest() {
497
494
  const { me, map } = await initNodeAndMap();
498
495
 
499
496
  const [initialAsPeer, secondAsPeer] = connectedPeers("initial", "second", {
@@ -518,28 +515,53 @@ describe("CoMap resolution", async () => {
518
515
 
519
516
  const queue = new cojsonInternals.Channel<TestMap>();
520
517
 
521
- TestMap.subscribe(map.id, meOnSecondPeer, {}, (subscribedMap) => {
518
+ await meOnSecondPeer.waitForAllCoValuesSync();
519
+
520
+ TestMap.subscribe(map.id, { loadAs: meOnSecondPeer }, (subscribedMap) => {
522
521
  // Read to property to trigger loading
523
522
  subscribedMap.nested?.twiceNested?.taste;
524
523
  void queue.push(subscribedMap);
525
524
  });
526
525
 
526
+ return { me, map, meOnSecondPeer, queue };
527
+ }
528
+
529
+ test("initial subscription loads nested data progressively", async () => {
530
+ const { queue } = await setupTest();
531
+
527
532
  const update1 = (await queue.next()).value;
528
533
  expect(update1.nested).toEqual(null);
529
534
 
530
535
  const update2 = (await queue.next()).value;
531
536
  expect(update2.nested?.name).toEqual("nested");
537
+ });
538
+
539
+ test("updates to nested properties are received", async () => {
540
+ const { map, queue } = await setupTest();
541
+
542
+ // Skip initial updates
543
+ await queue.next();
544
+ await queue.next();
532
545
 
533
546
  map.nested!.name = "nestedUpdated";
534
547
 
535
- const _ = (await queue.next()).value;
548
+ await queue.next(); // Skip intermediate update
536
549
  const update3 = (await queue.next()).value;
537
550
  expect(update3.nested?.name).toEqual("nestedUpdated");
538
551
 
539
552
  const oldTwiceNested = update3.nested!.twiceNested;
540
553
  expect(oldTwiceNested?.taste).toEqual("sour");
554
+ });
555
+
556
+ test("replacing nested object triggers updates", async () => {
557
+ const { meOnSecondPeer, queue } = await setupTest();
558
+
559
+ // Skip initial updates
560
+ await queue.next();
561
+ await queue.next();
562
+
563
+ const update3 = (await queue.next()).value;
541
564
 
542
- // When assigning a new nested value, we get an update
543
565
  const newTwiceNested = TwiceNestedMap.create(
544
566
  {
545
567
  taste: "sweet",
@@ -557,14 +579,40 @@ describe("CoMap resolution", async () => {
557
579
 
558
580
  update3.nested = newNested;
559
581
 
560
- (await queue.next()).value;
561
- // const update4 = (await queue.next()).value;
562
- const update4b = (await queue.next()).value;
582
+ await queue.next(); // Skip intermediate update
583
+ const update4 = (await queue.next()).value;
584
+
585
+ expect(update4.nested?.name).toEqual("newNested");
586
+ expect(update4.nested?.twiceNested?.taste).toEqual("sweet");
587
+ });
588
+
589
+ test("updates to deeply nested properties are received", async () => {
590
+ const { queue } = await setupTest();
591
+
592
+ // Skip to the point where we have the nested object
593
+ await queue.next();
594
+ await queue.next();
595
+ const update3 = (await queue.next()).value;
596
+
597
+ const newTwiceNested = TwiceNestedMap.create(
598
+ { taste: "sweet" },
599
+ { owner: update3.nested!._raw.owner },
600
+ );
601
+
602
+ const newNested = NestedMap.create(
603
+ {
604
+ name: "newNested",
605
+ twiceNested: newTwiceNested,
606
+ },
607
+ { owner: update3.nested!._raw.owner },
608
+ );
609
+
610
+ update3.nested = newNested;
563
611
 
564
- expect(update4b.nested?.name).toEqual("newNested");
565
- expect(update4b.nested?.twiceNested?.taste).toEqual("sweet");
612
+ // Skip intermediate updates
613
+ await queue.next();
614
+ await queue.next();
566
615
 
567
- // we get updates when the new nested value changes
568
616
  newTwiceNested.taste = "salty";
569
617
  const update5 = (await queue.next()).value;
570
618
  expect(update5.nested?.twiceNested?.taste).toEqual("salty");
@@ -109,7 +109,7 @@ describe("CoPlainText", () => {
109
109
  });
110
110
 
111
111
  // Load the text on the second peer
112
- const loaded = await CoPlainText.load(id, meOnSecondPeer);
112
+ const loaded = await CoPlainText.load(id, { loadAs: meOnSecondPeer });
113
113
  expect(loaded).toBeDefined();
114
114
  expect(loaded!.toString()).toBe("hello world");
115
115
  });
@@ -142,9 +142,13 @@ describe("CoPlainText", () => {
142
142
  const queue = new cojsonInternals.Channel();
143
143
 
144
144
  // Subscribe to text updates
145
- CoPlainText.subscribe(text.id, meOnSecondPeer, (subscribedText) => {
146
- void queue.push(subscribedText);
147
- });
145
+ CoPlainText.subscribe(
146
+ text.id,
147
+ { loadAs: meOnSecondPeer },
148
+ (subscribedText) => {
149
+ void queue.push(subscribedText);
150
+ },
151
+ );
148
152
 
149
153
  // Initial subscription should give us the text
150
154
  const update1 = (await queue.next()).value;
@@ -602,17 +602,17 @@ describe("CoRichText", async () => {
602
602
  crypto: Crypto,
603
603
  });
604
604
 
605
- const loadedText = await CoRichText.load(text.id, meOnSecondPeer, {
606
- marks: [{}],
607
- text: [],
605
+ const loadedText = await CoRichText.load(text.id, {
606
+ loadAs: meOnSecondPeer,
607
+ resolve: { marks: { $each: true }, text: true },
608
608
  });
609
609
 
610
610
  expect(loadedText).toBeDefined();
611
611
  expect(loadedText?.toString()).toEqual("hello world");
612
612
 
613
- const loadedText2 = await CoRichText.load(text.id, meOnSecondPeer, {
614
- marks: [{}],
615
- text: [],
613
+ const loadedText2 = await CoRichText.load(text.id, {
614
+ loadAs: meOnSecondPeer,
615
+ resolve: { marks: { $each: true }, text: true },
616
616
  });
617
617
 
618
618
  expect(loadedText2).toBeDefined();
@@ -646,8 +646,10 @@ describe("CoRichText", async () => {
646
646
 
647
647
  CoRichText.subscribe(
648
648
  text.id,
649
- meOnSecondPeer,
650
- { marks: [{}], text: [] },
649
+ {
650
+ loadAs: meOnSecondPeer,
651
+ resolve: { marks: { $each: true }, text: true },
652
+ },
651
653
  (subscribedText) => {
652
654
  void queue.push(subscribedText);
653
655
  },