jazz-tools 0.7.0-alpha.3 → 0.7.0-alpha.31

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. package/.turbo/turbo-build.log +78 -8
  2. package/CHANGELOG.md +181 -0
  3. package/dist/coValues/account.js +81 -41
  4. package/dist/coValues/account.js.map +1 -1
  5. package/dist/coValues/coList.js +156 -104
  6. package/dist/coValues/coList.js.map +1 -1
  7. package/dist/coValues/coMap.js +182 -163
  8. package/dist/coValues/coMap.js.map +1 -1
  9. package/dist/coValues/coStream.js +202 -71
  10. package/dist/coValues/coStream.js.map +1 -1
  11. package/dist/coValues/extensions/imageDef.js +13 -8
  12. package/dist/coValues/extensions/imageDef.js.map +1 -1
  13. package/dist/coValues/group.js +46 -38
  14. package/dist/coValues/group.js.map +1 -1
  15. package/dist/coValues/interfaces.js +23 -5
  16. package/dist/coValues/interfaces.js.map +1 -1
  17. package/dist/implementation/refs.js +26 -12
  18. package/dist/implementation/refs.js.map +1 -1
  19. package/dist/implementation/schema.js +38 -1
  20. package/dist/implementation/schema.js.map +1 -1
  21. package/dist/implementation/symbols.js +5 -0
  22. package/dist/implementation/symbols.js.map +1 -0
  23. package/dist/index.js +4 -3
  24. package/dist/index.js.map +1 -1
  25. package/dist/internal.js +1 -0
  26. package/dist/internal.js.map +1 -1
  27. package/dist/tests/coList.test.js +32 -36
  28. package/dist/tests/coList.test.js.map +1 -1
  29. package/dist/tests/coMap.test.js +170 -59
  30. package/dist/tests/coMap.test.js.map +1 -1
  31. package/dist/tests/coStream.test.js +59 -64
  32. package/dist/tests/coStream.test.js.map +1 -1
  33. package/dist/tests/groupsAndAccounts.test.js +88 -0
  34. package/dist/tests/groupsAndAccounts.test.js.map +1 -0
  35. package/package.json +5 -4
  36. package/src/coValues/account.ts +129 -105
  37. package/src/coValues/coList.ts +200 -131
  38. package/src/coValues/coMap.ts +243 -305
  39. package/src/coValues/coStream.ts +300 -127
  40. package/src/coValues/extensions/imageDef.ts +14 -16
  41. package/src/coValues/group.ts +90 -106
  42. package/src/coValues/interfaces.ts +33 -12
  43. package/src/implementation/refs.ts +42 -25
  44. package/src/implementation/schema.ts +69 -46
  45. package/src/implementation/symbols.ts +12 -0
  46. package/src/index.ts +10 -8
  47. package/src/internal.ts +1 -0
  48. package/src/tests/coList.test.ts +35 -39
  49. package/src/tests/coMap.test.ts +176 -81
  50. package/src/tests/coStream.test.ts +76 -81
  51. package/src/tests/groupsAndAccounts.test.ts +100 -0
@@ -1,10 +1,10 @@
1
- import { expect, describe, test, beforeEach, Test } from "vitest";
1
+ import { expect, describe, test, beforeEach } from "vitest";
2
2
 
3
3
  import { webcrypto } from "node:crypto";
4
4
  import { connectedPeers } from "cojson/src/streamUtils.js";
5
5
  import { newRandomSessionID } from "cojson/src/coValueCore.js";
6
6
  import { Effect, Queue } from "effect";
7
- import { BinaryCoStream, ID, Account, jazzReady, CoStream } from "..";
7
+ import { BinaryCoStream, ID, Account, jazzReady, CoStream, co } from "..";
8
8
  import { Simplify } from "effect/Types";
9
9
 
10
10
  if (!("crypto" in globalThis)) {
@@ -18,55 +18,51 @@ beforeEach(async () => {
18
18
 
19
19
  describe("Simple CoStream operations", async () => {
20
20
  const me = await Account.create({
21
- name: "Hermes Puggington",
21
+ creationProps: { name: "Hermes Puggington" },
22
22
  });
23
23
 
24
- class TestStream extends CoStream<string> {}
25
- TestStream.encoding({ _item: "json" });
24
+ class TestStream extends CoStream.Of(co.string) {}
26
25
 
27
- const stream = new TestStream(["milk"], { owner: me });
26
+ const stream = TestStream.create(["milk"], { owner: me });
28
27
 
29
28
  test("Construction", () => {
30
- expect(stream.by[me.id]?.value).toEqual("milk");
31
- expect(stream.in[me.sessionID]?.value).toEqual("milk");
29
+ expect(stream[me.id]?.value).toEqual("milk");
30
+ expect(stream.perSession[me.sessionID]?.value).toEqual("milk");
32
31
  });
33
32
 
34
33
  describe("Mutation", () => {
35
34
  test("pushing", () => {
36
35
  stream.push("bread");
37
- expect(stream.by[me.id]?.value).toEqual("bread");
38
- expect(stream.in[me.sessionID]?.value).toEqual("bread");
36
+ expect(stream[me.id]?.value).toEqual("bread");
37
+ expect(stream.perSession[me.sessionID]?.value).toEqual("bread");
39
38
 
40
39
  stream.push("butter");
41
- expect(stream.by[me.id]?.value).toEqual("butter");
42
- expect(stream.in[me.sessionID]?.value).toEqual("butter");
40
+ expect(stream[me.id]?.value).toEqual("butter");
41
+ expect(stream.perSession[me.sessionID]?.value).toEqual("butter");
43
42
  });
44
43
  });
45
44
  });
46
45
 
47
46
  describe("CoStream resolution", async () => {
48
- class TwiceNestedStream extends CoStream<string> {
47
+ class TwiceNestedStream extends CoStream.Of(co.string) {
49
48
  fancyValueOf(account: ID<Account>) {
50
- return "Sir " + this.by[account]?.value;
49
+ return "Sir " + this[account]?.value;
51
50
  }
52
51
  }
53
- TwiceNestedStream.encoding({ _item: "json" });
54
52
 
55
- class NestedStream extends CoStream<TwiceNestedStream | null>{}
56
- NestedStream.encoding({ _item: {ref: () => TwiceNestedStream} });
53
+ class NestedStream extends CoStream.Of(co.ref(TwiceNestedStream)) {}
57
54
 
58
- class TestStream extends CoStream<NestedStream | null> {}
59
- TestStream.encoding({ _item: {ref: () => NestedStream} });
55
+ class TestStream extends CoStream.Of(co.ref(NestedStream)) {}
60
56
 
61
57
  const initNodeAndStream = async () => {
62
58
  const me = await Account.create({
63
- name: "Hermes Puggington",
59
+ creationProps: { name: "Hermes Puggington" },
64
60
  });
65
61
 
66
- const stream = new TestStream(
62
+ const stream = TestStream.create(
67
63
  [
68
- new NestedStream(
69
- [new TwiceNestedStream(["milk"], { owner: me })],
64
+ NestedStream.create(
65
+ [TwiceNestedStream.create(["milk"], { owner: me })],
70
66
  { owner: me }
71
67
  ),
72
68
  ],
@@ -78,9 +74,9 @@ describe("CoStream resolution", async () => {
78
74
 
79
75
  test("Construction", async () => {
80
76
  const { me, stream } = await initNodeAndStream();
81
- expect(
82
- stream.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value
83
- ).toEqual("milk");
77
+ expect(stream[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toEqual(
78
+ "milk"
79
+ );
84
80
  });
85
81
 
86
82
  test("Loading and availability", async () => {
@@ -102,66 +98,66 @@ describe("CoStream resolution", async () => {
102
98
  as: meOnSecondPeer,
103
99
  });
104
100
 
105
- expect(loadedStream?.by[me.id]?.value).toEqual(null);
106
- expect(loadedStream?.by[me.id]?.ref?.id).toEqual(
107
- stream.by[me.id]?.value?.id
101
+ expect(loadedStream?.[me.id]?.value).toEqual(null);
102
+ expect(loadedStream?.[me.id]?.ref?.id).toEqual(
103
+ stream[me.id]?.value?.id
108
104
  );
109
105
 
110
106
  const loadedNestedStream = await NestedStream.load(
111
- stream.by[me.id]!.value!.id,
107
+ stream[me.id]!.value!.id,
112
108
  { as: meOnSecondPeer }
113
109
  );
114
110
 
115
- // expect(loadedStream?.by[me.id]?.value).toEqual(loadedNestedStream);
116
- expect(loadedStream?.by[me.id]?.value?.id).toEqual(
111
+ // expect(loadedStream?.[me.id]?.value).toEqual(loadedNestedStream);
112
+ expect(loadedStream?.[me.id]?.value?.id).toEqual(
117
113
  loadedNestedStream?.id
118
114
  );
119
- expect(loadedStream?.by[me.id]?.value?.by[me.id]?.value).toEqual(null);
120
- // expect(loadedStream?.by[me.id]?.ref?.value).toEqual(loadedNestedStream);
121
- expect(loadedStream?.by[me.id]?.ref?.value?.id).toEqual(
115
+ expect(loadedStream?.[me.id]?.value?.[me.id]?.value).toEqual(null);
116
+ // expect(loadedStream?.[me.id]?.ref?.value).toEqual(loadedNestedStream);
117
+ expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
122
118
  loadedNestedStream?.id
123
119
  );
124
- expect(loadedStream?.by[me.id]?.value?.by[me.id]?.ref?.id).toEqual(
125
- stream.by[me.id]?.value?.by[me.id]?.value?.id
120
+ expect(loadedStream?.[me.id]?.value?.[me.id]?.ref?.id).toEqual(
121
+ stream[me.id]?.value?.[me.id]?.value?.id
126
122
  );
127
123
 
128
124
  const loadedTwiceNestedStream = await TwiceNestedStream.load(
129
- stream.by[me.id]!.value!.by[me.id]!.value!.id,
125
+ stream[me.id]!.value![me.id]!.value!.id,
130
126
  { as: meOnSecondPeer }
131
127
  );
132
128
 
133
- // expect(loadedStream?.by[me.id]?.value?.by[me.id]?.value).toEqual(
129
+ // expect(loadedStream?.[me.id]?.value?.[me.id]?.value).toEqual(
134
130
  // loadedTwiceNestedStream
135
131
  // );
136
- expect(loadedStream?.by[me.id]?.value?.by[me.id]?.value?.id).toEqual(
132
+ expect(loadedStream?.[me.id]?.value?.[me.id]?.value?.id).toEqual(
137
133
  loadedTwiceNestedStream?.id
138
134
  );
139
135
  expect(
140
- loadedStream?.by[me.id]?.value?.by[me.id]?.value?.fancyValueOf(
141
- me.id
142
- )
136
+ loadedStream?.[me.id]?.value?.[me.id]?.value?.fancyValueOf(me.id)
143
137
  ).toEqual("Sir milk");
144
- // expect(loadedStream?.by[me.id]?.ref?.value).toEqual(loadedNestedStream);
145
- expect(loadedStream?.by[me.id]?.ref?.value?.id).toEqual(loadedNestedStream?.id);
146
- expect(loadedStream?.by[me.id]?.value?.by[me.id]?.ref?.value?.id).toEqual(
138
+ // expect(loadedStream?.[me.id]?.ref?.value).toEqual(loadedNestedStream);
139
+ expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
140
+ loadedNestedStream?.id
141
+ );
142
+ expect(loadedStream?.[me.id]?.value?.[me.id]?.ref?.value?.id).toEqual(
147
143
  loadedTwiceNestedStream?.id
148
144
  );
149
145
 
150
- const otherNestedStream = new NestedStream(
151
- [new TwiceNestedStream(["butter"], { owner: meOnSecondPeer })],
146
+ const otherNestedStream = NestedStream.create(
147
+ [TwiceNestedStream.create(["butter"], { owner: meOnSecondPeer })],
152
148
  { owner: meOnSecondPeer }
153
149
  );
154
150
  loadedStream?.push(otherNestedStream);
155
- // expect(loadedStream?.by[me.id]?.value).toEqual(otherNestedStream);
156
- expect(loadedStream?.by[me.id]?.value?.id).toEqual(otherNestedStream?.id);
157
- expect(loadedStream?.by[me.id]?.ref?.value?.id).toEqual(otherNestedStream?.id);
158
- expect(loadedStream?.by[me.id]?.value?.by[me.id]?.value?.id).toEqual(
159
- otherNestedStream.by[me.id]?.value?.id
151
+ // expect(loadedStream?.[me.id]?.value).toEqual(otherNestedStream);
152
+ expect(loadedStream?.[me.id]?.value?.id).toEqual(otherNestedStream?.id);
153
+ expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
154
+ otherNestedStream?.id
155
+ );
156
+ expect(loadedStream?.[me.id]?.value?.[me.id]?.value?.id).toEqual(
157
+ otherNestedStream[me.id]?.value?.id
160
158
  );
161
159
  expect(
162
- loadedStream?.by[me.id]?.value?.by[me.id]?.value?.fancyValueOf(
163
- me.id
164
- )
160
+ loadedStream?.[me.id]?.value?.[me.id]?.value?.fancyValueOf(me.id)
165
161
  ).toEqual("Sir butter");
166
162
  });
167
163
 
@@ -192,17 +188,18 @@ describe("CoStream resolution", async () => {
192
188
  { as: meOnSecondPeer },
193
189
  (subscribedStream) => {
194
190
  console.log(
195
- "subscribedStream.by[me.id]",
196
- subscribedStream.by[me.id]
191
+ "subscribedStream[me.id]",
192
+ subscribedStream[me.id]
197
193
  );
198
194
  console.log(
199
- "subscribedStream.by[me.id]?.value?.by[me.id]?.value",
200
- subscribedStream.by[me.id]?.value?.by[me.id]?.value
195
+ "subscribedStream[me.id]?.value?.[me.id]?.value",
196
+ subscribedStream[me.id]?.value?.[me.id]?.value
201
197
  );
202
198
  console.log(
203
- "subscribedStream.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value",
204
- subscribedStream.by[me.id]?.value?.by[me.id]?.value
205
- ?.by[me.id]?.value
199
+ "subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value",
200
+ subscribedStream[me.id]?.value?.[me.id]?.value?.[
201
+ me.id
202
+ ]?.value
206
203
  );
207
204
  Effect.runPromise(Queue.offer(queue, subscribedStream));
208
205
  }
@@ -212,33 +209,31 @@ describe("CoStream resolution", async () => {
212
209
  const te: T = stream;
213
210
 
214
211
  const update1 = yield* $(Queue.take(queue));
215
- expect(update1.by[me.id]?.value).toEqual(null);
212
+ expect(update1[me.id]?.value).toEqual(null);
216
213
 
217
214
  const update2 = yield* $(Queue.take(queue));
218
- expect(update2.by[me.id]?.value).toBeDefined();
219
- expect(update2.by[me.id]?.value?.by[me.id]?.value).toBe(null);
215
+ expect(update2[me.id]?.value).toBeDefined();
216
+ expect(update2[me.id]?.value?.[me.id]?.value).toBe(null);
220
217
 
221
218
  const update3 = yield* $(Queue.take(queue));
219
+ expect(update3[me.id]?.value?.[me.id]?.value).toBeDefined();
222
220
  expect(
223
- update3.by[me.id]?.value?.by[me.id]?.value
224
- ).toBeDefined();
225
- expect(
226
- update3.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value
221
+ update3[me.id]?.value?.[me.id]?.value?.[me.id]?.value
227
222
  ).toBe("milk");
228
223
 
229
- update3.by[me.id]!.value!.by[me.id]!.value!.push("bread");
224
+ update3[me.id]!.value![me.id]!.value!.push("bread");
230
225
 
231
226
  const update4 = yield* $(Queue.take(queue));
232
227
  expect(
233
- update4.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value
228
+ update4[me.id]?.value?.[me.id]?.value?.[me.id]?.value
234
229
  ).toBe("bread");
235
230
 
236
231
  // When assigning a new nested stream, we get an update
237
- const newTwiceNested = new TwiceNestedStream(["butter"], {
232
+ const newTwiceNested = TwiceNestedStream.create(["butter"], {
238
233
  owner: meOnSecondPeer,
239
234
  });
240
235
 
241
- const newNested = new NestedStream([newTwiceNested], {
236
+ const newNested = NestedStream.create([newTwiceNested], {
242
237
  owner: meOnSecondPeer,
243
238
  });
244
239
 
@@ -246,14 +241,14 @@ describe("CoStream resolution", async () => {
246
241
 
247
242
  const update5 = yield* $(Queue.take(queue));
248
243
  expect(
249
- update5.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value
244
+ update5[me.id]?.value?.[me.id]?.value?.[me.id]?.value
250
245
  ).toBe("butter");
251
246
 
252
247
  // we get updates when the new nested stream changes
253
248
  newTwiceNested.push("jam");
254
249
  const update6 = yield* $(Queue.take(queue));
255
250
  expect(
256
- update6.by[me.id]?.value?.by[me.id]?.value?.by[me.id]?.value
251
+ update6[me.id]?.value?.[me.id]?.value?.[me.id]?.value
257
252
  ).toBe("jam");
258
253
  })
259
254
  );
@@ -262,10 +257,10 @@ describe("CoStream resolution", async () => {
262
257
 
263
258
  describe("Simple BinaryCoStream operations", async () => {
264
259
  const me = await Account.create({
265
- name: "Hermes Puggington",
260
+ creationProps: { name: "Hermes Puggington" },
266
261
  });
267
262
 
268
- const stream = new BinaryCoStream(undefined, { owner: me });
263
+ const stream = BinaryCoStream.create({ owner: me });
269
264
 
270
265
  test("Construction", () => {
271
266
  expect(stream.getChunks()).toBe(undefined);
@@ -290,10 +285,10 @@ describe("Simple BinaryCoStream operations", async () => {
290
285
  describe("BinaryCoStream loading & Subscription", async () => {
291
286
  const initNodeAndStream = async () => {
292
287
  const me = await Account.create({
293
- name: "Hermes Puggington",
288
+ creationProps: { name: "Hermes Puggington" },
294
289
  });
295
290
 
296
- const stream = new BinaryCoStream(undefined, { owner: me });
291
+ const stream = BinaryCoStream.create({ owner: me });
297
292
 
298
293
  stream.start({ mimeType: "text/plain" });
299
294
  stream.push(new Uint8Array([1, 2, 3]));
@@ -341,7 +336,7 @@ describe("BinaryCoStream loading & Subscription", async () => {
341
336
  test("Subscription", async () => {
342
337
  const { me } = await initNodeAndStream();
343
338
 
344
- const stream = new BinaryCoStream(undefined, { owner: me });
339
+ const stream = BinaryCoStream.create({ owner: me });
345
340
 
346
341
  const [initialAsPeer, secondAsPeer] = connectedPeers(
347
342
  "initial",
@@ -0,0 +1,100 @@
1
+ import { expect, describe, test, beforeEach } from "vitest";
2
+
3
+ import { webcrypto } from "node:crypto";
4
+ import { Account, jazzReady, CoMap, co, Group } from "..";
5
+
6
+ if (!("crypto" in globalThis)) {
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ (globalThis as any).crypto = webcrypto;
9
+ }
10
+
11
+ beforeEach(async () => {
12
+ await jazzReady;
13
+ });
14
+
15
+ describe("Custom accounts and groups", async () => {
16
+ class CustomProfile extends CoMap {
17
+ name = co.string;
18
+ color = co.string;
19
+ }
20
+
21
+ class CustomAccount extends Account {
22
+ profile = co.ref(CustomProfile);
23
+ root = co.ref(CoMap);
24
+
25
+ migrate(creationProps?: { name: string }) {
26
+ if (creationProps) {
27
+ const profileGroup = Group.create({ owner: this });
28
+ profileGroup.addMember("everyone", "reader");
29
+ this.profile = CustomProfile.create(
30
+ { name: creationProps.name, color: "blue" },
31
+ { owner: this }
32
+ );
33
+ }
34
+ }
35
+ }
36
+
37
+ class CustomGroup extends Group {
38
+ profile = co.null;
39
+ root = co.null;
40
+ [co.members] = co.ref(CustomAccount);
41
+
42
+ get nMembers() {
43
+ return this.members.length;
44
+ }
45
+ }
46
+
47
+ type T = CustomGroup[typeof co.members];
48
+
49
+ test("Custom account and group", async () => {
50
+ const me = await CustomAccount.create({
51
+ creationProps: { name: "Hermes Puggington" },
52
+ });
53
+
54
+ expect(me.profile).toBeDefined();
55
+ expect(me.profile?.name).toBe("Hermes Puggington");
56
+ expect(me.profile?.color).toBe("blue");
57
+
58
+ const group = new CustomGroup({ owner: me });
59
+ group.addMember("everyone", "reader");
60
+
61
+ expect(group.members).toMatchObject([
62
+ { id: me.id, role: "admin" },
63
+ { id: "everyone", role: "reader" },
64
+ ]);
65
+
66
+ expect(group.nMembers).toBe(2);
67
+
68
+ await new Promise<void>((resolve) => {
69
+ group.subscribe((update) => {
70
+ const meAsMember = update.members.find((member) => {
71
+ return member.id === me.id && member.account?.profile;
72
+ });
73
+ if (meAsMember) {
74
+ expect(meAsMember.account?.profile?.name).toBe(
75
+ "Hermes Puggington"
76
+ );
77
+ expect(meAsMember.account?.profile?.color).toBe("blue");
78
+ resolve();
79
+ }
80
+ });
81
+ });
82
+
83
+ class MyMap extends CoMap {
84
+ name = co.string;
85
+ }
86
+
87
+ const map = MyMap.create({ name: "test" }, { owner: group });
88
+
89
+ const meAsCastMember = map._owner
90
+ .as(CustomGroup)
91
+ .members.find((member) => member.id === me.id);
92
+ expect(meAsCastMember?.account?.profile?.name).toBe(
93
+ "Hermes Puggington"
94
+ );
95
+ expect(meAsCastMember?.account?.profile?.color).toBe("blue");
96
+
97
+ expect((map._owner as any).nMembers).toBeUndefined();
98
+ expect(map._owner.as(CustomGroup).nMembers).toBe(2);
99
+ });
100
+ });