jazz-tools 0.8.15 → 0.8.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. package/CHANGELOG.md +283 -269
  2. package/dist/native/coValues/account.js +3 -6
  3. package/dist/native/coValues/account.js.map +1 -1
  4. package/dist/native/coValues/coList.js +3 -7
  5. package/dist/native/coValues/coList.js.map +1 -1
  6. package/dist/native/coValues/coMap.js +8 -14
  7. package/dist/native/coValues/coMap.js.map +1 -1
  8. package/dist/native/coValues/coStream.js +7 -12
  9. package/dist/native/coValues/coStream.js.map +1 -1
  10. package/dist/native/coValues/deepLoading.js +6 -3
  11. package/dist/native/coValues/deepLoading.js.map +1 -1
  12. package/dist/native/coValues/extensions/imageDef.js.map +1 -1
  13. package/dist/native/coValues/group.js +3 -6
  14. package/dist/native/coValues/group.js.map +1 -1
  15. package/dist/native/coValues/interfaces.js +4 -3
  16. package/dist/native/coValues/interfaces.js.map +1 -1
  17. package/dist/native/exports.js +3 -9
  18. package/dist/native/exports.js.map +1 -1
  19. package/dist/native/implementation/createContext.js +1 -2
  20. package/dist/native/implementation/createContext.js.map +1 -1
  21. package/dist/native/implementation/devtoolsFormatters.js +5 -25
  22. package/dist/native/implementation/devtoolsFormatters.js.map +1 -1
  23. package/dist/native/implementation/refs.js +1 -2
  24. package/dist/native/implementation/refs.js.map +1 -1
  25. package/dist/native/implementation/schema.js +1 -1
  26. package/dist/native/implementation/schema.js.map +1 -1
  27. package/dist/native/implementation/subscriptionScope.js +2 -4
  28. package/dist/native/implementation/subscriptionScope.js.map +1 -1
  29. package/dist/native/index.native.js +1 -1
  30. package/dist/native/index.native.js.map +1 -1
  31. package/dist/native/lib/cache.js.map +1 -1
  32. package/dist/native/lib/cache.test.js +1 -1
  33. package/dist/native/lib/cache.test.js.map +1 -1
  34. package/dist/web/coValues/account.js +3 -6
  35. package/dist/web/coValues/account.js.map +1 -1
  36. package/dist/web/coValues/coList.js +3 -7
  37. package/dist/web/coValues/coList.js.map +1 -1
  38. package/dist/web/coValues/coMap.js +8 -14
  39. package/dist/web/coValues/coMap.js.map +1 -1
  40. package/dist/web/coValues/coStream.js +7 -12
  41. package/dist/web/coValues/coStream.js.map +1 -1
  42. package/dist/web/coValues/deepLoading.js +6 -3
  43. package/dist/web/coValues/deepLoading.js.map +1 -1
  44. package/dist/web/coValues/extensions/imageDef.js.map +1 -1
  45. package/dist/web/coValues/group.js +3 -6
  46. package/dist/web/coValues/group.js.map +1 -1
  47. package/dist/web/coValues/interfaces.js +4 -3
  48. package/dist/web/coValues/interfaces.js.map +1 -1
  49. package/dist/web/exports.js +3 -9
  50. package/dist/web/exports.js.map +1 -1
  51. package/dist/web/implementation/createContext.js +1 -2
  52. package/dist/web/implementation/createContext.js.map +1 -1
  53. package/dist/web/implementation/devtoolsFormatters.js +5 -25
  54. package/dist/web/implementation/devtoolsFormatters.js.map +1 -1
  55. package/dist/web/implementation/refs.js +1 -2
  56. package/dist/web/implementation/refs.js.map +1 -1
  57. package/dist/web/implementation/schema.js +1 -1
  58. package/dist/web/implementation/schema.js.map +1 -1
  59. package/dist/web/implementation/subscriptionScope.js +2 -4
  60. package/dist/web/implementation/subscriptionScope.js.map +1 -1
  61. package/dist/web/lib/cache.js.map +1 -1
  62. package/dist/web/lib/cache.test.js +1 -1
  63. package/dist/web/lib/cache.test.js.map +1 -1
  64. package/package.json +5 -9
  65. package/src/coValues/account.ts +330 -339
  66. package/src/coValues/coList.ts +474 -495
  67. package/src/coValues/coMap.ts +584 -604
  68. package/src/coValues/coStream.ts +624 -650
  69. package/src/coValues/deepLoading.ts +184 -200
  70. package/src/coValues/extensions/imageDef.ts +44 -44
  71. package/src/coValues/group.ts +196 -210
  72. package/src/coValues/interfaces.ts +197 -199
  73. package/src/exports.ts +38 -26
  74. package/src/implementation/createContext.ts +206 -213
  75. package/src/implementation/devtoolsFormatters.ts +80 -100
  76. package/src/implementation/refs.ts +127 -139
  77. package/src/implementation/schema.ts +124 -128
  78. package/src/implementation/subscriptionScope.ts +111 -121
  79. package/src/index.native.ts +3 -3
  80. package/src/lib/cache.test.ts +48 -48
  81. package/src/lib/cache.ts +9 -9
  82. package/src/tests/coList.test.ts +264 -283
  83. package/src/tests/coMap.test.ts +741 -761
  84. package/src/tests/coStream.test.ts +405 -438
  85. package/src/tests/deepLoading.test.ts +251 -256
  86. package/src/tests/groupsAndAccounts.test.ts +70 -74
  87. package/src/tests/schema.test.ts +198 -198
  88. package/src/tests/subscribe.test.ts +312 -299
  89. package/tsconfig.json +2 -4
  90. package/tsconfig.native.json +4 -10
  91. package/tsconfig.web.json +4 -10
  92. package/.eslintrc.cjs +0 -24
  93. package/.prettierrc.js +0 -9
@@ -1,905 +1,885 @@
1
- import { expect, describe, test, expectTypeOf } from "vitest";
2
1
  import { connectedPeers } from "cojson/src/streamUtils.ts";
2
+ import { describe, expect, expectTypeOf, test } from "vitest";
3
3
  import {
4
- Account,
5
- Encoders,
6
- CoMap,
7
- co,
8
- WasmCrypto,
9
- isControlledAccount,
10
- cojsonInternals,
11
- createJazzContext,
12
- fixedCredentialsAuth,
4
+ Account,
5
+ CoMap,
6
+ Encoders,
7
+ WasmCrypto,
8
+ co,
9
+ cojsonInternals,
10
+ createJazzContext,
11
+ fixedCredentialsAuth,
12
+ isControlledAccount,
13
13
  } from "../index.web.js";
14
14
  import { Group, randomSessionProvider } from "../internal.js";
15
15
 
16
16
  const Crypto = await WasmCrypto.create();
17
17
 
18
18
  class TestMap extends CoMap {
19
- color = co.string;
20
- _height = co.number;
21
- birthday = co.Date;
22
- name? = co.string;
23
- nullable = co.optional.encoded<string | undefined>({
24
- encode: (value: string | undefined) => value || null,
25
- decode: (value: unknown) => (value as string) || undefined,
26
- });
27
- optionalDate = co.optional.encoded(Encoders.Date);
28
-
29
- get roughColor() {
30
- return this.color + "ish";
31
- }
19
+ color = co.string;
20
+ _height = co.number;
21
+ birthday = co.Date;
22
+ name? = co.string;
23
+ nullable = co.optional.encoded<string | undefined>({
24
+ encode: (value: string | undefined) => value || null,
25
+ decode: (value: unknown) => (value as string) || undefined,
26
+ });
27
+ optionalDate = co.optional.encoded(Encoders.Date);
28
+
29
+ get roughColor() {
30
+ return this.color + "ish";
31
+ }
32
32
  }
33
33
 
34
34
  describe("Simple CoMap operations", async () => {
35
- const me = await Account.create({
36
- creationProps: { name: "Hermes Puggington" },
37
- crypto: Crypto,
38
- });
39
-
40
- console.log("TestMap schema", TestMap.prototype._schema);
35
+ const me = await Account.create({
36
+ creationProps: { name: "Hermes Puggington" },
37
+ crypto: Crypto,
38
+ });
39
+
40
+ console.log("TestMap schema", TestMap.prototype._schema);
41
+
42
+ const birthday = new Date();
43
+
44
+ const map = TestMap.create(
45
+ {
46
+ color: "red",
47
+ _height: 10,
48
+ birthday: birthday,
49
+ nullable: undefined,
50
+ },
51
+ { owner: me },
52
+ );
53
+
54
+ test("Construction", () => {
55
+ expect(map.color).toEqual("red");
56
+ expect(map.roughColor).toEqual("redish");
57
+ expect(map._height).toEqual(10);
58
+ expect(map.birthday).toEqual(birthday);
59
+ expect(map._raw.get("birthday")).toEqual(birthday.toISOString());
60
+ expect(Object.keys(map)).toEqual([
61
+ "color",
62
+ "_height",
63
+ "birthday",
64
+ "nullable",
65
+ ]);
66
+ });
67
+
68
+ test("Construction with too many things provided", () => {
69
+ const mapWithExtra = TestMap.create(
70
+ {
71
+ color: "red",
72
+ _height: 10,
73
+ birthday: birthday,
74
+ name: "Hermes",
75
+ extra: "extra",
76
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
+ } as any,
78
+ { owner: me },
79
+ );
41
80
 
42
- const birthday = new Date();
81
+ expect(mapWithExtra.color).toEqual("red");
82
+ });
83
+
84
+ describe("Mutation", () => {
85
+ test("assignment & deletion", () => {
86
+ map.color = "blue";
87
+ expect(map.color).toEqual("blue");
88
+ expect(map._raw.get("color")).toEqual("blue");
89
+ const newBirthday = new Date();
90
+ map.birthday = newBirthday;
91
+ expect(map.birthday).toEqual(newBirthday);
92
+ expect(map._raw.get("birthday")).toEqual(newBirthday.toISOString());
93
+
94
+ Object.assign(map, { color: "green", _height: 20 });
95
+ expect(map.color).toEqual("green");
96
+ expect(map._raw.get("color")).toEqual("green");
97
+ expect(map._height).toEqual(20);
98
+ expect(map._raw.get("_height")).toEqual(20);
99
+
100
+ map.nullable = "not null";
101
+ map.nullable = undefined;
102
+ delete map.nullable;
103
+ map.nullable = undefined;
104
+
105
+ map.name = "Secret name";
106
+ expect(map.name).toEqual("Secret name");
107
+ map.name = undefined;
108
+ expect(map.name).toEqual(undefined);
109
+ expect(Object.keys(map)).toContain("name");
110
+ delete map.name;
111
+ expect(map.name).toEqual(undefined);
112
+ expect(Object.keys(map)).not.toContain("name");
113
+ });
114
+ });
43
115
 
44
- const map = TestMap.create(
116
+ describe("property existence", () => {
117
+ class TestMap extends CoMap.Record(co.string) {}
118
+ test("CoMap", () => {
119
+ const map = TestMap.create(
120
+ { name: "test" },
45
121
  {
46
- color: "red",
47
- _height: 10,
48
- birthday: birthday,
49
- nullable: undefined,
122
+ owner: me,
50
123
  },
51
- { owner: me },
52
- );
124
+ );
53
125
 
54
- test("Construction", () => {
55
- expect(map.color).toEqual("red");
56
- expect(map.roughColor).toEqual("redish");
57
- expect(map._height).toEqual(10);
58
- expect(map.birthday).toEqual(birthday);
59
- expect(map._raw.get("birthday")).toEqual(birthday.toISOString());
60
- expect(Object.keys(map)).toEqual([
61
- "color",
62
- "_height",
63
- "birthday",
64
- "nullable",
65
- ]);
126
+ expect("name" in map).toBe(true);
127
+ expect("something" in map).toBe(false);
66
128
  });
129
+ });
67
130
 
68
- test("Construction with too many things provided", () => {
69
- const mapWithExtra = TestMap.create(
131
+ class RecursiveMap extends CoMap {
132
+ name = co.string;
133
+ next?: co<RecursiveMap | null> = co.ref(RecursiveMap);
134
+ }
135
+
136
+ const recursiveMap = RecursiveMap.create(
137
+ {
138
+ name: "first",
139
+ next: RecursiveMap.create(
140
+ {
141
+ name: "second",
142
+ next: RecursiveMap.create(
70
143
  {
71
- color: "red",
72
- _height: 10,
73
- birthday: birthday,
74
- name: "Hermes",
75
- extra: "extra",
76
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
- } as any,
144
+ name: "third",
145
+ },
78
146
  { owner: me },
79
- );
80
-
81
- expect(mapWithExtra.color).toEqual("red");
82
- });
83
-
84
- describe("Mutation", () => {
85
- test("assignment & deletion", () => {
86
- map.color = "blue";
87
- expect(map.color).toEqual("blue");
88
- expect(map._raw.get("color")).toEqual("blue");
89
- const newBirthday = new Date();
90
- map.birthday = newBirthday;
91
- expect(map.birthday).toEqual(newBirthday);
92
- expect(map._raw.get("birthday")).toEqual(newBirthday.toISOString());
93
-
94
- Object.assign(map, { color: "green", _height: 20 });
95
- expect(map.color).toEqual("green");
96
- expect(map._raw.get("color")).toEqual("green");
97
- expect(map._height).toEqual(20);
98
- expect(map._raw.get("_height")).toEqual(20);
99
-
100
- map.nullable = "not null";
101
- map.nullable = undefined;
102
- delete map.nullable;
103
- map.nullable = undefined;
104
-
105
- map.name = "Secret name";
106
- expect(map.name).toEqual("Secret name");
107
- map.name = undefined;
108
- expect(map.name).toEqual(undefined);
109
- expect(Object.keys(map)).toContain("name");
110
- delete map.name;
111
- expect(map.name).toEqual(undefined);
112
- expect(Object.keys(map)).not.toContain("name");
113
- });
114
- });
147
+ ),
148
+ },
149
+ { owner: me },
150
+ ),
151
+ },
152
+ { owner: me },
153
+ );
115
154
 
116
- describe("property existence", () => {
117
- class TestMap extends CoMap.Record(co.string) {}
118
- test("CoMap", () => {
119
- const map = TestMap.create(
120
- { name: "test" },
121
- {
122
- owner: me,
123
- },
124
- );
125
-
126
- expect("name" in map).toBe(true);
127
- expect("something" in map).toBe(false);
128
- });
155
+ describe("Recursive CoMap", () => {
156
+ test("Construction", () => {
157
+ expect(recursiveMap.name).toEqual("first");
158
+ expect(recursiveMap.next?.name).toEqual("second");
159
+ expect(recursiveMap.next?.next?.name).toEqual("third");
129
160
  });
161
+ });
130
162
 
131
- class RecursiveMap extends CoMap {
132
- name = co.string;
133
- next?: co<RecursiveMap | null> = co.ref(RecursiveMap);
134
- }
135
-
136
- const recursiveMap = RecursiveMap.create(
163
+ class MapWithEnumOfMaps extends CoMap {
164
+ name = co.string;
165
+ child = co.ref<typeof ChildA | typeof ChildB>((raw) =>
166
+ raw.get("type") === "a" ? ChildA : ChildB,
167
+ );
168
+ }
169
+
170
+ class ChildA extends CoMap {
171
+ type = co.literal("a");
172
+ value = co.number;
173
+ }
174
+
175
+ class ChildB extends CoMap {
176
+ type = co.literal("b");
177
+ value = co.string;
178
+ }
179
+
180
+ const mapWithEnum = MapWithEnumOfMaps.create(
181
+ {
182
+ name: "enum",
183
+ child: ChildA.create(
137
184
  {
138
- name: "first",
139
- next: RecursiveMap.create(
140
- {
141
- name: "second",
142
- next: RecursiveMap.create(
143
- {
144
- name: "third",
145
- },
146
- { owner: me },
147
- ),
148
- },
149
- { owner: me },
150
- ),
185
+ type: "a",
186
+ value: 5,
151
187
  },
152
188
  { owner: me },
153
- );
189
+ ),
190
+ },
191
+ { owner: me },
192
+ );
193
+
194
+ test("Enum of maps", () => {
195
+ expect(mapWithEnum.name).toEqual("enum");
196
+ expect(mapWithEnum.child?.type).toEqual("a");
197
+ expect(mapWithEnum.child?.value).toEqual(5);
198
+ expect(mapWithEnum.child?.id).toBeDefined();
199
+ });
200
+
201
+ class SuperClassMap extends CoMap {
202
+ name = co.string;
203
+ }
204
+
205
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
206
+ class SubClassMap extends SuperClassMap {
207
+ name = co.literal("specificString");
208
+ value = co.number;
209
+ extra = co.ref(TestMap);
210
+ }
211
+
212
+ class GenericMapWithLoose<out T extends string = string> extends CoMap {
213
+ name = co.json<T>();
214
+ }
215
+
216
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
217
+ const loose: GenericMapWithLoose<string> = {} as GenericMapWithLoose<
218
+ "a" | "b"
219
+ >;
220
+ });
154
221
 
155
- describe("Recursive CoMap", () => {
156
- test("Construction", () => {
157
- expect(recursiveMap.name).toEqual("first");
158
- expect(recursiveMap.next?.name).toEqual("second");
159
- expect(recursiveMap.next?.next?.name).toEqual("third");
160
- });
161
- });
222
+ describe("CoMap resolution", async () => {
223
+ class TwiceNestedMap extends CoMap {
224
+ taste = co.string;
225
+ }
162
226
 
163
- class MapWithEnumOfMaps extends CoMap {
164
- name = co.string;
165
- child = co.ref<typeof ChildA | typeof ChildB>((raw) =>
166
- raw.get("type") === "a" ? ChildA : ChildB,
167
- );
168
- }
227
+ class NestedMap extends CoMap {
228
+ name = co.string;
229
+ twiceNested = co.ref(TwiceNestedMap);
169
230
 
170
- class ChildA extends CoMap {
171
- type = co.literal("a");
172
- value = co.number;
231
+ get _fancyName() {
232
+ return "Sir " + this.name;
173
233
  }
234
+ }
235
+
236
+ class TestMap extends CoMap {
237
+ color = co.string;
238
+ height = co.number;
239
+ nested = co.ref(NestedMap);
174
240
 
175
- class ChildB extends CoMap {
176
- type = co.literal("b");
177
- value = co.string;
241
+ get _roughColor() {
242
+ return this.color + "ish";
178
243
  }
244
+ }
179
245
 
180
- const mapWithEnum = MapWithEnumOfMaps.create(
181
- {
182
- name: "enum",
183
- child: ChildA.create(
184
- {
185
- type: "a",
186
- value: 5,
187
- },
188
- { owner: me },
246
+ const initNodeAndMap = async () => {
247
+ const me = await Account.create({
248
+ creationProps: { name: "Hermes Puggington" },
249
+ crypto: Crypto,
250
+ });
251
+
252
+ const map = TestMap.create(
253
+ {
254
+ color: "red",
255
+ height: 10,
256
+ nested: NestedMap.create(
257
+ {
258
+ name: "nested",
259
+ twiceNested: TwiceNestedMap.create(
260
+ { taste: "sour" },
261
+ { owner: me },
189
262
  ),
190
- },
191
- { owner: me },
263
+ },
264
+ { owner: me },
265
+ ),
266
+ },
267
+ { owner: me },
192
268
  );
193
269
 
194
- test("Enum of maps", () => {
195
- expect(mapWithEnum.name).toEqual("enum");
196
- expect(mapWithEnum.child?.type).toEqual("a");
197
- expect(mapWithEnum.child?.value).toEqual(5);
198
- expect(mapWithEnum.child?.id).toBeDefined();
199
- });
270
+ return { me, map };
271
+ };
200
272
 
201
- class SuperClassMap extends CoMap {
202
- name = co.string;
203
- }
273
+ test("Construction", async () => {
274
+ const { map } = await initNodeAndMap();
204
275
 
205
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
206
- class SubClassMap extends SuperClassMap {
207
- name = co.literal("specificString");
208
- value = co.number;
209
- extra = co.ref(TestMap);
210
- }
276
+ // const test: Schema.Schema.To<typeof NestedMap>
211
277
 
212
- class GenericMapWithLoose<out T extends string = string> extends CoMap {
213
- name = co.json<T>();
214
- }
278
+ expect(map.color).toEqual("red");
279
+ expect(map._roughColor).toEqual("redish");
280
+ expect(map.height).toEqual(10);
281
+ expect(map.nested?.name).toEqual("nested");
282
+ expect(map.nested?._fancyName).toEqual("Sir nested");
283
+ expect(map.nested?.id).toBeDefined();
284
+ expect(map.nested?.twiceNested?.taste).toEqual("sour");
285
+ });
215
286
 
216
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
217
- const loose: GenericMapWithLoose<string> = {} as GenericMapWithLoose<
218
- "a" | "b"
219
- >;
220
- });
287
+ test("Loading and availability", async () => {
288
+ const { me, map } = await initNodeAndMap();
289
+ const [initialAsPeer, secondPeer] = connectedPeers("initial", "second", {
290
+ peer1role: "server",
291
+ peer2role: "client",
292
+ });
221
293
 
222
- describe("CoMap resolution", async () => {
223
- class TwiceNestedMap extends CoMap {
224
- taste = co.string;
294
+ if (!isControlledAccount(me)) {
295
+ throw "me is not a controlled account";
225
296
  }
297
+ me._raw.core.node.syncManager.addPeer(secondPeer);
298
+ const { account: meOnSecondPeer } = await createJazzContext({
299
+ auth: fixedCredentialsAuth({
300
+ accountID: me.id,
301
+ secret: me._raw.agentSecret,
302
+ }),
303
+ sessionProvider: randomSessionProvider,
304
+ peersToLoadFrom: [initialAsPeer],
305
+ crypto: Crypto,
306
+ });
226
307
 
227
- class NestedMap extends CoMap {
228
- name = co.string;
229
- twiceNested = co.ref(TwiceNestedMap);
308
+ const loadedMap = await TestMap.load(map.id, meOnSecondPeer, {});
230
309
 
231
- get _fancyName() {
232
- return "Sir " + this.name;
233
- }
234
- }
310
+ expect(loadedMap?.color).toEqual("red");
311
+ expect(loadedMap?.height).toEqual(10);
312
+ expect(loadedMap?.nested).toEqual(null);
313
+ expect(loadedMap?._refs.nested?.id).toEqual(map.nested?.id);
314
+ expect(loadedMap?._refs.nested?.value).toEqual(null);
235
315
 
236
- class TestMap extends CoMap {
237
- color = co.string;
238
- height = co.number;
239
- nested = co.ref(NestedMap);
316
+ const loadedNestedMap = await NestedMap.load(
317
+ map.nested!.id,
318
+ meOnSecondPeer,
319
+ {},
320
+ );
240
321
 
241
- get _roughColor() {
242
- return this.color + "ish";
243
- }
244
- }
322
+ expect(loadedMap?.nested?.name).toEqual("nested");
323
+ expect(loadedMap?.nested?._fancyName).toEqual("Sir nested");
324
+ expect(loadedMap?._refs.nested?.value).toEqual(loadedNestedMap);
325
+ expect(loadedMap?.nested?.twiceNested?.taste).toEqual(undefined);
326
+
327
+ const loadedTwiceNestedMap = await TwiceNestedMap.load(
328
+ map.nested!.twiceNested!.id,
329
+ meOnSecondPeer,
330
+ {},
331
+ );
245
332
 
246
- const initNodeAndMap = async () => {
247
- const me = await Account.create({
248
- creationProps: { name: "Hermes Puggington" },
249
- crypto: Crypto,
250
- });
333
+ expect(loadedMap?.nested?.twiceNested?.taste).toEqual("sour");
334
+ expect(loadedMap?.nested?._refs.twiceNested?.value).toEqual(
335
+ loadedTwiceNestedMap,
336
+ );
251
337
 
252
- const map = TestMap.create(
253
- {
254
- color: "red",
255
- height: 10,
256
- nested: NestedMap.create(
257
- {
258
- name: "nested",
259
- twiceNested: TwiceNestedMap.create(
260
- { taste: "sour" },
261
- { owner: me },
262
- ),
263
- },
264
- { owner: me },
265
- ),
266
- },
267
- { owner: me },
268
- );
338
+ const otherNestedMap = NestedMap.create(
339
+ {
340
+ name: "otherNested",
341
+ twiceNested: TwiceNestedMap.create(
342
+ { taste: "sweet" },
343
+ { owner: meOnSecondPeer },
344
+ ),
345
+ },
346
+ { owner: meOnSecondPeer },
347
+ );
269
348
 
270
- return { me, map };
271
- };
349
+ loadedMap!.nested = otherNestedMap;
350
+ expect(loadedMap?.nested?.name).toEqual("otherNested");
351
+ expect(loadedMap?._refs.nested?.id).toEqual(otherNestedMap.id);
352
+ expect(loadedMap?._refs.nested?.value).toEqual(otherNestedMap);
353
+ expect(loadedMap?.nested?.twiceNested?.taste).toEqual("sweet");
354
+ expect(loadedMap?.nested?._refs.twiceNested?.value).toBeDefined();
355
+ });
272
356
 
273
- test("Construction", async () => {
274
- const { map } = await initNodeAndMap();
357
+ test("Subscription & auto-resolution", async () => {
358
+ const { me, map } = await initNodeAndMap();
275
359
 
276
- // const test: Schema.Schema.To<typeof NestedMap>
360
+ const [initialAsPeer, secondAsPeer] = connectedPeers("initial", "second", {
361
+ peer1role: "server",
362
+ peer2role: "client",
363
+ });
277
364
 
278
- expect(map.color).toEqual("red");
279
- expect(map._roughColor).toEqual("redish");
280
- expect(map.height).toEqual(10);
281
- expect(map.nested?.name).toEqual("nested");
282
- expect(map.nested?._fancyName).toEqual("Sir nested");
283
- expect(map.nested?.id).toBeDefined();
284
- expect(map.nested?.twiceNested?.taste).toEqual("sour");
365
+ if (!isControlledAccount(me)) {
366
+ throw "me is not a controlled account";
367
+ }
368
+ me._raw.core.node.syncManager.addPeer(secondAsPeer);
369
+ const { account: meOnSecondPeer } = await createJazzContext({
370
+ auth: fixedCredentialsAuth({
371
+ accountID: me.id,
372
+ secret: me._raw.agentSecret,
373
+ }),
374
+ sessionProvider: randomSessionProvider,
375
+ peersToLoadFrom: [initialAsPeer],
376
+ crypto: Crypto,
285
377
  });
286
378
 
287
- test("Loading and availability", async () => {
288
- const { me, map } = await initNodeAndMap();
289
- const [initialAsPeer, secondPeer] = connectedPeers(
290
- "initial",
291
- "second",
292
- {
293
- peer1role: "server",
294
- peer2role: "client",
295
- },
296
- );
297
-
298
- if (!isControlledAccount(me)) {
299
- throw "me is not a controlled account";
300
- }
301
- me._raw.core.node.syncManager.addPeer(secondPeer);
302
- const { account: meOnSecondPeer } = await createJazzContext({
303
- auth: fixedCredentialsAuth({
304
- accountID: me.id,
305
- secret: me._raw.agentSecret,
306
- }),
307
- sessionProvider: randomSessionProvider,
308
- peersToLoadFrom: [initialAsPeer],
309
- crypto: Crypto,
310
- });
311
-
312
- const loadedMap = await TestMap.load(map.id, meOnSecondPeer, {});
313
-
314
- expect(loadedMap?.color).toEqual("red");
315
- expect(loadedMap?.height).toEqual(10);
316
- expect(loadedMap?.nested).toEqual(null);
317
- expect(loadedMap?._refs.nested?.id).toEqual(map.nested?.id);
318
- expect(loadedMap?._refs.nested?.value).toEqual(null);
319
-
320
- const loadedNestedMap = await NestedMap.load(
321
- map.nested!.id,
322
- meOnSecondPeer,
323
- {},
324
- );
325
-
326
- expect(loadedMap?.nested?.name).toEqual("nested");
327
- expect(loadedMap?.nested?._fancyName).toEqual("Sir nested");
328
- expect(loadedMap?._refs.nested?.value).toEqual(loadedNestedMap);
329
- expect(loadedMap?.nested?.twiceNested?.taste).toEqual(undefined);
330
-
331
- const loadedTwiceNestedMap = await TwiceNestedMap.load(
332
- map.nested!.twiceNested!.id,
333
- meOnSecondPeer,
334
- {},
335
- );
336
-
337
- expect(loadedMap?.nested?.twiceNested?.taste).toEqual("sour");
338
- expect(loadedMap?.nested?._refs.twiceNested?.value).toEqual(
339
- loadedTwiceNestedMap,
340
- );
341
-
342
- const otherNestedMap = NestedMap.create(
343
- {
344
- name: "otherNested",
345
- twiceNested: TwiceNestedMap.create(
346
- { taste: "sweet" },
347
- { owner: meOnSecondPeer },
348
- ),
349
- },
350
- { owner: meOnSecondPeer },
351
- );
352
-
353
- loadedMap!.nested = otherNestedMap;
354
- expect(loadedMap?.nested?.name).toEqual("otherNested");
355
- expect(loadedMap?._refs.nested?.id).toEqual(otherNestedMap.id);
356
- expect(loadedMap?._refs.nested?.value).toEqual(otherNestedMap);
357
- expect(loadedMap?.nested?.twiceNested?.taste).toEqual("sweet");
358
- expect(loadedMap?.nested?._refs.twiceNested?.value).toBeDefined();
379
+ const queue = new cojsonInternals.Channel<TestMap>();
380
+
381
+ TestMap.subscribe(map.id, meOnSecondPeer, {}, (subscribedMap) => {
382
+ console.log(
383
+ "subscribedMap.nested?.twiceNested?.taste",
384
+ subscribedMap.nested?.twiceNested?.taste,
385
+ );
386
+ void queue.push(subscribedMap);
359
387
  });
360
388
 
361
- test("Subscription & auto-resolution", async () => {
362
- const { me, map } = await initNodeAndMap();
389
+ const update1 = (await queue.next()).value;
390
+ expect(update1.nested).toEqual(null);
363
391
 
364
- const [initialAsPeer, secondAsPeer] = connectedPeers(
365
- "initial",
366
- "second",
367
- {
368
- peer1role: "server",
369
- peer2role: "client",
370
- },
371
- );
372
-
373
- if (!isControlledAccount(me)) {
374
- throw "me is not a controlled account";
375
- }
376
- me._raw.core.node.syncManager.addPeer(secondAsPeer);
377
- const { account: meOnSecondPeer } = await createJazzContext({
378
- auth: fixedCredentialsAuth({
379
- accountID: me.id,
380
- secret: me._raw.agentSecret,
381
- }),
382
- sessionProvider: randomSessionProvider,
383
- peersToLoadFrom: [initialAsPeer],
384
- crypto: Crypto,
385
- });
386
-
387
- const queue = new cojsonInternals.Channel<TestMap>();
388
-
389
- TestMap.subscribe(map.id, meOnSecondPeer, {}, (subscribedMap) => {
390
- console.log(
391
- "subscribedMap.nested?.twiceNested?.taste",
392
- subscribedMap.nested?.twiceNested?.taste,
393
- );
394
- void queue.push(subscribedMap);
395
- });
396
-
397
- const update1 = (await queue.next()).value;
398
- expect(update1.nested).toEqual(null);
399
-
400
- const update2 = (await queue.next()).value;
401
- expect(update2.nested?.name).toEqual("nested");
402
-
403
- map.nested!.name = "nestedUpdated";
404
-
405
- const _ = (await queue.next()).value;
406
- const update3 = (await queue.next()).value;
407
- expect(update3.nested?.name).toEqual("nestedUpdated");
408
-
409
- const oldTwiceNested = update3.nested!.twiceNested;
410
- expect(oldTwiceNested?.taste).toEqual("sour");
411
-
412
- // When assigning a new nested value, we get an update
413
- const newTwiceNested = TwiceNestedMap.create(
414
- {
415
- taste: "sweet",
416
- },
417
- { owner: meOnSecondPeer },
418
- );
392
+ const update2 = (await queue.next()).value;
393
+ expect(update2.nested?.name).toEqual("nested");
419
394
 
420
- const newNested = NestedMap.create(
421
- {
422
- name: "newNested",
423
- twiceNested: newTwiceNested,
424
- },
425
- { owner: meOnSecondPeer },
426
- );
395
+ map.nested!.name = "nestedUpdated";
427
396
 
428
- update3.nested = newNested;
397
+ const _ = (await queue.next()).value;
398
+ const update3 = (await queue.next()).value;
399
+ expect(update3.nested?.name).toEqual("nestedUpdated");
429
400
 
430
- (await queue.next()).value;
431
- // const update4 = (await queue.next()).value;
432
- const update4b = (await queue.next()).value;
401
+ const oldTwiceNested = update3.nested!.twiceNested;
402
+ expect(oldTwiceNested?.taste).toEqual("sour");
433
403
 
434
- expect(update4b.nested?.name).toEqual("newNested");
435
- expect(update4b.nested?.twiceNested?.taste).toEqual("sweet");
404
+ // When assigning a new nested value, we get an update
405
+ const newTwiceNested = TwiceNestedMap.create(
406
+ {
407
+ taste: "sweet",
408
+ },
409
+ { owner: meOnSecondPeer },
410
+ );
436
411
 
437
- // we get updates when the new nested value changes
438
- newTwiceNested.taste = "salty";
439
- const update5 = (await queue.next()).value;
440
- expect(update5.nested?.twiceNested?.taste).toEqual("salty");
412
+ const newNested = NestedMap.create(
413
+ {
414
+ name: "newNested",
415
+ twiceNested: newTwiceNested,
416
+ },
417
+ { owner: meOnSecondPeer },
418
+ );
441
419
 
442
- newTwiceNested.taste = "umami";
443
- const update6 = (await queue.next()).value;
444
- expect(update6.nested?.twiceNested?.taste).toEqual("umami");
445
- });
420
+ update3.nested = newNested;
446
421
 
447
- class TestMapWithOptionalRef extends CoMap {
448
- color = co.string;
449
- nested = co.optional.ref(NestedMap);
450
- }
422
+ (await queue.next()).value;
423
+ // const update4 = (await queue.next()).value;
424
+ const update4b = (await queue.next()).value;
451
425
 
452
- test("Construction with optional", async () => {
453
- const me = await Account.create({
454
- creationProps: { name: "Hermes Puggington" },
455
- crypto: Crypto,
456
- });
426
+ expect(update4b.nested?.name).toEqual("newNested");
427
+ expect(update4b.nested?.twiceNested?.taste).toEqual("sweet");
457
428
 
458
- const mapWithout = TestMapWithOptionalRef.create(
459
- {
460
- color: "red",
461
- },
462
- { owner: me },
463
- );
429
+ // we get updates when the new nested value changes
430
+ newTwiceNested.taste = "salty";
431
+ const update5 = (await queue.next()).value;
432
+ expect(update5.nested?.twiceNested?.taste).toEqual("salty");
464
433
 
465
- expect(mapWithout.color).toEqual("red");
466
- expect(mapWithout.nested).toEqual(undefined);
434
+ newTwiceNested.taste = "umami";
435
+ const update6 = (await queue.next()).value;
436
+ expect(update6.nested?.twiceNested?.taste).toEqual("umami");
437
+ });
467
438
 
468
- const mapWith = TestMapWithOptionalRef.create(
469
- {
470
- color: "red",
471
- nested: NestedMap.create(
472
- {
473
- name: "wow!",
474
- twiceNested: TwiceNestedMap.create(
475
- { taste: "sour" },
476
- { owner: me },
477
- ),
478
- },
479
- { owner: me },
480
- ),
481
- },
482
- { owner: me },
483
- );
439
+ class TestMapWithOptionalRef extends CoMap {
440
+ color = co.string;
441
+ nested = co.optional.ref(NestedMap);
442
+ }
484
443
 
485
- expect(mapWith.color).toEqual("red");
486
- expect(mapWith.nested?.name).toEqual("wow!");
487
- expect(mapWith.nested?._fancyName).toEqual("Sir wow!");
488
- expect(mapWith.nested?._raw).toBeDefined();
444
+ test("Construction with optional", async () => {
445
+ const me = await Account.create({
446
+ creationProps: { name: "Hermes Puggington" },
447
+ crypto: Crypto,
489
448
  });
490
449
 
491
- // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
492
- class TestRecord extends CoMap {
493
- [co.items] = co.number;
494
- }
495
- // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
496
- interface TestRecord extends Record<string, number> {}
450
+ const mapWithout = TestMapWithOptionalRef.create(
451
+ {
452
+ color: "red",
453
+ },
454
+ { owner: me },
455
+ );
456
+
457
+ expect(mapWithout.color).toEqual("red");
458
+ expect(mapWithout.nested).toEqual(undefined);
459
+
460
+ const mapWith = TestMapWithOptionalRef.create(
461
+ {
462
+ color: "red",
463
+ nested: NestedMap.create(
464
+ {
465
+ name: "wow!",
466
+ twiceNested: TwiceNestedMap.create(
467
+ { taste: "sour" },
468
+ { owner: me },
469
+ ),
470
+ },
471
+ { owner: me },
472
+ ),
473
+ },
474
+ { owner: me },
475
+ );
497
476
 
498
- test("Construction with index signature", async () => {
499
- const me = await Account.create({
500
- creationProps: { name: "Hermes Puggington" },
501
- crypto: Crypto,
502
- });
477
+ expect(mapWith.color).toEqual("red");
478
+ expect(mapWith.nested?.name).toEqual("wow!");
479
+ expect(mapWith.nested?._fancyName).toEqual("Sir wow!");
480
+ expect(mapWith.nested?._raw).toBeDefined();
481
+ });
503
482
 
504
- const record = TestRecord.create(
505
- {
506
- height: 5,
507
- other: 3,
508
- },
509
- { owner: me },
510
- );
511
-
512
- expect(record.height).toEqual(5);
513
- expect(record._raw.get("height")).toEqual(5);
514
- expect(record.other).toEqual(3);
515
- expect(record._raw.get("other")).toEqual(3);
516
- expect(Object.keys(record)).toEqual(["height", "other"]);
517
- expect(record.toJSON()).toMatchObject({
518
- _type: "CoMap",
519
- height: 5,
520
- id: expect.any(String),
521
- other: 3,
522
- });
483
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
484
+ class TestRecord extends CoMap {
485
+ [co.items] = co.number;
486
+ }
487
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
488
+ interface TestRecord extends Record<string, number> {}
489
+
490
+ test("Construction with index signature", async () => {
491
+ const me = await Account.create({
492
+ creationProps: { name: "Hermes Puggington" },
493
+ crypto: Crypto,
523
494
  });
524
495
 
525
- class TestRecord2 extends CoMap.Record(co.number) {}
496
+ const record = TestRecord.create(
497
+ {
498
+ height: 5,
499
+ other: 3,
500
+ },
501
+ { owner: me },
502
+ );
526
503
 
527
- test("Construction with index signature (shorthand)", async () => {
528
- const me = await Account.create({
529
- creationProps: { name: "Hermes Puggington" },
530
- crypto: Crypto,
531
- });
504
+ expect(record.height).toEqual(5);
505
+ expect(record._raw.get("height")).toEqual(5);
506
+ expect(record.other).toEqual(3);
507
+ expect(record._raw.get("other")).toEqual(3);
508
+ expect(Object.keys(record)).toEqual(["height", "other"]);
509
+ expect(record.toJSON()).toMatchObject({
510
+ _type: "CoMap",
511
+ height: 5,
512
+ id: expect.any(String),
513
+ other: 3,
514
+ });
515
+ });
532
516
 
533
- const record = TestRecord2.create(
534
- {
535
- height: 5,
536
- other: 3,
537
- },
538
- { owner: me },
539
- );
517
+ class TestRecord2 extends CoMap.Record(co.number) {}
540
518
 
541
- expect(record.height).toEqual(5);
542
- expect(record._raw.get("height")).toEqual(5);
543
- expect(record.other).toEqual(3);
544
- expect(record._raw.get("other")).toEqual(3);
545
- expect(Object.keys(record)).toEqual(["height", "other"]);
519
+ test("Construction with index signature (shorthand)", async () => {
520
+ const me = await Account.create({
521
+ creationProps: { name: "Hermes Puggington" },
522
+ crypto: Crypto,
546
523
  });
547
524
 
548
- class TestRecordRef extends CoMap.Record(co.ref(TwiceNestedMap)) {}
525
+ const record = TestRecord2.create(
526
+ {
527
+ height: 5,
528
+ other: 3,
529
+ },
530
+ { owner: me },
531
+ );
549
532
 
550
- test("Construction with index signature ref", async () => {
551
- const me = await Account.create({
552
- creationProps: { name: "Hermes Puggington" },
553
- crypto: Crypto,
554
- });
533
+ expect(record.height).toEqual(5);
534
+ expect(record._raw.get("height")).toEqual(5);
535
+ expect(record.other).toEqual(3);
536
+ expect(record._raw.get("other")).toEqual(3);
537
+ expect(Object.keys(record)).toEqual(["height", "other"]);
538
+ });
555
539
 
556
- const record = TestRecordRef.create(
557
- {
558
- firstNested: TwiceNestedMap.create(
559
- { taste: "sour" },
560
- { owner: me },
561
- ),
562
- secondNested: TwiceNestedMap.create(
563
- { taste: "sweet" },
564
- { owner: me },
565
- ),
566
- },
567
- { owner: me },
568
- );
569
-
570
- expect(record.firstNested?.taste).toEqual("sour");
571
- expect(record.firstNested?.id).toBeDefined();
572
- expect(record.secondNested?.taste).toEqual("sweet");
573
- expect(record.secondNested?.id).toBeDefined();
574
- expect(Object.keys(record)).toEqual(["firstNested", "secondNested"]);
575
- expect(Object.keys(record._refs)).toEqual([
576
- "firstNested",
577
- "secondNested",
578
- ]);
579
- });
580
- });
540
+ class TestRecordRef extends CoMap.Record(co.ref(TwiceNestedMap)) {}
581
541
 
582
- describe("CoMap applyDiff", async () => {
542
+ test("Construction with index signature ref", async () => {
583
543
  const me = await Account.create({
584
- creationProps: { name: "Tester McTesterson" },
585
- crypto: Crypto,
544
+ creationProps: { name: "Hermes Puggington" },
545
+ crypto: Crypto,
586
546
  });
587
547
 
588
- class TestMap extends CoMap {
589
- name = co.string;
590
- age = co.number;
591
- isActive = co.boolean;
592
- birthday = co.encoded(Encoders.Date);
593
- nested = co.ref(NestedMap);
594
- optionalField = co.optional.string;
595
- optionalNested = co.optional.ref(NestedMap);
596
- }
548
+ const record = TestRecordRef.create(
549
+ {
550
+ firstNested: TwiceNestedMap.create({ taste: "sour" }, { owner: me }),
551
+ secondNested: TwiceNestedMap.create({ taste: "sweet" }, { owner: me }),
552
+ },
553
+ { owner: me },
554
+ );
597
555
 
598
- class NestedMap extends CoMap {
599
- value = co.string;
600
- }
556
+ expect(record.firstNested?.taste).toEqual("sour");
557
+ expect(record.firstNested?.id).toBeDefined();
558
+ expect(record.secondNested?.taste).toEqual("sweet");
559
+ expect(record.secondNested?.id).toBeDefined();
560
+ expect(Object.keys(record)).toEqual(["firstNested", "secondNested"]);
561
+ expect(Object.keys(record._refs)).toEqual(["firstNested", "secondNested"]);
562
+ });
563
+ });
601
564
 
602
- test("Basic applyDiff", () => {
603
- const map = TestMap.create(
604
- {
605
- name: "Alice",
606
- age: 30,
607
- isActive: true,
608
- birthday: new Date("1990-01-01"),
609
- nested: NestedMap.create({ value: "original" }, { owner: me }),
610
- },
611
- { owner: me },
612
- );
565
+ describe("CoMap applyDiff", async () => {
566
+ const me = await Account.create({
567
+ creationProps: { name: "Tester McTesterson" },
568
+ crypto: Crypto,
569
+ });
570
+
571
+ class TestMap extends CoMap {
572
+ name = co.string;
573
+ age = co.number;
574
+ isActive = co.boolean;
575
+ birthday = co.encoded(Encoders.Date);
576
+ nested = co.ref(NestedMap);
577
+ optionalField = co.optional.string;
578
+ optionalNested = co.optional.ref(NestedMap);
579
+ }
580
+
581
+ class NestedMap extends CoMap {
582
+ value = co.string;
583
+ }
584
+
585
+ test("Basic applyDiff", () => {
586
+ const map = TestMap.create(
587
+ {
588
+ name: "Alice",
589
+ age: 30,
590
+ isActive: true,
591
+ birthday: new Date("1990-01-01"),
592
+ nested: NestedMap.create({ value: "original" }, { owner: me }),
593
+ },
594
+ { owner: me },
595
+ );
613
596
 
614
- const newValues = {
615
- name: "Bob",
616
- age: 35,
617
- isActive: false,
618
- };
597
+ const newValues = {
598
+ name: "Bob",
599
+ age: 35,
600
+ isActive: false,
601
+ };
619
602
 
620
- map.applyDiff(newValues);
603
+ map.applyDiff(newValues);
621
604
 
622
- expect(map.name).toEqual("Bob");
623
- expect(map.age).toEqual(35);
624
- expect(map.isActive).toEqual(false);
625
- expect(map.birthday).toEqual(new Date("1990-01-01"));
626
- expect(map.nested?.value).toEqual("original");
627
- });
605
+ expect(map.name).toEqual("Bob");
606
+ expect(map.age).toEqual(35);
607
+ expect(map.isActive).toEqual(false);
608
+ expect(map.birthday).toEqual(new Date("1990-01-01"));
609
+ expect(map.nested?.value).toEqual("original");
610
+ });
628
611
 
629
- test("applyDiff with nested changes", () => {
630
- const map = TestMap.create(
631
- {
632
- name: "Charlie",
633
- age: 25,
634
- isActive: true,
635
- birthday: new Date("1995-01-01"),
636
- nested: NestedMap.create({ value: "original" }, { owner: me }),
637
- },
638
- { owner: me },
639
- );
612
+ test("applyDiff with nested changes", () => {
613
+ const map = TestMap.create(
614
+ {
615
+ name: "Charlie",
616
+ age: 25,
617
+ isActive: true,
618
+ birthday: new Date("1995-01-01"),
619
+ nested: NestedMap.create({ value: "original" }, { owner: me }),
620
+ },
621
+ { owner: me },
622
+ );
640
623
 
641
- const newValues = {
642
- name: "David",
643
- nested: NestedMap.create({ value: "updated" }, { owner: me }),
644
- };
624
+ const newValues = {
625
+ name: "David",
626
+ nested: NestedMap.create({ value: "updated" }, { owner: me }),
627
+ };
645
628
 
646
- map.applyDiff(newValues);
629
+ map.applyDiff(newValues);
647
630
 
648
- expect(map.name).toEqual("David");
649
- expect(map.age).toEqual(25);
650
- expect(map.nested?.value).toEqual("updated");
651
- });
631
+ expect(map.name).toEqual("David");
632
+ expect(map.age).toEqual(25);
633
+ expect(map.nested?.value).toEqual("updated");
634
+ });
652
635
 
653
- test("applyDiff with encoded fields", () => {
654
- const map = TestMap.create(
655
- {
656
- name: "Eve",
657
- age: 28,
658
- isActive: true,
659
- birthday: new Date("1993-01-01"),
660
- nested: NestedMap.create({ value: "original" }, { owner: me }),
661
- },
662
- { owner: me },
663
- );
636
+ test("applyDiff with encoded fields", () => {
637
+ const map = TestMap.create(
638
+ {
639
+ name: "Eve",
640
+ age: 28,
641
+ isActive: true,
642
+ birthday: new Date("1993-01-01"),
643
+ nested: NestedMap.create({ value: "original" }, { owner: me }),
644
+ },
645
+ { owner: me },
646
+ );
664
647
 
665
- const newValues = {
666
- birthday: new Date("1993-06-15"),
667
- };
648
+ const newValues = {
649
+ birthday: new Date("1993-06-15"),
650
+ };
668
651
 
669
- map.applyDiff(newValues);
652
+ map.applyDiff(newValues);
670
653
 
671
- expect(map.birthday).toEqual(new Date("1993-06-15"));
672
- });
654
+ expect(map.birthday).toEqual(new Date("1993-06-15"));
655
+ });
673
656
 
674
- test("applyDiff with optional fields", () => {
675
- const map = TestMap.create(
676
- {
677
- name: "Frank",
678
- age: 40,
679
- isActive: true,
680
- birthday: new Date("1980-01-01"),
681
- nested: NestedMap.create({ value: "original" }, { owner: me }),
682
- },
683
- { owner: me },
684
- );
657
+ test("applyDiff with optional fields", () => {
658
+ const map = TestMap.create(
659
+ {
660
+ name: "Frank",
661
+ age: 40,
662
+ isActive: true,
663
+ birthday: new Date("1980-01-01"),
664
+ nested: NestedMap.create({ value: "original" }, { owner: me }),
665
+ },
666
+ { owner: me },
667
+ );
685
668
 
686
- const newValues = {
687
- optionalField: "New optional value",
688
- };
669
+ const newValues = {
670
+ optionalField: "New optional value",
671
+ };
689
672
 
690
- map.applyDiff(newValues);
673
+ map.applyDiff(newValues);
691
674
 
692
- expect(map.optionalField).toEqual("New optional value");
675
+ expect(map.optionalField).toEqual("New optional value");
693
676
 
694
- map.applyDiff({ optionalField: undefined });
677
+ map.applyDiff({ optionalField: undefined });
695
678
 
696
- expect(map.optionalField).toBeUndefined();
697
- });
679
+ expect(map.optionalField).toBeUndefined();
680
+ });
698
681
 
699
- test("applyDiff with no changes", () => {
700
- const map = TestMap.create(
701
- {
702
- name: "Grace",
703
- age: 35,
704
- isActive: true,
705
- birthday: new Date("1985-01-01"),
706
- nested: NestedMap.create({ value: "original" }, { owner: me }),
707
- },
708
- { owner: me },
709
- );
682
+ test("applyDiff with no changes", () => {
683
+ const map = TestMap.create(
684
+ {
685
+ name: "Grace",
686
+ age: 35,
687
+ isActive: true,
688
+ birthday: new Date("1985-01-01"),
689
+ nested: NestedMap.create({ value: "original" }, { owner: me }),
690
+ },
691
+ { owner: me },
692
+ );
710
693
 
711
- const originalJSON = map.toJSON();
694
+ const originalJSON = map.toJSON();
712
695
 
713
- map.applyDiff({});
696
+ map.applyDiff({});
714
697
 
715
- expect(map.toJSON()).toEqual(originalJSON);
716
- });
698
+ expect(map.toJSON()).toEqual(originalJSON);
699
+ });
717
700
 
718
- test("applyDiff with invalid field", () => {
719
- const map = TestMap.create(
720
- {
721
- name: "Henry",
722
- age: 45,
723
- isActive: false,
724
- birthday: new Date("1975-01-01"),
725
- nested: NestedMap.create({ value: "original" }, { owner: me }),
726
- },
727
- { owner: me },
728
- );
701
+ test("applyDiff with invalid field", () => {
702
+ const map = TestMap.create(
703
+ {
704
+ name: "Henry",
705
+ age: 45,
706
+ isActive: false,
707
+ birthday: new Date("1975-01-01"),
708
+ nested: NestedMap.create({ value: "original" }, { owner: me }),
709
+ },
710
+ { owner: me },
711
+ );
729
712
 
730
- const newValues = {
731
- name: "Ian",
732
- invalidField: "This should be ignored",
733
- };
734
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
735
- map.applyDiff(newValues as any);
713
+ const newValues = {
714
+ name: "Ian",
715
+ invalidField: "This should be ignored",
716
+ };
717
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
718
+ map.applyDiff(newValues as any);
736
719
 
737
- expect(map.name).toEqual("Ian");
738
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
739
- expect((map as any).invalidField).toBeUndefined();
740
- });
720
+ expect(map.name).toEqual("Ian");
721
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
722
+ expect((map as any).invalidField).toBeUndefined();
723
+ });
741
724
 
742
- test("applyDiff with optional reference set to null", () => {
743
- const map = TestMap.create(
744
- {
745
- name: "Jack",
746
- age: 50,
747
- isActive: true,
748
- birthday: new Date("1970-01-01"),
749
- nested: NestedMap.create({ value: "original" }, { owner: me }),
750
- optionalNested: NestedMap.create(
751
- { value: "optional" },
752
- { owner: me },
753
- ),
754
- },
755
- { owner: me },
756
- );
725
+ test("applyDiff with optional reference set to null", () => {
726
+ const map = TestMap.create(
727
+ {
728
+ name: "Jack",
729
+ age: 50,
730
+ isActive: true,
731
+ birthday: new Date("1970-01-01"),
732
+ nested: NestedMap.create({ value: "original" }, { owner: me }),
733
+ optionalNested: NestedMap.create({ value: "optional" }, { owner: me }),
734
+ },
735
+ { owner: me },
736
+ );
757
737
 
758
- const newValues = {
759
- optionalNested: null,
760
- };
738
+ const newValues = {
739
+ optionalNested: null,
740
+ };
761
741
 
762
- map.applyDiff(newValues);
742
+ map.applyDiff(newValues);
763
743
 
764
- expect(map.optionalNested).toBeNull();
765
- });
744
+ expect(map.optionalNested).toBeNull();
745
+ });
766
746
 
767
- test("applyDiff with required reference set to null should throw", () => {
768
- const map = TestMap.create(
769
- {
770
- name: "Kate",
771
- age: 55,
772
- isActive: true,
773
- birthday: new Date("1965-01-01"),
774
- nested: NestedMap.create({ value: "original" }, { owner: me }),
775
- },
776
- { owner: me },
777
- );
747
+ test("applyDiff with required reference set to null should throw", () => {
748
+ const map = TestMap.create(
749
+ {
750
+ name: "Kate",
751
+ age: 55,
752
+ isActive: true,
753
+ birthday: new Date("1965-01-01"),
754
+ nested: NestedMap.create({ value: "original" }, { owner: me }),
755
+ },
756
+ { owner: me },
757
+ );
778
758
 
779
- const newValues = {
780
- nested: null,
781
- };
759
+ const newValues = {
760
+ nested: null,
761
+ };
782
762
 
783
- // @ts-expect-error testing invalid usage
784
- expect(() => map.applyDiff(newValues)).toThrowError(
785
- "Cannot set required reference nested to null",
786
- );
787
- });
763
+ // @ts-expect-error testing invalid usage
764
+ expect(() => map.applyDiff(newValues)).toThrowError(
765
+ "Cannot set required reference nested to null",
766
+ );
767
+ });
788
768
  });
789
769
 
790
770
  describe("CoMap Typescript validation", async () => {
791
- const me = await Account.create({
792
- creationProps: { name: "Hermes Puggington" },
793
- crypto: Crypto,
794
- });
771
+ const me = await Account.create({
772
+ creationProps: { name: "Hermes Puggington" },
773
+ crypto: Crypto,
774
+ });
795
775
 
796
- test("Is not ok to pass null into a required ref", () => {
797
- class TestMap extends CoMap {
798
- required = co.ref(NestedMap);
799
- optional = co.optional.ref(NestedMap);
800
- }
776
+ test("Is not ok to pass null into a required ref", () => {
777
+ class TestMap extends CoMap {
778
+ required = co.ref(NestedMap);
779
+ optional = co.optional.ref(NestedMap);
780
+ }
801
781
 
802
- class NestedMap extends CoMap {
803
- value = co.string;
804
- }
782
+ class NestedMap extends CoMap {
783
+ value = co.string;
784
+ }
805
785
 
806
- expectTypeOf<typeof TestMap.create<TestMap>>().toBeCallableWith(
807
- {
808
- optional: NestedMap.create({ value: "" }, { owner: me }),
809
- // @ts-expect-error null can't be passed to a non-optional field
810
- required: null,
811
- },
812
- { owner: me },
813
- );
814
- });
786
+ expectTypeOf<typeof TestMap.create<TestMap>>().toBeCallableWith(
787
+ {
788
+ optional: NestedMap.create({ value: "" }, { owner: me }),
789
+ // @ts-expect-error null can't be passed to a non-optional field
790
+ required: null,
791
+ },
792
+ { owner: me },
793
+ );
794
+ });
815
795
 
816
- test("Is not ok if a required ref is omitted", () => {
817
- class TestMap extends CoMap {
818
- required = co.ref(NestedMap);
819
- optional = co.ref(NestedMap, { optional: true });
820
- }
796
+ test("Is not ok if a required ref is omitted", () => {
797
+ class TestMap extends CoMap {
798
+ required = co.ref(NestedMap);
799
+ optional = co.ref(NestedMap, { optional: true });
800
+ }
821
801
 
822
- class NestedMap extends CoMap {
823
- value = co.string;
824
- }
802
+ class NestedMap extends CoMap {
803
+ value = co.string;
804
+ }
825
805
 
826
- expectTypeOf<typeof TestMap.create<TestMap>>().toBeCallableWith(
827
- // @ts-expect-error non-optional fields can't be omitted
828
- {},
829
- { owner: me },
830
- );
831
- });
806
+ expectTypeOf<typeof TestMap.create<TestMap>>().toBeCallableWith(
807
+ // @ts-expect-error non-optional fields can't be omitted
808
+ {},
809
+ { owner: me },
810
+ );
811
+ });
832
812
 
833
- test("Is ok to omit optional fields", () => {
834
- class TestMap extends CoMap {
835
- required = co.ref(NestedMap);
836
- optional = co.ref(NestedMap, { optional: true });
837
- }
813
+ test("Is ok to omit optional fields", () => {
814
+ class TestMap extends CoMap {
815
+ required = co.ref(NestedMap);
816
+ optional = co.ref(NestedMap, { optional: true });
817
+ }
838
818
 
839
- class NestedMap extends CoMap {
840
- value = co.string;
841
- }
819
+ class NestedMap extends CoMap {
820
+ value = co.string;
821
+ }
842
822
 
843
- expectTypeOf<typeof TestMap.create<TestMap>>().toBeCallableWith(
844
- {
845
- required: NestedMap.create({ value: "" }, { owner: me }),
846
- },
847
- { owner: me },
848
- );
823
+ expectTypeOf<typeof TestMap.create<TestMap>>().toBeCallableWith(
824
+ {
825
+ required: NestedMap.create({ value: "" }, { owner: me }),
826
+ },
827
+ { owner: me },
828
+ );
849
829
 
850
- expectTypeOf<typeof TestMap.create<TestMap>>().toBeCallableWith(
851
- {
852
- required: NestedMap.create({ value: "" }, { owner: me }),
853
- optional: null,
854
- },
855
- { owner: me },
856
- );
857
- });
830
+ expectTypeOf<typeof TestMap.create<TestMap>>().toBeCallableWith(
831
+ {
832
+ required: NestedMap.create({ value: "" }, { owner: me }),
833
+ optional: null,
834
+ },
835
+ { owner: me },
836
+ );
837
+ });
858
838
 
859
- test("the required refs should be nullable", () => {
860
- class TestMap extends CoMap {
861
- required = co.ref(NestedMap);
862
- optional = co.ref(NestedMap, { optional: true });
863
- }
839
+ test("the required refs should be nullable", () => {
840
+ class TestMap extends CoMap {
841
+ required = co.ref(NestedMap);
842
+ optional = co.ref(NestedMap, { optional: true });
843
+ }
864
844
 
865
- class NestedMap extends CoMap {
866
- value = co.string;
867
- }
845
+ class NestedMap extends CoMap {
846
+ value = co.string;
847
+ }
868
848
 
869
- const map = TestMap.create(
870
- {
871
- required: NestedMap.create({ value: "" }, { owner: me }),
872
- },
873
- { owner: me },
874
- );
849
+ const map = TestMap.create(
850
+ {
851
+ required: NestedMap.create({ value: "" }, { owner: me }),
852
+ },
853
+ { owner: me },
854
+ );
875
855
 
876
- expectTypeOf(map.required).toBeNullable();
877
- });
856
+ expectTypeOf(map.required).toBeNullable();
857
+ });
878
858
  });
879
859
 
880
860
  describe("Creating and finding unique CoMaps", async () => {
881
- test("Creating and finding unique CoMaps", async () => {
882
- const me = await Account.create({
883
- creationProps: { name: "Tester McTesterson" },
884
- crypto: Crypto,
885
- });
861
+ test("Creating and finding unique CoMaps", async () => {
862
+ const me = await Account.create({
863
+ creationProps: { name: "Tester McTesterson" },
864
+ crypto: Crypto,
865
+ });
886
866
 
887
- const group = await Group.create({
888
- owner: me,
889
- });
867
+ const group = await Group.create({
868
+ owner: me,
869
+ });
890
870
 
891
- const alice = TestMap.create(
892
- {
893
- name: "Alice",
894
- _height: 100,
895
- birthday: new Date("1990-01-01"),
896
- color: "red",
897
- },
898
- { owner: group, unique: { name: "Alice" } },
899
- );
871
+ const alice = TestMap.create(
872
+ {
873
+ name: "Alice",
874
+ _height: 100,
875
+ birthday: new Date("1990-01-01"),
876
+ color: "red",
877
+ },
878
+ { owner: group, unique: { name: "Alice" } },
879
+ );
900
880
 
901
- const foundAlice = TestMap.findUnique({ name: "Alice" }, group.id, me);
881
+ const foundAlice = TestMap.findUnique({ name: "Alice" }, group.id, me);
902
882
 
903
- expect(foundAlice).toEqual(alice.id);
904
- });
883
+ expect(foundAlice).toEqual(alice.id);
884
+ });
905
885
  });