cojson 0.6.7 → 0.7.0-alpha.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 (53) hide show
  1. package/.eslintrc.cjs +1 -0
  2. package/.turbo/turbo-build.log +2 -2
  3. package/CHANGELOG.md +3 -3
  4. package/dist/coValue.js.map +1 -1
  5. package/dist/coValueCore.js.map +1 -1
  6. package/dist/coValues/account.js +5 -5
  7. package/dist/coValues/account.js.map +1 -1
  8. package/dist/coValues/coList.js +39 -58
  9. package/dist/coValues/coList.js.map +1 -1
  10. package/dist/coValues/coMap.js +20 -61
  11. package/dist/coValues/coMap.js.map +1 -1
  12. package/dist/coValues/coStream.js +14 -64
  13. package/dist/coValues/coStream.js.map +1 -1
  14. package/dist/coValues/group.js +57 -59
  15. package/dist/coValues/group.js.map +1 -1
  16. package/dist/coreToCoValue.js +17 -12
  17. package/dist/coreToCoValue.js.map +1 -1
  18. package/dist/index.js +8 -8
  19. package/dist/index.js.map +1 -1
  20. package/dist/localNode.js +54 -38
  21. package/dist/localNode.js.map +1 -1
  22. package/dist/permissions.js +2 -2
  23. package/dist/permissions.js.map +1 -1
  24. package/dist/tests/testUtils.js +6 -11
  25. package/dist/tests/testUtils.js.map +1 -1
  26. package/dist/typeUtils/expectGroup.js +2 -2
  27. package/dist/typeUtils/expectGroup.js.map +1 -1
  28. package/dist/typeUtils/isCoValue.js +8 -8
  29. package/dist/typeUtils/isCoValue.js.map +1 -1
  30. package/package.json +3 -4
  31. package/src/coValue.ts +21 -21
  32. package/src/coValueCore.ts +8 -8
  33. package/src/coValues/account.ts +14 -26
  34. package/src/coValues/coList.ts +58 -97
  35. package/src/coValues/coMap.ts +27 -129
  36. package/src/coValues/coStream.ts +31 -137
  37. package/src/coValues/group.ts +52 -46
  38. package/src/coreToCoValue.ts +16 -12
  39. package/src/index.ts +27 -36
  40. package/src/jsonValue.ts +1 -1
  41. package/src/localNode.ts +88 -75
  42. package/src/media.ts +4 -4
  43. package/src/permissions.ts +2 -2
  44. package/src/tests/account.test.ts +12 -12
  45. package/src/tests/coValue.test.ts +149 -182
  46. package/src/tests/coValueCore.test.ts +8 -3
  47. package/src/tests/crypto.test.ts +7 -0
  48. package/src/tests/group.test.ts +13 -6
  49. package/src/tests/permissions.test.ts +648 -840
  50. package/src/tests/sync.test.ts +44 -68
  51. package/src/tests/testUtils.ts +6 -11
  52. package/src/typeUtils/expectGroup.ts +4 -4
  53. package/src/typeUtils/isCoValue.ts +11 -11
@@ -1,9 +1,10 @@
1
+ import { expect, test, beforeEach } from "vitest";
1
2
  import { newRandomSessionID } from "../coValueCore.js";
2
3
  import { LocalNode } from "../localNode.js";
3
4
  import { SyncMessage } from "../sync.js";
4
5
  import { expectMap } from "../coValue.js";
5
6
  import { MapOpPayload } from "../coValues/coMap.js";
6
- import { Group } from "../coValues/group.js";
7
+ import { RawGroup } from "../coValues/group.js";
7
8
  import {
8
9
  randomAnonymousAccountAndSessionID,
9
10
  shouldNotResolve,
@@ -13,6 +14,12 @@ import { AccountID } from "../coValues/account.js";
13
14
  import { cojsonReady } from "../index.js";
14
15
  import { stableStringify } from "../jsonStringify.js";
15
16
 
17
+ import { webcrypto } from "node:crypto";
18
+ if (!("crypto" in globalThis)) {
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ (globalThis as any).crypto = webcrypto;
21
+ }
22
+
16
23
  beforeEach(async () => {
17
24
  await cojsonReady;
18
25
  });
@@ -25,9 +32,7 @@ test("Node replies with initial tx and header to empty subscribe", async () => {
25
32
 
26
33
  const map = group.createMap();
27
34
 
28
- map.edit((editable) => {
29
- editable.set("hello", "world", "trusting");
30
- });
35
+ map.set("hello", "world", "trusting");
31
36
 
32
37
  const [inRx, inTx] = newStreamPair<SyncMessage>();
33
38
  const [outRx, outTx] = newStreamPair<SyncMessage>();
@@ -91,8 +96,8 @@ test("Node replies with initial tx and header to empty subscribe", async () => {
91
96
  ]),
92
97
  },
93
98
  ],
94
- lastSignature:
95
- map.core.sessionLogs.get(node.currentSessionID)!.lastSignature!,
99
+ lastSignature: map.core.sessionLogs.get(node.currentSessionID)!
100
+ .lastSignature!,
96
101
  },
97
102
  },
98
103
  } satisfies SyncMessage);
@@ -106,10 +111,8 @@ test("Node replies with only new tx to subscribe with some known state", async (
106
111
 
107
112
  const map = group.createMap();
108
113
 
109
- map.edit((editable) => {
110
- editable.set("hello", "world", "trusting");
111
- editable.set("goodbye", "world", "trusting");
112
- });
114
+ map.set("hello", "world", "trusting");
115
+ map.set("goodbye", "world", "trusting");
113
116
 
114
117
  const [inRx, inTx] = newStreamPair<SyncMessage>();
115
118
  const [outRx, outTx] = newStreamPair<SyncMessage>();
@@ -169,8 +172,8 @@ test("Node replies with only new tx to subscribe with some known state", async (
169
172
  ]),
170
173
  },
171
174
  ],
172
- lastSignature:
173
- map.core.sessionLogs.get(node.currentSessionID)!.lastSignature!,
175
+ lastSignature: map.core.sessionLogs.get(node.currentSessionID)!
176
+ .lastSignature!,
174
177
  },
175
178
  },
176
179
  } satisfies SyncMessage);
@@ -232,9 +235,7 @@ test("After subscribing, node sends own known state and new txs to peer", async
232
235
  new: {},
233
236
  } satisfies SyncMessage);
234
237
 
235
- map.edit((editable) => {
236
- editable.set("hello", "world", "trusting");
237
- });
238
+ map.set("hello", "world", "trusting");
238
239
 
239
240
  const mapEditMsg1 = await reader.read();
240
241
 
@@ -258,15 +259,13 @@ test("After subscribing, node sends own known state and new txs to peer", async
258
259
  ]),
259
260
  },
260
261
  ],
261
- lastSignature:
262
- map.core.sessionLogs.get(node.currentSessionID)!.lastSignature!,
262
+ lastSignature: map.core.sessionLogs.get(node.currentSessionID)!
263
+ .lastSignature!,
263
264
  },
264
265
  },
265
266
  } satisfies SyncMessage);
266
267
 
267
- map.edit((editable) => {
268
- editable.set("goodbye", "world", "trusting");
269
- });
268
+ map.set("goodbye", "world", "trusting");
270
269
 
271
270
  const mapEditMsg2 = await reader.read();
272
271
 
@@ -290,8 +289,8 @@ test("After subscribing, node sends own known state and new txs to peer", async
290
289
  ]),
291
290
  },
292
291
  ],
293
- lastSignature:
294
- map.core.sessionLogs.get(node.currentSessionID)!.lastSignature!,
292
+ lastSignature: map.core.sessionLogs.get(node.currentSessionID)!
293
+ .lastSignature!,
295
294
  },
296
295
  },
297
296
  } satisfies SyncMessage);
@@ -305,9 +304,7 @@ test("Client replies with known new content to tellKnownState from server", asyn
305
304
 
306
305
  const map = group.createMap();
307
306
 
308
- map.edit((editable) => {
309
- editable.set("hello", "world", "trusting");
310
- });
307
+ map.set("hello", "world", "trusting");
311
308
 
312
309
  const [inRx, inTx] = newStreamPair<SyncMessage>();
313
310
  const [outRx, outTx] = newStreamPair<SyncMessage>();
@@ -369,8 +366,8 @@ test("Client replies with known new content to tellKnownState from server", asyn
369
366
  ]),
370
367
  },
371
368
  ],
372
- lastSignature:
373
- map.core.sessionLogs.get(node.currentSessionID)!.lastSignature!,
369
+ lastSignature: map.core.sessionLogs.get(node.currentSessionID)!
370
+ .lastSignature!,
374
371
  },
375
372
  },
376
373
  } satisfies SyncMessage);
@@ -428,13 +425,9 @@ test("No matter the optimistic known state, node respects invalid known state me
428
425
  new: {},
429
426
  } satisfies SyncMessage);
430
427
 
431
- map.edit((editable) => {
432
- editable.set("hello", "world", "trusting");
433
- });
428
+ map.set("hello", "world", "trusting");
434
429
 
435
- map.edit((editable) => {
436
- editable.set("goodbye", "world", "trusting");
437
- });
430
+ map.set("goodbye", "world", "trusting");
438
431
 
439
432
  const _mapEditMsgs = await reader.read();
440
433
 
@@ -473,8 +466,8 @@ test("No matter the optimistic known state, node respects invalid known state me
473
466
  ]),
474
467
  },
475
468
  ],
476
- lastSignature:
477
- map.core.sessionLogs.get(node.currentSessionID)!.lastSignature!,
469
+ lastSignature: map.core.sessionLogs.get(node.currentSessionID)!
470
+ .lastSignature!,
478
471
  },
479
472
  },
480
473
  } satisfies SyncMessage);
@@ -498,9 +491,7 @@ test("If we add a peer, but it never subscribes to a coValue, it won't get any m
498
491
  role: "peer",
499
492
  });
500
493
 
501
- map.edit((editable) => {
502
- editable.set("hello", "world", "trusting");
503
- });
494
+ map.set("hello", "world", "trusting");
504
495
 
505
496
  const reader = outRx.getReader();
506
497
 
@@ -546,9 +537,7 @@ test("If we add a server peer, all updates to all coValues are sent to it, even
546
537
  sessions: {},
547
538
  } satisfies SyncMessage);
548
539
 
549
- map.edit((editable) => {
550
- editable.set("hello", "world", "trusting");
551
- });
540
+ map.set("hello", "world", "trusting");
552
541
 
553
542
  // expect((await reader.read()).value).toMatchObject(admContEx(admin.id));
554
543
  expect((await reader.read()).value).toMatchObject(groupContentEx(group));
@@ -576,8 +565,8 @@ test("If we add a server peer, all updates to all coValues are sent to it, even
576
565
  ]),
577
566
  },
578
567
  ],
579
- lastSignature:
580
- map.core.sessionLogs.get(node.currentSessionID)!.lastSignature!,
568
+ lastSignature: map.core.sessionLogs.get(node.currentSessionID)!
569
+ .lastSignature!,
581
570
  },
582
571
  },
583
572
  } satisfies SyncMessage);
@@ -769,9 +758,7 @@ test.skip("When replaying creation and transactions of a coValue as new content,
769
758
  expect(groupTellKnownStateMsg.value).toMatchObject(groupStateEx(group));
770
759
 
771
760
  expect(
772
- node2.syncManager.peers["test1"]!.optimisticKnownStates[
773
- group.core.id
774
- ]
761
+ node2.syncManager.peers["test1"]!.optimisticKnownStates[group.core.id]
775
762
  ).toBeDefined();
776
763
 
777
764
  // await to1.write(adminTellKnownStateMsg.value!);
@@ -816,9 +803,7 @@ test.skip("When replaying creation and transactions of a coValue as new content,
816
803
 
817
804
  await to2.write(mapNewContentMsg.value!);
818
805
 
819
- map.edit((editable) => {
820
- editable.set("hello", "world", "trusting");
821
- });
806
+ map.set("hello", "world", "trusting");
822
807
 
823
808
  const mapEditMsg = await from1.read();
824
809
 
@@ -842,9 +827,7 @@ test.skip("When loading a coValue on one node, the server node it is requested f
842
827
  const group = node1.createGroup();
843
828
 
844
829
  const map = group.createMap();
845
- map.edit((editable) => {
846
- editable.set("hello", "world", "trusting");
847
- });
830
+ map.set("hello", "world", "trusting");
848
831
 
849
832
  const node2 = new LocalNode(admin, newRandomSessionID(admin.id));
850
833
 
@@ -870,9 +853,7 @@ test("Can sync a coValue through a server to another client", async () => {
870
853
  const group = client1.createGroup();
871
854
 
872
855
  const map = group.createMap();
873
- map.edit((editable) => {
874
- editable.set("hello", "world", "trusting");
875
- });
856
+ map.set("hello", "world", "trusting");
876
857
 
877
858
  const [serverUser, serverSession] = randomAnonymousAccountAndSessionID();
878
859
 
@@ -880,7 +861,8 @@ test("Can sync a coValue through a server to another client", async () => {
880
861
 
881
862
  const [serverAsPeer, client1AsPeer] = connectedPeers("server", "client1", {
882
863
  peer1role: "server",
883
- peer2role: "client", trace: true,
864
+ peer2role: "client",
865
+ trace: true,
884
866
  });
885
867
 
886
868
  client1.syncManager.addPeer(serverAsPeer);
@@ -891,7 +873,7 @@ test("Can sync a coValue through a server to another client", async () => {
891
873
  const [serverAsOtherPeer, client2AsPeer] = connectedPeers(
892
874
  "server",
893
875
  "client2",
894
- { peer1role: "server", peer2role: "client", trace: true, }
876
+ { peer1role: "server", peer2role: "client", trace: true }
895
877
  );
896
878
 
897
879
  client2.syncManager.addPeer(serverAsOtherPeer);
@@ -915,9 +897,7 @@ test("Can sync a coValue with private transactions through a server to another c
915
897
  const group = client1.createGroup();
916
898
 
917
899
  const map = group.createMap();
918
- map.edit((editable) => {
919
- editable.set("hello", "world", "private");
920
- });
900
+ map.set("hello", "world", "private");
921
901
 
922
902
  const [serverUser, serverSession] = randomAnonymousAccountAndSessionID();
923
903
 
@@ -1057,9 +1037,7 @@ test("When a peer's outgoing/writable stream closes, we remove the peer", async
1057
1037
  reader.releaseLock();
1058
1038
  await outRx.cancel();
1059
1039
 
1060
- map.edit((editable) => {
1061
- editable.set("hello", "world", "trusting");
1062
- });
1040
+ map.set("hello", "world", "trusting");
1063
1041
 
1064
1042
  await new Promise((resolve) => setTimeout(resolve, 100));
1065
1043
 
@@ -1074,9 +1052,7 @@ test("If we start loading a coValue before connecting to a peer that has it, it
1074
1052
  const group = node1.createGroup();
1075
1053
 
1076
1054
  const map = group.createMap();
1077
- map.edit((editable) => {
1078
- editable.set("hello", "world", "trusting");
1079
- });
1055
+ map.set("hello", "world", "trusting");
1080
1056
 
1081
1057
  const node2 = new LocalNode(admin, newRandomSessionID(admin.id));
1082
1058
 
@@ -1104,7 +1080,7 @@ test("If we start loading a coValue before connecting to a peer that has it, it
1104
1080
  );
1105
1081
  });
1106
1082
 
1107
- function groupContentEx(group: Group) {
1083
+ function groupContentEx(group: RawGroup) {
1108
1084
  return {
1109
1085
  action: "content",
1110
1086
  id: group.core.id,
@@ -1118,7 +1094,7 @@ function admContEx(adminID: AccountID) {
1118
1094
  };
1119
1095
  }
1120
1096
 
1121
- function groupStateEx(group: Group) {
1097
+ function groupStateEx(group: RawGroup) {
1122
1098
  return {
1123
1099
  action: "known",
1124
1100
  id: group.core.id,
@@ -1,11 +1,10 @@
1
+ import { expect } from "vitest";
1
2
  import { AgentSecret, createdNowUnique, getAgentID, newRandomAgentSecret } from "../crypto.js";
2
3
  import { newRandomSessionID } from "../coValueCore.js";
3
4
  import { LocalNode } from "../localNode.js";
4
5
  import { expectGroup } from "../typeUtils/expectGroup.js";
5
6
  import { ControlledAgent } from "../coValues/account.js";
6
7
  import { SessionID } from "../ids.js";
7
- // @ts-ignore
8
- import { expect } from "bun:test";
9
8
 
10
9
  export function randomAnonymousAccountAndSessionID(): [ControlledAgent, SessionID] {
11
10
  const agentSecret = newRandomAgentSecret();
@@ -29,10 +28,8 @@ export function newGroup() {
29
28
 
30
29
  const group = expectGroup(groupCore.getCurrentContent());
31
30
 
32
- group.mutate((editable) => {
33
- editable.set(admin.id, "admin", "trusting");
34
- expect(editable.get(admin.id)).toEqual("admin");
35
- });
31
+ group.set(admin.id, "admin", "trusting");
32
+ expect(group.get(admin.id)).toEqual("admin");
36
33
 
37
34
  return { node, groupCore, admin };
38
35
  }
@@ -44,10 +41,8 @@ export function groupWithTwoAdmins() {
44
41
 
45
42
  let group = expectGroup(groupCore.getCurrentContent());
46
43
 
47
- group = group.mutate((mutable) => {
48
- mutable.set(otherAdmin.id, "admin", "trusting");
49
- expect(mutable.get(otherAdmin.id)).toEqual("admin");
50
- });
44
+ group.set(otherAdmin.id, "admin", "trusting");
45
+ expect(group.get(otherAdmin.id)).toEqual("admin");
51
46
 
52
47
  if (group.type !== "comap") {
53
48
  throw new Error("Expected map");
@@ -73,7 +68,7 @@ export function groupWithTwoAdminsHighLevel() {
73
68
 
74
69
  const otherAdmin = node.createAccount("otherAdmin");
75
70
 
76
- group = group.addMember(otherAdmin, "admin");
71
+ group.addMember(otherAdmin, "admin");
77
72
 
78
73
  return { admin, node, group, otherAdmin };
79
74
  }
@@ -1,13 +1,13 @@
1
- import { expectMap, type CoValue } from "../coValue.js";
2
- import { Group } from "../coValues/group.js";
1
+ import { expectMap, type RawCoValue } from "../coValue.js";
2
+ import { RawGroup } from "../coValues/group.js";
3
3
 
4
- export function expectGroup(content: CoValue): Group {
4
+ export function expectGroup(content: RawCoValue): RawGroup {
5
5
  const map = expectMap(content);
6
6
  if (map.core.header.ruleset.type !== "group") {
7
7
  throw new Error("Expected group ruleset in group");
8
8
  }
9
9
 
10
- if (!(map instanceof Group)) {
10
+ if (!(map instanceof RawGroup)) {
11
11
  throw new Error("Expected group");
12
12
  }
13
13
 
@@ -1,18 +1,18 @@
1
- import { type CoValue } from "../coValue.js";
1
+ import { type RawCoValue } from "../coValue.js";
2
2
  import type { JsonValue } from "../jsonValue.js";
3
- import { CoMap } from "../coValues/coMap.js";
4
- import { CoList } from "../coValues/coList.js";
5
- import { CoStream } from "../coValues/coStream.js";
6
- import { BinaryCoStream } from "../coValues/coStream.js";
3
+ import { RawCoMap } from "../coValues/coMap.js";
4
+ import { RawCoList } from "../coValues/coList.js";
5
+ import { RawCoStream } from "../coValues/coStream.js";
6
+ import { RawBinaryCoStream } from "../coValues/coStream.js";
7
7
 
8
8
 
9
9
  export function isCoValue(
10
- value: JsonValue | CoValue | undefined
11
- ): value is CoValue {
10
+ value: JsonValue | RawCoValue | undefined
11
+ ): value is RawCoValue {
12
12
  return (
13
- value instanceof CoMap ||
14
- value instanceof CoList ||
15
- value instanceof CoStream ||
16
- value instanceof BinaryCoStream
13
+ value instanceof RawCoMap ||
14
+ value instanceof RawCoList ||
15
+ value instanceof RawCoStream ||
16
+ value instanceof RawBinaryCoStream
17
17
  );
18
18
  }