jazz-tools 0.8.15 → 0.8.16

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 +276 -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,498 +1,465 @@
1
- import { expect, describe, test } from "vitest";
2
1
  import { connectedPeers } from "cojson/src/streamUtils.ts";
2
+ import { describe, expect, test } from "vitest";
3
3
  import {
4
- BinaryCoStream,
5
- ID,
6
- Account,
7
- CoStream,
8
- co,
9
- WasmCrypto,
10
- isControlledAccount,
11
- cojsonInternals,
12
- createJazzContext,
13
- fixedCredentialsAuth,
4
+ Account,
5
+ BinaryCoStream,
6
+ CoStream,
7
+ ID,
8
+ WasmCrypto,
9
+ co,
10
+ cojsonInternals,
11
+ createJazzContext,
12
+ fixedCredentialsAuth,
13
+ isControlledAccount,
14
14
  } from "../index.web.js";
15
15
  import { randomSessionProvider } from "../internal.js";
16
16
 
17
17
  const Crypto = await WasmCrypto.create();
18
18
 
19
19
  describe("Simple CoStream operations", async () => {
20
- const me = await Account.create({
21
- creationProps: { name: "Hermes Puggington" },
22
- crypto: Crypto,
20
+ const me = await Account.create({
21
+ creationProps: { name: "Hermes Puggington" },
22
+ crypto: Crypto,
23
+ });
24
+ if (!isControlledAccount(me)) {
25
+ throw "me is not a controlled account";
26
+ }
27
+ class TestStream extends CoStream.Of(co.string) {}
28
+
29
+ const stream = TestStream.create(["milk"], { owner: me });
30
+
31
+ test("Construction", () => {
32
+ expect(stream[me.id]?.value).toEqual("milk");
33
+ expect(stream.perSession[me.sessionID]?.value).toEqual("milk");
34
+ });
35
+
36
+ describe("Mutation", () => {
37
+ test("pushing", () => {
38
+ stream.push("bread");
39
+ expect(stream[me.id]?.value).toEqual("bread");
40
+ expect(stream.perSession[me.sessionID]?.value).toEqual("bread");
41
+
42
+ stream.push("butter");
43
+ expect(stream[me.id]?.value).toEqual("butter");
44
+ expect(stream.perSession[me.sessionID]?.value).toEqual("butter");
23
45
  });
24
- if (!isControlledAccount(me)) {
25
- throw "me is not a controlled account";
46
+ });
47
+ });
48
+
49
+ describe("CoStream resolution", async () => {
50
+ class TwiceNestedStream extends CoStream.Of(co.string) {
51
+ fancyValueOf(account: ID<Account>) {
52
+ return "Sir " + this[account]?.value;
26
53
  }
27
- class TestStream extends CoStream.Of(co.string) {}
54
+ }
55
+
56
+ class NestedStream extends CoStream.Of(co.ref(TwiceNestedStream)) {}
28
57
 
29
- const stream = TestStream.create(["milk"], { owner: me });
58
+ class TestStream extends CoStream.Of(co.ref(NestedStream)) {}
30
59
 
31
- test("Construction", () => {
32
- expect(stream[me.id]?.value).toEqual("milk");
33
- expect(stream.perSession[me.sessionID]?.value).toEqual("milk");
60
+ const initNodeAndStream = async () => {
61
+ const me = await Account.create({
62
+ creationProps: { name: "Hermes Puggington" },
63
+ crypto: Crypto,
34
64
  });
35
65
 
36
- describe("Mutation", () => {
37
- test("pushing", () => {
38
- stream.push("bread");
39
- expect(stream[me.id]?.value).toEqual("bread");
40
- expect(stream.perSession[me.sessionID]?.value).toEqual("bread");
66
+ const stream = TestStream.create(
67
+ [
68
+ NestedStream.create(
69
+ [TwiceNestedStream.create(["milk"], { owner: me })],
70
+ { owner: me },
71
+ ),
72
+ ],
73
+ { owner: me },
74
+ );
75
+
76
+ return { me, stream };
77
+ };
78
+
79
+ test("Construction", async () => {
80
+ const { me, stream } = await initNodeAndStream();
81
+ expect(stream[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toEqual(
82
+ "milk",
83
+ );
84
+ });
85
+
86
+ test("Loading and availability", async () => {
87
+ const { me, stream } = await initNodeAndStream();
88
+ const [initialAsPeer, secondPeer] = connectedPeers("initial", "second", {
89
+ peer1role: "server",
90
+ peer2role: "client",
91
+ });
92
+ if (!isControlledAccount(me)) {
93
+ throw "me is not a controlled account";
94
+ }
95
+ me._raw.core.node.syncManager.addPeer(secondPeer);
96
+ const { account: meOnSecondPeer } = await createJazzContext({
97
+ auth: fixedCredentialsAuth({
98
+ accountID: me.id,
99
+ secret: me._raw.agentSecret,
100
+ }),
101
+ sessionProvider: randomSessionProvider,
102
+ peersToLoadFrom: [initialAsPeer],
103
+ crypto: Crypto,
104
+ });
41
105
 
42
- stream.push("butter");
43
- expect(stream[me.id]?.value).toEqual("butter");
44
- expect(stream.perSession[me.sessionID]?.value).toEqual("butter");
45
- });
106
+ const loadedStream = await TestStream.load(stream.id, meOnSecondPeer, []);
107
+
108
+ expect(loadedStream?.[me.id]?.value).toEqual(null);
109
+ expect(loadedStream?.[me.id]?.ref?.id).toEqual(stream[me.id]?.value?.id);
110
+
111
+ const loadedNestedStream = await NestedStream.load(
112
+ stream[me.id]!.value!.id,
113
+ meOnSecondPeer,
114
+ [],
115
+ );
116
+
117
+ // expect(loadedStream?.[me.id]?.value).toEqual(loadedNestedStream);
118
+ expect(loadedStream?.[me.id]?.value?.id).toEqual(loadedNestedStream?.id);
119
+ expect(loadedStream?.[me.id]?.value?.[me.id]?.value).toEqual(null);
120
+ // expect(loadedStream?.[me.id]?.ref?.value).toEqual(loadedNestedStream);
121
+ expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
122
+ loadedNestedStream?.id,
123
+ );
124
+ expect(loadedStream?.[me.id]?.value?.[me.id]?.ref?.id).toEqual(
125
+ stream[me.id]?.value?.[me.id]?.value?.id,
126
+ );
127
+
128
+ const loadedTwiceNestedStream = await TwiceNestedStream.load(
129
+ stream[me.id]!.value![me.id]!.value!.id,
130
+ meOnSecondPeer,
131
+ [],
132
+ );
133
+
134
+ // expect(loadedStream?.[me.id]?.value?.[me.id]?.value).toEqual(
135
+ // loadedTwiceNestedStream
136
+ // );
137
+ expect(loadedStream?.[me.id]?.value?.[me.id]?.value?.id).toEqual(
138
+ loadedTwiceNestedStream?.id,
139
+ );
140
+ expect(
141
+ loadedStream?.[me.id]?.value?.[me.id]?.value?.fancyValueOf(me.id),
142
+ ).toEqual("Sir milk");
143
+ // expect(loadedStream?.[me.id]?.ref?.value).toEqual(loadedNestedStream);
144
+ expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
145
+ loadedNestedStream?.id,
146
+ );
147
+ expect(loadedStream?.[me.id]?.value?.[me.id]?.ref?.value?.id).toEqual(
148
+ loadedTwiceNestedStream?.id,
149
+ );
150
+
151
+ const otherNestedStream = NestedStream.create(
152
+ [TwiceNestedStream.create(["butter"], { owner: meOnSecondPeer })],
153
+ { owner: meOnSecondPeer },
154
+ );
155
+ loadedStream?.push(otherNestedStream);
156
+ // expect(loadedStream?.[me.id]?.value).toEqual(otherNestedStream);
157
+ expect(loadedStream?.[me.id]?.value?.id).toEqual(otherNestedStream?.id);
158
+ expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
159
+ otherNestedStream?.id,
160
+ );
161
+ expect(loadedStream?.[me.id]?.value?.[me.id]?.value?.id).toEqual(
162
+ otherNestedStream[me.id]?.value?.id,
163
+ );
164
+ expect(
165
+ loadedStream?.[me.id]?.value?.[me.id]?.value?.fancyValueOf(me.id),
166
+ ).toEqual("Sir butter");
167
+ });
168
+
169
+ test("Subscription & auto-resolution", async () => {
170
+ const { me, stream } = await initNodeAndStream();
171
+
172
+ const [initialAsPeer, secondAsPeer] = connectedPeers("initial", "second", {
173
+ peer1role: "server",
174
+ peer2role: "client",
46
175
  });
47
- });
48
176
 
49
- describe("CoStream resolution", async () => {
50
- class TwiceNestedStream extends CoStream.Of(co.string) {
51
- fancyValueOf(account: ID<Account>) {
52
- return "Sir " + this[account]?.value;
53
- }
177
+ me._raw.core.node.syncManager.addPeer(secondAsPeer);
178
+ if (!isControlledAccount(me)) {
179
+ throw "me is not a controlled account";
54
180
  }
181
+ const { account: meOnSecondPeer } = await createJazzContext({
182
+ auth: fixedCredentialsAuth({
183
+ accountID: me.id,
184
+ secret: me._raw.agentSecret,
185
+ }),
186
+ sessionProvider: randomSessionProvider,
187
+ peersToLoadFrom: [initialAsPeer],
188
+ crypto: Crypto,
189
+ });
55
190
 
56
- class NestedStream extends CoStream.Of(co.ref(TwiceNestedStream)) {}
57
-
58
- class TestStream extends CoStream.Of(co.ref(NestedStream)) {}
59
-
60
- const initNodeAndStream = async () => {
61
- const me = await Account.create({
62
- creationProps: { name: "Hermes Puggington" },
63
- crypto: Crypto,
64
- });
65
-
66
- const stream = TestStream.create(
67
- [
68
- NestedStream.create(
69
- [TwiceNestedStream.create(["milk"], { owner: me })],
70
- { owner: me },
71
- ),
72
- ],
73
- { owner: me },
74
- );
75
-
76
- return { me, stream };
77
- };
78
-
79
- test("Construction", async () => {
80
- const { me, stream } = await initNodeAndStream();
81
- expect(stream[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toEqual(
82
- "milk",
83
- );
191
+ const queue = new cojsonInternals.Channel();
192
+
193
+ TestStream.subscribe(stream.id, meOnSecondPeer, [], (subscribedStream) => {
194
+ console.log("subscribedStream[me.id]", subscribedStream[me.id]);
195
+ console.log(
196
+ "subscribedStream[me.id]?.value?.[me.id]?.value",
197
+ subscribedStream[me.id]?.value?.[me.id]?.value,
198
+ );
199
+ console.log(
200
+ "subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value",
201
+ subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value,
202
+ );
203
+ void queue.push(subscribedStream);
84
204
  });
85
205
 
86
- test("Loading and availability", async () => {
87
- const { me, stream } = await initNodeAndStream();
88
- const [initialAsPeer, secondPeer] = connectedPeers(
89
- "initial",
90
- "second",
91
- {
92
- peer1role: "server",
93
- peer2role: "client",
94
- },
95
- );
96
- if (!isControlledAccount(me)) {
97
- throw "me is not a controlled account";
98
- }
99
- me._raw.core.node.syncManager.addPeer(secondPeer);
100
- const { account: meOnSecondPeer } = await createJazzContext({
101
- auth: fixedCredentialsAuth({
102
- accountID: me.id,
103
- secret: me._raw.agentSecret,
104
- }),
105
- sessionProvider: randomSessionProvider,
106
- peersToLoadFrom: [initialAsPeer],
107
- crypto: Crypto,
108
- });
109
-
110
- const loadedStream = await TestStream.load(
111
- stream.id,
112
- meOnSecondPeer,
113
- [],
114
- );
115
-
116
- expect(loadedStream?.[me.id]?.value).toEqual(null);
117
- expect(loadedStream?.[me.id]?.ref?.id).toEqual(
118
- stream[me.id]?.value?.id,
119
- );
120
-
121
- const loadedNestedStream = await NestedStream.load(
122
- stream[me.id]!.value!.id,
123
- meOnSecondPeer,
124
- [],
125
- );
126
-
127
- // expect(loadedStream?.[me.id]?.value).toEqual(loadedNestedStream);
128
- expect(loadedStream?.[me.id]?.value?.id).toEqual(
129
- loadedNestedStream?.id,
130
- );
131
- expect(loadedStream?.[me.id]?.value?.[me.id]?.value).toEqual(null);
132
- // expect(loadedStream?.[me.id]?.ref?.value).toEqual(loadedNestedStream);
133
- expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
134
- loadedNestedStream?.id,
135
- );
136
- expect(loadedStream?.[me.id]?.value?.[me.id]?.ref?.id).toEqual(
137
- stream[me.id]?.value?.[me.id]?.value?.id,
138
- );
139
-
140
- const loadedTwiceNestedStream = await TwiceNestedStream.load(
141
- stream[me.id]!.value![me.id]!.value!.id,
142
- meOnSecondPeer,
143
- [],
144
- );
145
-
146
- // expect(loadedStream?.[me.id]?.value?.[me.id]?.value).toEqual(
147
- // loadedTwiceNestedStream
148
- // );
149
- expect(loadedStream?.[me.id]?.value?.[me.id]?.value?.id).toEqual(
150
- loadedTwiceNestedStream?.id,
151
- );
152
- expect(
153
- loadedStream?.[me.id]?.value?.[me.id]?.value?.fancyValueOf(me.id),
154
- ).toEqual("Sir milk");
155
- // expect(loadedStream?.[me.id]?.ref?.value).toEqual(loadedNestedStream);
156
- expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
157
- loadedNestedStream?.id,
158
- );
159
- expect(loadedStream?.[me.id]?.value?.[me.id]?.ref?.value?.id).toEqual(
160
- loadedTwiceNestedStream?.id,
161
- );
162
-
163
- const otherNestedStream = NestedStream.create(
164
- [TwiceNestedStream.create(["butter"], { owner: meOnSecondPeer })],
165
- { owner: meOnSecondPeer },
166
- );
167
- loadedStream?.push(otherNestedStream);
168
- // expect(loadedStream?.[me.id]?.value).toEqual(otherNestedStream);
169
- expect(loadedStream?.[me.id]?.value?.id).toEqual(otherNestedStream?.id);
170
- expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
171
- otherNestedStream?.id,
172
- );
173
- expect(loadedStream?.[me.id]?.value?.[me.id]?.value?.id).toEqual(
174
- otherNestedStream[me.id]?.value?.id,
175
- );
176
- expect(
177
- loadedStream?.[me.id]?.value?.[me.id]?.value?.fancyValueOf(me.id),
178
- ).toEqual("Sir butter");
206
+ const update1 = (await queue.next()).value;
207
+ expect(update1[me.id]?.value).toEqual(null);
208
+
209
+ const update2 = (await queue.next()).value;
210
+ expect(update2[me.id]?.value).toBeDefined();
211
+ expect(update2[me.id]?.value?.[me.id]?.value).toBe(null);
212
+
213
+ const update3 = (await queue.next()).value;
214
+ expect(update3[me.id]?.value?.[me.id]?.value).toBeDefined();
215
+ expect(update3[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toBe("milk");
216
+
217
+ update3[me.id]!.value![me.id]!.value!.push("bread");
218
+
219
+ const update4 = (await queue.next()).value;
220
+ expect(update4[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toBe("bread");
221
+
222
+ // When assigning a new nested stream, we get an update
223
+ const newTwiceNested = TwiceNestedStream.create(["butter"], {
224
+ owner: meOnSecondPeer,
179
225
  });
180
226
 
181
- test("Subscription & auto-resolution", async () => {
182
- const { me, stream } = await initNodeAndStream();
183
-
184
- const [initialAsPeer, secondAsPeer] = connectedPeers(
185
- "initial",
186
- "second",
187
- {
188
- peer1role: "server",
189
- peer2role: "client",
190
- },
191
- );
192
-
193
- me._raw.core.node.syncManager.addPeer(secondAsPeer);
194
- if (!isControlledAccount(me)) {
195
- throw "me is not a controlled account";
196
- }
197
- const { account: meOnSecondPeer } = await createJazzContext({
198
- auth: fixedCredentialsAuth({
199
- accountID: me.id,
200
- secret: me._raw.agentSecret,
201
- }),
202
- sessionProvider: randomSessionProvider,
203
- peersToLoadFrom: [initialAsPeer],
204
- crypto: Crypto,
205
- });
206
-
207
- const queue = new cojsonInternals.Channel();
208
-
209
- TestStream.subscribe(
210
- stream.id,
211
- meOnSecondPeer,
212
- [],
213
- (subscribedStream) => {
214
- console.log("subscribedStream[me.id]", subscribedStream[me.id]);
215
- console.log(
216
- "subscribedStream[me.id]?.value?.[me.id]?.value",
217
- subscribedStream[me.id]?.value?.[me.id]?.value,
218
- );
219
- console.log(
220
- "subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value",
221
- subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]
222
- ?.value,
223
- );
224
- void queue.push(subscribedStream);
225
- },
226
- );
227
-
228
- const update1 = (await queue.next()).value;
229
- expect(update1[me.id]?.value).toEqual(null);
230
-
231
- const update2 = (await queue.next()).value;
232
- expect(update2[me.id]?.value).toBeDefined();
233
- expect(update2[me.id]?.value?.[me.id]?.value).toBe(null);
234
-
235
- const update3 = (await queue.next()).value;
236
- expect(update3[me.id]?.value?.[me.id]?.value).toBeDefined();
237
- expect(update3[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toBe(
238
- "milk",
239
- );
240
-
241
- update3[me.id]!.value![me.id]!.value!.push("bread");
242
-
243
- const update4 = (await queue.next()).value;
244
- expect(update4[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toBe(
245
- "bread",
246
- );
247
-
248
- // When assigning a new nested stream, we get an update
249
- const newTwiceNested = TwiceNestedStream.create(["butter"], {
250
- owner: meOnSecondPeer,
251
- });
252
-
253
- const newNested = NestedStream.create([newTwiceNested], {
254
- owner: meOnSecondPeer,
255
- });
256
-
257
- update4.push(newNested);
258
-
259
- const update5 = (await queue.next()).value;
260
- expect(update5[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toBe(
261
- "butter",
262
- );
263
-
264
- // we get updates when the new nested stream changes
265
- newTwiceNested.push("jam");
266
- const update6 = (await queue.next()).value;
267
- expect(update6[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toBe(
268
- "jam",
269
- );
227
+ const newNested = NestedStream.create([newTwiceNested], {
228
+ owner: meOnSecondPeer,
270
229
  });
230
+
231
+ update4.push(newNested);
232
+
233
+ const update5 = (await queue.next()).value;
234
+ expect(update5[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toBe(
235
+ "butter",
236
+ );
237
+
238
+ // we get updates when the new nested stream changes
239
+ newTwiceNested.push("jam");
240
+ const update6 = (await queue.next()).value;
241
+ expect(update6[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toBe("jam");
242
+ });
271
243
  });
272
244
 
273
245
  describe("Simple BinaryCoStream operations", async () => {
246
+ const me = await Account.create({
247
+ creationProps: { name: "Hermes Puggington" },
248
+ crypto: Crypto,
249
+ });
250
+
251
+ const stream = BinaryCoStream.create({ owner: me });
252
+
253
+ test("Construction", () => {
254
+ expect(stream.getChunks()).toBe(undefined);
255
+ });
256
+
257
+ test("Mutation", () => {
258
+ stream.start({ mimeType: "text/plain" });
259
+ stream.push(new Uint8Array([1, 2, 3]));
260
+ stream.push(new Uint8Array([4, 5, 6]));
261
+ stream.end();
262
+
263
+ const chunks = stream.getChunks();
264
+ expect(chunks?.mimeType).toBe("text/plain");
265
+ expect(chunks?.chunks).toEqual([
266
+ new Uint8Array([1, 2, 3]),
267
+ new Uint8Array([4, 5, 6]),
268
+ ]);
269
+ expect(chunks?.finished).toBe(true);
270
+ });
271
+ });
272
+
273
+ describe("BinaryCoStream loading & Subscription", async () => {
274
+ const initNodeAndStream = async () => {
274
275
  const me = await Account.create({
275
- creationProps: { name: "Hermes Puggington" },
276
- crypto: Crypto,
276
+ creationProps: { name: "Hermes Puggington" },
277
+ crypto: Crypto,
277
278
  });
278
279
 
279
280
  const stream = BinaryCoStream.create({ owner: me });
280
281
 
281
- test("Construction", () => {
282
- expect(stream.getChunks()).toBe(undefined);
282
+ stream.start({ mimeType: "text/plain" });
283
+ stream.push(new Uint8Array([1, 2, 3]));
284
+ stream.push(new Uint8Array([4, 5, 6]));
285
+ stream.end();
286
+
287
+ return { me, stream };
288
+ };
289
+
290
+ test("Construction", async () => {
291
+ const { stream } = await initNodeAndStream();
292
+ expect(stream.getChunks()).toEqual({
293
+ mimeType: "text/plain",
294
+ chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
295
+ finished: true,
283
296
  });
297
+ });
284
298
 
285
- test("Mutation", () => {
286
- stream.start({ mimeType: "text/plain" });
287
- stream.push(new Uint8Array([1, 2, 3]));
288
- stream.push(new Uint8Array([4, 5, 6]));
289
- stream.end();
290
-
291
- const chunks = stream.getChunks();
292
- expect(chunks?.mimeType).toBe("text/plain");
293
- expect(chunks?.chunks).toEqual([
294
- new Uint8Array([1, 2, 3]),
295
- new Uint8Array([4, 5, 6]),
296
- ]);
297
- expect(chunks?.finished).toBe(true);
299
+ test("Loading and availability", async () => {
300
+ const { me, stream } = await initNodeAndStream();
301
+ const [initialAsPeer, secondAsPeer] = connectedPeers("initial", "second", {
302
+ peer1role: "server",
303
+ peer2role: "client",
304
+ });
305
+ if (!isControlledAccount(me)) {
306
+ throw "me is not a controlled account";
307
+ }
308
+ me._raw.core.node.syncManager.addPeer(secondAsPeer);
309
+ const { account: meOnSecondPeer } = await createJazzContext({
310
+ auth: fixedCredentialsAuth({
311
+ accountID: me.id,
312
+ secret: me._raw.agentSecret,
313
+ }),
314
+ sessionProvider: randomSessionProvider,
315
+ peersToLoadFrom: [initialAsPeer],
316
+ crypto: Crypto,
298
317
  });
299
- });
300
318
 
301
- describe("BinaryCoStream loading & Subscription", async () => {
302
- const initNodeAndStream = async () => {
303
- const me = await Account.create({
304
- creationProps: { name: "Hermes Puggington" },
305
- crypto: Crypto,
306
- });
307
-
308
- const stream = BinaryCoStream.create({ owner: me });
309
-
310
- stream.start({ mimeType: "text/plain" });
311
- stream.push(new Uint8Array([1, 2, 3]));
312
- stream.push(new Uint8Array([4, 5, 6]));
313
- stream.end();
314
-
315
- return { me, stream };
316
- };
317
-
318
- test("Construction", async () => {
319
- const { stream } = await initNodeAndStream();
320
- expect(stream.getChunks()).toEqual({
321
- mimeType: "text/plain",
322
- chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
323
- finished: true,
324
- });
319
+ const loadedStream = await BinaryCoStream.load(
320
+ stream.id,
321
+ meOnSecondPeer,
322
+ [],
323
+ );
324
+
325
+ expect(loadedStream?.getChunks()).toEqual({
326
+ mimeType: "text/plain",
327
+ chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
328
+ finished: true,
329
+ });
330
+ });
331
+
332
+ test("Subscription", async () => {
333
+ const { me } = await initNodeAndStream();
334
+ const stream = BinaryCoStream.create({ owner: me });
335
+
336
+ const [initialAsPeer, secondAsPeer] = connectedPeers("initial", "second", {
337
+ peer1role: "server",
338
+ peer2role: "client",
339
+ });
340
+ me._raw.core.node.syncManager.addPeer(secondAsPeer);
341
+ if (!isControlledAccount(me)) {
342
+ throw "me is not a controlled account";
343
+ }
344
+ const { account: meOnSecondPeer } = await createJazzContext({
345
+ auth: fixedCredentialsAuth({
346
+ accountID: me.id,
347
+ secret: me._raw.agentSecret,
348
+ }),
349
+ sessionProvider: randomSessionProvider,
350
+ peersToLoadFrom: [initialAsPeer],
351
+ crypto: Crypto,
325
352
  });
326
353
 
327
- test("Loading and availability", async () => {
328
- const { me, stream } = await initNodeAndStream();
329
- const [initialAsPeer, secondAsPeer] = connectedPeers(
330
- "initial",
331
- "second",
332
- {
333
- peer1role: "server",
334
- peer2role: "client",
335
- },
336
- );
337
- if (!isControlledAccount(me)) {
338
- throw "me is not a controlled account";
339
- }
340
- me._raw.core.node.syncManager.addPeer(secondAsPeer);
341
- const { account: meOnSecondPeer } = await createJazzContext({
342
- auth: fixedCredentialsAuth({
343
- accountID: me.id,
344
- secret: me._raw.agentSecret,
345
- }),
346
- sessionProvider: randomSessionProvider,
347
- peersToLoadFrom: [initialAsPeer],
348
- crypto: Crypto,
349
- });
350
-
351
- const loadedStream = await BinaryCoStream.load(
352
- stream.id,
353
- meOnSecondPeer,
354
- [],
355
- );
356
-
357
- expect(loadedStream?.getChunks()).toEqual({
358
- mimeType: "text/plain",
359
- chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
360
- finished: true,
361
- });
354
+ const queue = new cojsonInternals.Channel();
355
+
356
+ BinaryCoStream.subscribe(
357
+ stream.id,
358
+ meOnSecondPeer,
359
+ [],
360
+ (subscribedStream) => {
361
+ void queue.push(subscribedStream);
362
+ },
363
+ );
364
+
365
+ const update1 = (await queue.next()).value;
366
+ expect(update1.getChunks()).toBe(undefined);
367
+
368
+ stream.start({ mimeType: "text/plain" });
369
+
370
+ const update2 = (await queue.next()).value;
371
+ expect(update2.getChunks({ allowUnfinished: true })).toEqual({
372
+ mimeType: "text/plain",
373
+ fileName: undefined,
374
+ chunks: [],
375
+ totalSizeBytes: undefined,
376
+ finished: false,
362
377
  });
363
378
 
364
- test("Subscription", async () => {
365
- const { me } = await initNodeAndStream();
366
- const stream = BinaryCoStream.create({ owner: me });
367
-
368
- const [initialAsPeer, secondAsPeer] = connectedPeers(
369
- "initial",
370
- "second",
371
- { peer1role: "server", peer2role: "client" },
372
- );
373
- me._raw.core.node.syncManager.addPeer(secondAsPeer);
374
- if (!isControlledAccount(me)) {
375
- throw "me is not a controlled account";
376
- }
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();
388
-
389
- BinaryCoStream.subscribe(
390
- stream.id,
391
- meOnSecondPeer,
392
- [],
393
- (subscribedStream) => {
394
- void queue.push(subscribedStream);
395
- },
396
- );
397
-
398
- const update1 = (await queue.next()).value;
399
- expect(update1.getChunks()).toBe(undefined);
400
-
401
- stream.start({ mimeType: "text/plain" });
402
-
403
- const update2 = (await queue.next()).value;
404
- expect(update2.getChunks({ allowUnfinished: true })).toEqual({
405
- mimeType: "text/plain",
406
- fileName: undefined,
407
- chunks: [],
408
- totalSizeBytes: undefined,
409
- finished: false,
410
- });
411
-
412
- stream.push(new Uint8Array([1, 2, 3]));
413
-
414
- const update3 = (await queue.next()).value;
415
- expect(update3.getChunks({ allowUnfinished: true })).toEqual({
416
- mimeType: "text/plain",
417
- fileName: undefined,
418
- chunks: [new Uint8Array([1, 2, 3])],
419
- totalSizeBytes: undefined,
420
- finished: false,
421
- });
422
-
423
- stream.push(new Uint8Array([4, 5, 6]));
424
-
425
- const update4 = (await queue.next()).value;
426
- expect(update4.getChunks({ allowUnfinished: true })).toEqual({
427
- mimeType: "text/plain",
428
- fileName: undefined,
429
- chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
430
- totalSizeBytes: undefined,
431
- finished: false,
432
- });
433
-
434
- stream.end();
435
-
436
- const update5 = (await queue.next()).value;
437
- expect(update5.getChunks()).toEqual({
438
- mimeType: "text/plain",
439
- fileName: undefined,
440
- chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
441
- totalSizeBytes: undefined,
442
- finished: true,
443
- });
379
+ stream.push(new Uint8Array([1, 2, 3]));
380
+
381
+ const update3 = (await queue.next()).value;
382
+ expect(update3.getChunks({ allowUnfinished: true })).toEqual({
383
+ mimeType: "text/plain",
384
+ fileName: undefined,
385
+ chunks: [new Uint8Array([1, 2, 3])],
386
+ totalSizeBytes: undefined,
387
+ finished: false,
444
388
  });
389
+
390
+ stream.push(new Uint8Array([4, 5, 6]));
391
+
392
+ const update4 = (await queue.next()).value;
393
+ expect(update4.getChunks({ allowUnfinished: true })).toEqual({
394
+ mimeType: "text/plain",
395
+ fileName: undefined,
396
+ chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
397
+ totalSizeBytes: undefined,
398
+ finished: false,
399
+ });
400
+
401
+ stream.end();
402
+
403
+ const update5 = (await queue.next()).value;
404
+ expect(update5.getChunks()).toEqual({
405
+ mimeType: "text/plain",
406
+ fileName: undefined,
407
+ chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
408
+ totalSizeBytes: undefined,
409
+ finished: true,
410
+ });
411
+ });
445
412
  });
446
413
 
447
414
  describe("BinaryCoStream.loadAsBlob", async () => {
448
- async function setup() {
449
- const me = await Account.create({
450
- creationProps: { name: "Hermes Puggington" },
451
- crypto: Crypto,
452
- });
415
+ async function setup() {
416
+ const me = await Account.create({
417
+ creationProps: { name: "Hermes Puggington" },
418
+ crypto: Crypto,
419
+ });
453
420
 
454
- const stream = BinaryCoStream.create({ owner: me });
421
+ const stream = BinaryCoStream.create({ owner: me });
455
422
 
456
- stream.start({ mimeType: "text/plain" });
423
+ stream.start({ mimeType: "text/plain" });
457
424
 
458
- return { stream, me };
459
- }
425
+ return { stream, me };
426
+ }
460
427
 
461
- test("resolves only when the stream is ended", async () => {
462
- const { stream, me } = await setup();
463
- stream.push(new Uint8Array([1]));
428
+ test("resolves only when the stream is ended", async () => {
429
+ const { stream, me } = await setup();
430
+ stream.push(new Uint8Array([1]));
464
431
 
465
- const promise = BinaryCoStream.loadAsBlob(stream.id, me);
432
+ const promise = BinaryCoStream.loadAsBlob(stream.id, me);
466
433
 
467
- await stream.ensureLoaded([]);
434
+ await stream.ensureLoaded([]);
468
435
 
469
- stream.push(new Uint8Array([2]));
470
- stream.end();
436
+ stream.push(new Uint8Array([2]));
437
+ stream.end();
471
438
 
472
- const blob = await promise;
439
+ const blob = await promise;
473
440
 
474
- // The promise resolves only when the stream is ended
475
- // so we get a blob with all the chunks
476
- expect(blob?.size).toBe(2);
477
- });
441
+ // The promise resolves only when the stream is ended
442
+ // so we get a blob with all the chunks
443
+ expect(blob?.size).toBe(2);
444
+ });
478
445
 
479
- test("resolves with an unfinshed blob if allowUnfinished: true", async () => {
480
- const { stream, me } = await setup();
481
- stream.push(new Uint8Array([1]));
446
+ test("resolves with an unfinshed blob if allowUnfinished: true", async () => {
447
+ const { stream, me } = await setup();
448
+ stream.push(new Uint8Array([1]));
482
449
 
483
- const promise = BinaryCoStream.loadAsBlob(stream.id, me, {
484
- allowUnfinished: true,
485
- });
450
+ const promise = BinaryCoStream.loadAsBlob(stream.id, me, {
451
+ allowUnfinished: true,
452
+ });
486
453
 
487
- await stream.ensureLoaded([]);
454
+ await stream.ensureLoaded([]);
488
455
 
489
- stream.push(new Uint8Array([2]));
490
- stream.end();
456
+ stream.push(new Uint8Array([2]));
457
+ stream.end();
491
458
 
492
- const blob = await promise;
459
+ const blob = await promise;
493
460
 
494
- // The promise resolves before the stream is ended
495
- // so we get a blob only with the first chunk
496
- expect(blob?.size).toBe(1);
497
- });
461
+ // The promise resolves before the stream is ended
462
+ // so we get a blob only with the first chunk
463
+ expect(blob?.size).toBe(1);
464
+ });
498
465
  });