jazz-tools 0.15.8 → 0.15.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +45 -45
- package/CHANGELOG.md +21 -0
- package/dist/browser/createBrowserContext.d.ts.map +1 -1
- package/dist/browser/index.js +9 -7
- package/dist/browser/index.js.map +1 -1
- package/dist/{chunk-DGFPP22M.js → chunk-V54IPL5M.js} +31 -6
- package/dist/chunk-V54IPL5M.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/inspector/{custom-element-I7Q6H5E5.js → custom-element-TUXKXSZU.js} +18791 -18806
- package/dist/inspector/custom-element-TUXKXSZU.js.map +1 -0
- package/dist/inspector/register-custom-element.js +1 -1
- package/dist/react-native-core/index.d.ts +1 -1
- package/dist/react-native-core/index.d.ts.map +1 -1
- package/dist/react-native-core/index.js +15 -31
- package/dist/react-native-core/index.js.map +1 -1
- package/dist/react-native-core/platform.d.ts +1 -1
- package/dist/react-native-core/platform.d.ts.map +1 -1
- package/dist/testing.js +22 -3
- package/dist/testing.js.map +1 -1
- package/dist/tools/implementation/createContext.d.ts +8 -4
- package/dist/tools/implementation/createContext.d.ts.map +1 -1
- package/dist/tools/implementation/zodSchema/zodReExport.d.ts +1 -1
- package/dist/tools/implementation/zodSchema/zodReExport.d.ts.map +1 -1
- package/dist/tools/subscribe/SubscriptionScope.d.ts +2 -0
- package/dist/tools/subscribe/SubscriptionScope.d.ts.map +1 -1
- package/dist/tools/testing.d.ts +3 -1
- package/dist/tools/testing.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/browser/createBrowserContext.ts +8 -6
- package/src/react-core/tests/useCoState.test.ts +0 -12
- package/src/react-native-core/index.ts +1 -1
- package/src/react-native-core/platform.ts +13 -12
- package/src/tools/implementation/createContext.ts +16 -0
- package/src/tools/implementation/zodSchema/zodReExport.ts +1 -0
- package/src/tools/subscribe/SubscriptionScope.ts +21 -2
- package/src/tools/testing.ts +25 -2
- package/src/tools/tests/coFeed.test.ts +190 -239
- package/src/tools/tests/coMap.test.ts +0 -8
- package/src/tools/tests/coPlainText.test.ts +2 -1
- package/src/tools/tests/deepLoading.test.ts +6 -6
- package/src/tools/tests/load.test.ts +65 -30
- package/src/tools/tests/subscribe.test.ts +92 -0
- package/dist/chunk-DGFPP22M.js.map +0 -1
- package/dist/inspector/custom-element-I7Q6H5E5.js.map +0 -1
- package/dist/react-native-core/storage/sqlite-react-native.d.ts +0 -9
- package/dist/react-native-core/storage/sqlite-react-native.d.ts.map +0 -1
- package/src/react-native-core/storage/sqlite-react-native.ts +0 -19
@@ -1,5 +1,13 @@
|
|
1
1
|
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
2
|
-
import {
|
2
|
+
import { Channel } from "queueueue";
|
3
|
+
import {
|
4
|
+
assert,
|
5
|
+
beforeEach,
|
6
|
+
describe,
|
7
|
+
expect,
|
8
|
+
expectTypeOf,
|
9
|
+
test,
|
10
|
+
} from "vitest";
|
3
11
|
import {
|
4
12
|
Account,
|
5
13
|
FileStream,
|
@@ -14,12 +22,24 @@ import {
|
|
14
22
|
createJazzContextFromExistingCredentials,
|
15
23
|
randomSessionProvider,
|
16
24
|
} from "../internal.js";
|
17
|
-
import { createJazzTestAccount } from "../testing.js";
|
25
|
+
import { createJazzTestAccount, setupJazzTestSync } from "../testing.js";
|
18
26
|
import { setupTwoNodes } from "./utils.js";
|
19
27
|
|
20
28
|
const Crypto = await WasmCrypto.create();
|
21
29
|
|
22
|
-
|
30
|
+
let me = await Account.create({
|
31
|
+
creationProps: { name: "Hermes Puggington" },
|
32
|
+
crypto: Crypto,
|
33
|
+
});
|
34
|
+
|
35
|
+
beforeEach(async () => {
|
36
|
+
await setupJazzTestSync();
|
37
|
+
|
38
|
+
me = await createJazzTestAccount({
|
39
|
+
isCurrentActiveAccount: true,
|
40
|
+
creationProps: { name: "Hermes Puggington" },
|
41
|
+
});
|
42
|
+
});
|
23
43
|
|
24
44
|
describe("Simple CoFeed operations", async () => {
|
25
45
|
const me = await Account.create({
|
@@ -72,19 +92,20 @@ describe("CoFeed resolution", async () => {
|
|
72
92
|
const TestStream = co.feed(NestedStream);
|
73
93
|
|
74
94
|
const initNodeAndStream = async () => {
|
75
|
-
const me = await
|
76
|
-
|
77
|
-
crypto: Crypto,
|
95
|
+
const me = await createJazzTestAccount({
|
96
|
+
isCurrentActiveAccount: true,
|
78
97
|
});
|
79
98
|
|
99
|
+
const group = Group.create(me);
|
100
|
+
group.makePublic();
|
80
101
|
const stream = TestStream.create(
|
81
102
|
[
|
82
103
|
NestedStream.create(
|
83
|
-
[TwiceNestedStream.create(["milk"], { owner:
|
84
|
-
{ owner:
|
104
|
+
[TwiceNestedStream.create(["milk"], { owner: group })],
|
105
|
+
{ owner: group },
|
85
106
|
),
|
86
107
|
],
|
87
|
-
{ owner:
|
108
|
+
{ owner: group },
|
88
109
|
);
|
89
110
|
|
90
111
|
return { me, stream };
|
@@ -105,177 +126,86 @@ describe("CoFeed resolution", async () => {
|
|
105
126
|
|
106
127
|
test("Loading and availability", async () => {
|
107
128
|
const { me, stream } = await initNodeAndStream();
|
108
|
-
|
109
|
-
|
110
|
-
peer2role: "client",
|
111
|
-
});
|
112
|
-
if (!isControlledAccount(me)) {
|
113
|
-
throw "me is not a controlled account";
|
114
|
-
}
|
115
|
-
me._raw.core.node.syncManager.addPeer(secondPeer);
|
116
|
-
const { account: meOnSecondPeer } =
|
117
|
-
await createJazzContextFromExistingCredentials({
|
118
|
-
credentials: {
|
119
|
-
accountID: me.id,
|
120
|
-
secret: me._raw.core.node.getCurrentAgent().agentSecret,
|
121
|
-
},
|
122
|
-
sessionProvider: randomSessionProvider,
|
123
|
-
peersToLoadFrom: [initialAsPeer],
|
124
|
-
crypto: Crypto,
|
125
|
-
});
|
129
|
+
|
130
|
+
const anotherAccount = await createJazzTestAccount();
|
126
131
|
|
127
132
|
const loadedStream = await TestStream.load(stream.id, {
|
128
|
-
loadAs:
|
133
|
+
loadAs: anotherAccount,
|
129
134
|
});
|
130
135
|
|
131
|
-
|
132
|
-
// expectTypeOf(loadedStream?.[me.id]).not.toBeAny();
|
136
|
+
assert(loadedStream);
|
133
137
|
|
134
|
-
|
135
|
-
expect(loadedStream?.perAccount[me.id]?.ref?.id).toEqual(
|
136
|
-
stream.perAccount[me.id]?.value?.id,
|
137
|
-
);
|
138
|
+
const myStream = loadedStream.perAccount[me.id];
|
138
139
|
|
139
|
-
|
140
|
-
stream.perAccount[me.id]!.value!.id,
|
141
|
-
{ loadAs: meOnSecondPeer },
|
142
|
-
);
|
140
|
+
assert(myStream);
|
143
141
|
|
144
|
-
|
145
|
-
expect(loadedStream?.perAccount[me.id]?.value?.id).toEqual(
|
146
|
-
loadedNestedStream?.id,
|
147
|
-
);
|
148
|
-
expect(
|
149
|
-
loadedStream?.perAccount[me.id]?.value?.perAccount[me.id]?.value,
|
150
|
-
).toEqual(null);
|
151
|
-
// expect(loadedStream?.[me.id]?.ref?.value).toEqual(loadedNestedStream);
|
152
|
-
expect(loadedStream?.perAccount[me.id]?.ref?.value?.id).toEqual(
|
153
|
-
loadedNestedStream?.id,
|
154
|
-
);
|
155
|
-
expect(
|
156
|
-
loadedStream?.perAccount[me.id]?.value?.perAccount[me.id]?.ref?.id,
|
157
|
-
).toEqual(stream.perAccount[me.id]?.value?.perAccount[me.id]?.value?.id);
|
142
|
+
expect(myStream.value).toBeTruthy();
|
158
143
|
|
159
|
-
|
160
|
-
stream.perAccount[me.id]!.value!.perAccount[me.id]!.value!.id,
|
161
|
-
{ loadAs: meOnSecondPeer },
|
162
|
-
);
|
144
|
+
assert(myStream.value);
|
163
145
|
|
164
|
-
|
165
|
-
// loadedTwiceNestedStream
|
166
|
-
// );
|
167
|
-
expect(
|
168
|
-
loadedStream?.perAccount[me.id]?.value?.perAccount[me.id]?.value?.id,
|
169
|
-
).toEqual(loadedTwiceNestedStream?.id);
|
170
|
-
// expect(loadedStream?.[me.id]?.ref?.value).toEqual(loadedNestedStream);
|
171
|
-
expect(loadedStream?.perAccount[me.id]?.ref?.value?.id).toEqual(
|
172
|
-
loadedNestedStream?.id,
|
173
|
-
);
|
174
|
-
expect(
|
175
|
-
loadedStream?.perAccount[me.id]?.value?.perAccount[me.id]?.ref?.value?.id,
|
176
|
-
).toEqual(loadedTwiceNestedStream?.id);
|
146
|
+
const loadedNestedStreamByMe = myStream.value.perAccount[me.id];
|
177
147
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
);
|
190
|
-
|
191
|
-
|
192
|
-
).toEqual(otherNestedStream.perAccount[me.id]?.value?.id);
|
148
|
+
assert(loadedNestedStreamByMe);
|
149
|
+
|
150
|
+
expect(loadedNestedStreamByMe.value).toBeTruthy();
|
151
|
+
|
152
|
+
assert(loadedNestedStreamByMe.value);
|
153
|
+
|
154
|
+
const loadedTwiceNestedStreamByMe =
|
155
|
+
loadedNestedStreamByMe.value.perAccount[me.id];
|
156
|
+
|
157
|
+
assert(loadedTwiceNestedStreamByMe);
|
158
|
+
|
159
|
+
expect(loadedTwiceNestedStreamByMe.value).toBe("milk");
|
160
|
+
|
161
|
+
assert(loadedTwiceNestedStreamByMe.value);
|
193
162
|
});
|
194
163
|
|
195
164
|
test("Subscription & auto-resolution", async () => {
|
196
165
|
const { me, stream } = await initNodeAndStream();
|
197
166
|
|
198
|
-
const
|
199
|
-
peer1role: "server",
|
200
|
-
peer2role: "client",
|
201
|
-
});
|
167
|
+
const anotherAccount = await createJazzTestAccount();
|
202
168
|
|
203
|
-
|
204
|
-
if (!isControlledAccount(me)) {
|
205
|
-
throw "me is not a controlled account";
|
206
|
-
}
|
207
|
-
const { account: meOnSecondPeer } =
|
208
|
-
await createJazzContextFromExistingCredentials({
|
209
|
-
credentials: {
|
210
|
-
accountID: me.id,
|
211
|
-
secret: me._raw.core.node.getCurrentAgent().agentSecret,
|
212
|
-
},
|
213
|
-
sessionProvider: randomSessionProvider,
|
214
|
-
peersToLoadFrom: [initialAsPeer],
|
215
|
-
crypto: Crypto,
|
216
|
-
});
|
217
|
-
|
218
|
-
const queue = new cojsonInternals.Channel();
|
169
|
+
const queue = new Channel();
|
219
170
|
|
220
171
|
TestStream.subscribe(
|
221
172
|
stream.id,
|
222
|
-
{ loadAs:
|
173
|
+
{ loadAs: anotherAccount },
|
223
174
|
(subscribedStream) => {
|
224
175
|
void queue.push(subscribedStream);
|
225
176
|
},
|
226
177
|
);
|
227
178
|
|
228
179
|
const update1 = (await queue.next()).value;
|
229
|
-
expect(update1.perAccount[me.id]?.value).toEqual(null);
|
230
|
-
|
231
|
-
const update2 = (await queue.next()).value;
|
232
|
-
expect(update2.perAccount[me.id]?.value).toBeDefined();
|
233
|
-
expect(update2.perAccount[me.id]?.value?.perAccount[me.id]?.value).toBe(
|
234
|
-
null,
|
235
|
-
);
|
236
|
-
|
237
|
-
const update3 = (await queue.next()).value;
|
238
180
|
expect(
|
239
|
-
|
240
|
-
).toBeDefined();
|
241
|
-
expect(
|
242
|
-
update3.perAccount[me.id]?.value?.perAccount[me.id]?.value?.perAccount[
|
181
|
+
update1.perAccount[me.id]?.value?.perAccount[me.id]?.value?.perAccount[
|
243
182
|
me.id
|
244
183
|
]?.value,
|
245
184
|
).toBe("milk");
|
246
185
|
|
247
|
-
update3.perAccount[me.id]!.value!.perAccount[me.id]!.value!.push("bread");
|
248
|
-
|
249
|
-
const update4 = (await queue.next()).value;
|
250
|
-
expect(
|
251
|
-
update4.perAccount[me.id]?.value?.perAccount[me.id]?.value?.perAccount[
|
252
|
-
me.id
|
253
|
-
]?.value,
|
254
|
-
).toBe("bread");
|
255
|
-
|
256
186
|
// When assigning a new nested stream, we get an update
|
257
187
|
const newTwiceNested = TwiceNestedStream.create(["butter"], {
|
258
|
-
owner:
|
188
|
+
owner: stream._owner,
|
259
189
|
});
|
260
190
|
|
261
191
|
const newNested = NestedStream.create([newTwiceNested], {
|
262
|
-
owner:
|
192
|
+
owner: stream._owner,
|
263
193
|
});
|
264
194
|
|
265
|
-
|
195
|
+
stream.push(newNested);
|
266
196
|
|
267
|
-
const
|
197
|
+
const update2 = (await queue.next()).value;
|
268
198
|
expect(
|
269
|
-
|
199
|
+
update2.perAccount[me.id]?.value?.perAccount[me.id]?.value?.perAccount[
|
270
200
|
me.id
|
271
201
|
]?.value,
|
272
202
|
).toBe("butter");
|
273
203
|
|
274
204
|
// we get updates when the new nested stream changes
|
275
205
|
newTwiceNested.push("jam");
|
276
|
-
const
|
206
|
+
const update3 = (await queue.next()).value;
|
277
207
|
expect(
|
278
|
-
|
208
|
+
update3.perAccount[me.id]?.value?.perAccount[me.id]?.value?.perAccount[
|
279
209
|
me.id
|
280
210
|
]?.value,
|
281
211
|
).toBe("jam");
|
@@ -284,54 +214,24 @@ describe("CoFeed resolution", async () => {
|
|
284
214
|
test("Subscription without options", async () => {
|
285
215
|
const { me, stream } = await initNodeAndStream();
|
286
216
|
|
287
|
-
const
|
288
|
-
peer1role: "server",
|
289
|
-
peer2role: "client",
|
290
|
-
});
|
291
|
-
if (!isControlledAccount(me)) {
|
292
|
-
throw "me is not a controlled account";
|
293
|
-
}
|
294
|
-
me._raw.core.node.syncManager.addPeer(secondAsPeer);
|
295
|
-
|
296
|
-
await createJazzContextFromExistingCredentials({
|
297
|
-
credentials: {
|
298
|
-
accountID: me.id,
|
299
|
-
secret: me._raw.core.node.getCurrentAgent().agentSecret,
|
300
|
-
},
|
301
|
-
sessionProvider: randomSessionProvider,
|
302
|
-
peersToLoadFrom: [initialAsPeer],
|
303
|
-
crypto: Crypto,
|
304
|
-
});
|
305
|
-
|
306
|
-
const queue = new cojsonInternals.Channel<Loaded<typeof TestStream>>();
|
217
|
+
const queue = new Channel();
|
307
218
|
|
308
219
|
TestStream.subscribe(stream.id, (subscribedStream) => {
|
309
220
|
void queue.push(subscribedStream);
|
310
221
|
});
|
311
222
|
|
312
223
|
const update1 = (await queue.next()).value;
|
313
|
-
expect(update1.perAccount[me.id]?.value).toEqual(null);
|
314
|
-
|
315
|
-
const update2 = (await queue.next()).value;
|
316
|
-
expect(update2.perAccount[me.id]?.value?.perAccount[me.id]?.value).toEqual(
|
317
|
-
null,
|
318
|
-
);
|
319
|
-
|
320
|
-
const update3 = (await queue.next()).value;
|
321
224
|
expect(
|
322
|
-
|
323
|
-
).toBeDefined();
|
324
|
-
expect(
|
325
|
-
update3.perAccount[me.id]?.value?.perAccount[me.id]?.value?.perAccount[
|
225
|
+
update1.perAccount[me.id]?.value?.perAccount[me.id]?.value?.perAccount[
|
326
226
|
me.id
|
327
227
|
]?.value,
|
328
228
|
).toBe("milk");
|
329
229
|
|
330
|
-
|
230
|
+
stream.perAccount[me.id]!.value!.perAccount[me.id]!.value!.push("bread");
|
331
231
|
|
332
|
-
const
|
232
|
+
const update2 = (await queue.next()).value;
|
333
233
|
expect(
|
334
|
-
|
234
|
+
update2.perAccount[me.id]?.value?.perAccount[me.id]?.value?.perAccount[
|
335
235
|
me.id
|
336
236
|
]?.value,
|
337
237
|
).toBe("bread");
|
@@ -395,12 +295,13 @@ describe("Simple FileStream operations", async () => {
|
|
395
295
|
|
396
296
|
describe("FileStream loading & Subscription", async () => {
|
397
297
|
const initNodeAndStream = async () => {
|
398
|
-
const me = await
|
399
|
-
|
400
|
-
crypto: Crypto,
|
298
|
+
const me = await createJazzTestAccount({
|
299
|
+
isCurrentActiveAccount: true,
|
401
300
|
});
|
402
301
|
|
403
|
-
const
|
302
|
+
const group = Group.create(me);
|
303
|
+
group.makePublic();
|
304
|
+
const stream = FileStream.create({ owner: group });
|
404
305
|
|
405
306
|
stream.start({ mimeType: "text/plain" });
|
406
307
|
stream.push(new Uint8Array([1, 2, 3]));
|
@@ -420,28 +321,11 @@ describe("FileStream loading & Subscription", async () => {
|
|
420
321
|
});
|
421
322
|
|
422
323
|
test("Loading and availability", async () => {
|
423
|
-
const {
|
424
|
-
const
|
425
|
-
peer1role: "server",
|
426
|
-
peer2role: "client",
|
427
|
-
});
|
428
|
-
if (!isControlledAccount(me)) {
|
429
|
-
throw "me is not a controlled account";
|
430
|
-
}
|
431
|
-
me._raw.core.node.syncManager.addPeer(secondAsPeer);
|
432
|
-
const { account: meOnSecondPeer } =
|
433
|
-
await createJazzContextFromExistingCredentials({
|
434
|
-
credentials: {
|
435
|
-
accountID: me.id,
|
436
|
-
secret: me._raw.core.node.getCurrentAgent().agentSecret,
|
437
|
-
},
|
438
|
-
sessionProvider: randomSessionProvider,
|
439
|
-
peersToLoadFrom: [initialAsPeer],
|
440
|
-
crypto: Crypto,
|
441
|
-
});
|
324
|
+
const { stream } = await initNodeAndStream();
|
325
|
+
const anotherAccount = await createJazzTestAccount();
|
442
326
|
|
443
327
|
const loadedStream = await FileStream.load(stream.id, {
|
444
|
-
loadAs:
|
328
|
+
loadAs: anotherAccount,
|
445
329
|
});
|
446
330
|
|
447
331
|
expect(loadedStream?.getChunks()).toEqual({
|
@@ -453,32 +337,17 @@ describe("FileStream loading & Subscription", async () => {
|
|
453
337
|
|
454
338
|
test("Subscription", async () => {
|
455
339
|
const { me } = await initNodeAndStream();
|
456
|
-
const
|
340
|
+
const group = Group.create(me);
|
341
|
+
group.makePublic();
|
342
|
+
const stream = FileStream.create({ owner: group });
|
457
343
|
|
458
|
-
const
|
459
|
-
|
460
|
-
|
461
|
-
});
|
462
|
-
me._raw.core.node.syncManager.addPeer(secondAsPeer);
|
463
|
-
if (!isControlledAccount(me)) {
|
464
|
-
throw "me is not a controlled account";
|
465
|
-
}
|
466
|
-
const { account: meOnSecondPeer } =
|
467
|
-
await createJazzContextFromExistingCredentials({
|
468
|
-
credentials: {
|
469
|
-
accountID: me.id,
|
470
|
-
secret: me._raw.core.node.getCurrentAgent().agentSecret,
|
471
|
-
},
|
472
|
-
sessionProvider: randomSessionProvider,
|
473
|
-
peersToLoadFrom: [initialAsPeer],
|
474
|
-
crypto: Crypto,
|
475
|
-
});
|
476
|
-
|
477
|
-
const queue = new cojsonInternals.Channel();
|
344
|
+
const anotherAccount = await createJazzTestAccount();
|
345
|
+
|
346
|
+
const queue = new Channel();
|
478
347
|
|
479
348
|
FileStream.subscribe(
|
480
349
|
stream.id,
|
481
|
-
{ loadAs:
|
350
|
+
{ loadAs: anotherAccount },
|
482
351
|
(subscribedStream) => {
|
483
352
|
void queue.push(subscribedStream);
|
484
353
|
},
|
@@ -534,27 +403,11 @@ describe("FileStream loading & Subscription", async () => {
|
|
534
403
|
|
535
404
|
test("Subscription without options", async () => {
|
536
405
|
const { me } = await initNodeAndStream();
|
537
|
-
const
|
538
|
-
|
539
|
-
const
|
540
|
-
peer1role: "server",
|
541
|
-
peer2role: "client",
|
542
|
-
});
|
543
|
-
me._raw.core.node.syncManager.addPeer(secondAsPeer);
|
544
|
-
if (!isControlledAccount(me)) {
|
545
|
-
throw "me is not a controlled account";
|
546
|
-
}
|
547
|
-
await createJazzContextFromExistingCredentials({
|
548
|
-
credentials: {
|
549
|
-
accountID: me.id,
|
550
|
-
secret: me._raw.core.node.getCurrentAgent().agentSecret,
|
551
|
-
},
|
552
|
-
sessionProvider: randomSessionProvider,
|
553
|
-
peersToLoadFrom: [initialAsPeer],
|
554
|
-
crypto: Crypto,
|
555
|
-
});
|
406
|
+
const group = Group.create(me);
|
407
|
+
group.makePublic();
|
408
|
+
const stream = FileStream.create({ owner: group });
|
556
409
|
|
557
|
-
const queue = new
|
410
|
+
const queue = new Channel();
|
558
411
|
|
559
412
|
FileStream.subscribe(stream.id, (subscribedStream) => {
|
560
413
|
void queue.push(subscribedStream);
|
@@ -591,12 +444,13 @@ describe("FileStream loading & Subscription", async () => {
|
|
591
444
|
|
592
445
|
describe("FileStream.load", async () => {
|
593
446
|
async function setup() {
|
594
|
-
const me = await
|
595
|
-
|
596
|
-
crypto: Crypto,
|
447
|
+
const me = await createJazzTestAccount({
|
448
|
+
isCurrentActiveAccount: true,
|
597
449
|
});
|
598
450
|
|
599
|
-
const
|
451
|
+
const group = Group.create(me);
|
452
|
+
group.makePublic();
|
453
|
+
const stream = FileStream.create({ owner: group });
|
600
454
|
|
601
455
|
stream.start({ mimeType: "text/plain" });
|
602
456
|
|
@@ -789,6 +643,103 @@ describe("FileStream progress tracking", async () => {
|
|
789
643
|
});
|
790
644
|
});
|
791
645
|
|
646
|
+
describe("FileStream large file loading", async () => {
|
647
|
+
test("load a large FileStream with allowUnfinished: true should return the loaded file before it's fully loaded", async () => {
|
648
|
+
const syncServer = await setupJazzTestSync({ asyncPeers: true });
|
649
|
+
|
650
|
+
const group = Group.create(syncServer);
|
651
|
+
const largeStream = FileStream.create({ owner: group });
|
652
|
+
group.addMember("everyone", "reader");
|
653
|
+
|
654
|
+
// Create a large file stream with multiple chunks
|
655
|
+
largeStream.start({ mimeType: "application/octet-stream" });
|
656
|
+
|
657
|
+
const dataSize = 100 * 1024; // 100KB total
|
658
|
+
const chunkSize = 1024; // 1KB chunks
|
659
|
+
const numChunks = dataSize / chunkSize;
|
660
|
+
|
661
|
+
// Create test data chunks
|
662
|
+
for (let i = 0; i < numChunks; i++) {
|
663
|
+
const chunk = new Uint8Array(chunkSize);
|
664
|
+
for (let j = 0; j < chunkSize; j++) {
|
665
|
+
chunk[j] = (i * chunkSize + j) % 256;
|
666
|
+
}
|
667
|
+
largeStream.push(chunk);
|
668
|
+
}
|
669
|
+
|
670
|
+
largeStream.end();
|
671
|
+
|
672
|
+
// Wait for the large FileStream to be fully synced
|
673
|
+
await largeStream.waitForSync();
|
674
|
+
|
675
|
+
const alice = await createJazzTestAccount();
|
676
|
+
|
677
|
+
// Test loading the large FileStream
|
678
|
+
const loadedStream = await FileStream.load(largeStream.id, {
|
679
|
+
loadAs: alice,
|
680
|
+
allowUnfinished: true,
|
681
|
+
});
|
682
|
+
|
683
|
+
assert(loadedStream);
|
684
|
+
|
685
|
+
const loadedChunks = loadedStream.getChunks({ allowUnfinished: true });
|
686
|
+
expect(loadedChunks).not.toBeNull();
|
687
|
+
expect(loadedChunks?.finished).toBe(undefined);
|
688
|
+
|
689
|
+
expect(loadedStream._raw.core.knownState()).not.toEqual(
|
690
|
+
largeStream._raw.core.knownState(),
|
691
|
+
);
|
692
|
+
});
|
693
|
+
|
694
|
+
test("load a large FileStream with allowUnfinished: false should return the loaded file only when it's fully loaded", async () => {
|
695
|
+
const syncServer = await setupJazzTestSync({ asyncPeers: true });
|
696
|
+
|
697
|
+
const group = Group.create(syncServer);
|
698
|
+
const largeStream = FileStream.create({ owner: group });
|
699
|
+
group.addMember("everyone", "reader");
|
700
|
+
|
701
|
+
// Create a large file stream with multiple chunks
|
702
|
+
largeStream.start({ mimeType: "application/octet-stream" });
|
703
|
+
|
704
|
+
const dataSize = 100 * 1024; // 100KB total
|
705
|
+
const chunkSize = 1024; // 1KB chunks
|
706
|
+
const numChunks = dataSize / chunkSize;
|
707
|
+
|
708
|
+
// Create test data chunks
|
709
|
+
for (let i = 0; i < numChunks; i++) {
|
710
|
+
const chunk = new Uint8Array(chunkSize);
|
711
|
+
for (let j = 0; j < chunkSize; j++) {
|
712
|
+
chunk[j] = (i * chunkSize + j) % 256;
|
713
|
+
}
|
714
|
+
largeStream.push(chunk);
|
715
|
+
}
|
716
|
+
|
717
|
+
largeStream.end();
|
718
|
+
|
719
|
+
// Wait for the large FileStream to be fully synced
|
720
|
+
await largeStream.waitForSync();
|
721
|
+
|
722
|
+
const alice = await createJazzTestAccount();
|
723
|
+
|
724
|
+
// Test loading the large FileStream
|
725
|
+
const loadedStream = await FileStream.load(largeStream.id, {
|
726
|
+
loadAs: alice,
|
727
|
+
allowUnfinished: false,
|
728
|
+
});
|
729
|
+
|
730
|
+
assert(loadedStream);
|
731
|
+
|
732
|
+
const loadedChunks = loadedStream.getChunks();
|
733
|
+
expect(loadedChunks).not.toBeNull();
|
734
|
+
expect(loadedChunks?.finished).toBe(true);
|
735
|
+
expect(loadedChunks?.chunks).toHaveLength(numChunks); // 100 chunks of 1KB each
|
736
|
+
|
737
|
+
expect(loadedStream._raw.core.knownState()).toEqual(
|
738
|
+
largeStream._raw.core.knownState(),
|
739
|
+
);
|
740
|
+
});
|
741
|
+
});
|
742
|
+
|
792
743
|
describe("waitForSync", async () => {
|
793
744
|
test("CoFeed: should resolve when the value is uploaded", async () => {
|
794
745
|
const TestStream = co.feed(z.string());
|
@@ -543,10 +543,6 @@ describe("CoMap resolution", async () => {
|
|
543
543
|
});
|
544
544
|
|
545
545
|
assert(loadedPerson);
|
546
|
-
expect(loadedPerson.dog).toBe(null);
|
547
|
-
|
548
|
-
await waitFor(() => expect(loadedPerson.dog).toBeTruthy());
|
549
|
-
|
550
546
|
expect(loadedPerson.dog?.name).toEqual("Rex");
|
551
547
|
});
|
552
548
|
|
@@ -652,10 +648,6 @@ describe("CoMap resolution", async () => {
|
|
652
648
|
|
653
649
|
expect(resolved).toBe(true);
|
654
650
|
assert(loadedPerson);
|
655
|
-
expect(loadedPerson.dog).toBe(null);
|
656
|
-
|
657
|
-
await waitFor(() => expect(loadedPerson.dog).toBeTruthy());
|
658
|
-
|
659
651
|
expect(loadedPerson.dog?.name).toEqual("Rex");
|
660
652
|
});
|
661
653
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { WasmCrypto } from "cojson/crypto/WasmCrypto";
|
2
|
+
import { Channel } from "queueueue";
|
2
3
|
import { describe, expect, test } from "vitest";
|
3
4
|
import {
|
4
5
|
Account,
|
@@ -215,7 +216,7 @@ describe("CoPlainText", () => {
|
|
215
216
|
crypto: Crypto,
|
216
217
|
});
|
217
218
|
|
218
|
-
const queue = new
|
219
|
+
const queue = new Channel();
|
219
220
|
|
220
221
|
// Subscribe to text updates
|
221
222
|
co.plainText().subscribe(
|
@@ -409,7 +409,7 @@ describe("Deep loading with unauthorized account", async () => {
|
|
409
409
|
expect(mapOnAlice).toBe(null);
|
410
410
|
|
411
411
|
expect(errorSpy).toHaveBeenCalledWith(
|
412
|
-
`The current user is not authorized to access this value from ${map.id}`,
|
412
|
+
`The current user (${alice.id}) is not authorized to access this value from ${map.id}`,
|
413
413
|
);
|
414
414
|
|
415
415
|
errorSpy.mockReset();
|
@@ -431,7 +431,7 @@ describe("Deep loading with unauthorized account", async () => {
|
|
431
431
|
expect(mapWithListOnAlice).toBe(null);
|
432
432
|
|
433
433
|
expect(errorSpy).toHaveBeenCalledWith(
|
434
|
-
`The current user is not authorized to access this value from ${map.id} on path list`,
|
434
|
+
`The current user (${alice.id}) is not authorized to access this value from ${map.id} on path list`,
|
435
435
|
);
|
436
436
|
|
437
437
|
errorSpy.mockReset();
|
@@ -465,7 +465,7 @@ describe("Deep loading with unauthorized account", async () => {
|
|
465
465
|
expect(mapOnAlice).toBe(null);
|
466
466
|
|
467
467
|
expect(errorSpy).toHaveBeenCalledWith(
|
468
|
-
`The current user is not authorized to access this value from ${map.id} on path list.0`,
|
468
|
+
`The current user (${alice.id}) is not authorized to access this value from ${map.id} on path list.0`,
|
469
469
|
);
|
470
470
|
|
471
471
|
errorSpy.mockReset();
|
@@ -492,7 +492,7 @@ describe("Deep loading with unauthorized account", async () => {
|
|
492
492
|
expect(mapOnAlice?.optionalRef?.value).toBe(undefined);
|
493
493
|
|
494
494
|
expect(errorSpy).toHaveBeenCalledWith(
|
495
|
-
`The current user is not authorized to access this value from ${map.id} on path optionalRef`,
|
495
|
+
`The current user (${alice.id}) is not authorized to access this value from ${map.id} on path optionalRef`,
|
496
496
|
);
|
497
497
|
|
498
498
|
errorSpy.mockReset();
|
@@ -551,7 +551,7 @@ describe("Deep loading with unauthorized account", async () => {
|
|
551
551
|
expect(mapOnAlice).toBe(null);
|
552
552
|
|
553
553
|
expect(errorSpy).toHaveBeenCalledWith(
|
554
|
-
`The current user is not authorized to access this value from ${map.id} on path list.0.stream`,
|
554
|
+
`The current user (${alice.id}) is not authorized to access this value from ${map.id} on path list.0.stream`,
|
555
555
|
);
|
556
556
|
|
557
557
|
errorSpy.mockReset();
|
@@ -587,7 +587,7 @@ describe("Deep loading with unauthorized account", async () => {
|
|
587
587
|
expect(mapOnAlice).toBe(null);
|
588
588
|
|
589
589
|
expect(errorSpy).toHaveBeenCalledWith(
|
590
|
-
`The current user is not authorized to access this value from ${map.id} on path list.0.stream.${value.id}`,
|
590
|
+
`The current user (${alice.id}) is not authorized to access this value from ${map.id} on path list.0.stream.${value.id}`,
|
591
591
|
);
|
592
592
|
|
593
593
|
errorSpy.mockReset();
|