jazz-tools 0.7.0-alpha.37 → 0.7.0-alpha.39
Sign up to get free protection for your applications and to get access to all the features.
- package/.eslintrc.cjs +3 -10
- package/.prettierrc.js +9 -0
- package/.turbo/turbo-build.log +1 -95
- package/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-test.log +140 -0
- package/CHANGELOG.md +19 -0
- package/README.md +10 -2
- package/dist/coValues/account.js +22 -12
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/coList.js +7 -9
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.js +11 -3
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.js +15 -8
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/deepLoading.js +57 -0
- package/dist/coValues/deepLoading.js.map +1 -0
- package/dist/coValues/extensions/imageDef.js +1 -1
- package/dist/coValues/extensions/imageDef.js.map +1 -1
- package/dist/coValues/group.js +1 -0
- package/dist/coValues/group.js.map +1 -1
- package/dist/coValues/interfaces.js +34 -28
- package/dist/coValues/interfaces.js.map +1 -1
- package/dist/implementation/devtoolsFormatters.js +1 -0
- package/dist/implementation/devtoolsFormatters.js.map +1 -1
- package/dist/implementation/refs.js +4 -2
- package/dist/implementation/refs.js.map +1 -1
- package/dist/implementation/schema.js +5 -1
- package/dist/implementation/schema.js.map +1 -1
- package/dist/implementation/subscriptionScope.js +9 -4
- package/dist/implementation/subscriptionScope.js.map +1 -1
- package/dist/implementation/symbols.js.map +1 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/internal.js +2 -1
- package/dist/internal.js.map +1 -1
- package/dist/tests/coList.test.js +20 -17
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coMap.test.js +27 -17
- package/dist/tests/coMap.test.js.map +1 -1
- package/dist/tests/coStream.test.js +39 -24
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/deepLoading.test.js +188 -0
- package/dist/tests/deepLoading.test.js.map +1 -0
- package/dist/tests/groupsAndAccounts.test.js +6 -11
- package/dist/tests/groupsAndAccounts.test.js.map +1 -1
- package/package.json +12 -6
- package/src/coValues/account.ts +60 -58
- package/src/coValues/coList.ts +31 -51
- package/src/coValues/coMap.ts +27 -21
- package/src/coValues/coStream.ts +44 -32
- package/src/coValues/deepLoading.ts +215 -0
- package/src/coValues/extensions/imageDef.ts +3 -3
- package/src/coValues/group.ts +11 -13
- package/src/coValues/interfaces.ts +151 -93
- package/src/implementation/devtoolsFormatters.ts +1 -0
- package/src/implementation/inspect.ts +1 -1
- package/src/implementation/refs.ts +29 -15
- package/src/implementation/schema.ts +21 -6
- package/src/implementation/subscriptionScope.ts +33 -17
- package/src/implementation/symbols.ts +0 -1
- package/src/index.ts +5 -3
- package/src/internal.ts +3 -2
- package/src/tests/coList.test.ts +33 -28
- package/src/tests/coMap.test.ts +63 -55
- package/src/tests/coStream.test.ts +82 -67
- package/src/tests/deepLoading.test.ts +301 -0
- package/src/tests/groupsAndAccounts.test.ts +9 -18
@@ -1,26 +1,25 @@
|
|
1
|
-
import { expect, describe, test
|
2
|
-
|
3
|
-
import { webcrypto } from "node:crypto";
|
1
|
+
import { expect, describe, test } from "vitest";
|
4
2
|
import { connectedPeers } from "cojson/src/streamUtils.js";
|
5
3
|
import { newRandomSessionID } from "cojson/src/coValueCore.js";
|
6
4
|
import { Effect, Queue } from "effect";
|
7
|
-
import {
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
5
|
+
import {
|
6
|
+
BinaryCoStream,
|
7
|
+
ID,
|
8
|
+
Account,
|
9
|
+
CoStream,
|
10
|
+
co,
|
11
|
+
WasmCrypto,
|
12
|
+
isControlledAccount,
|
13
|
+
} from "../index.js";
|
14
|
+
|
15
|
+
const Crypto = await WasmCrypto.create();
|
18
16
|
|
19
17
|
describe("Simple CoStream operations", async () => {
|
20
18
|
const me = await Account.create({
|
21
19
|
creationProps: { name: "Hermes Puggington" },
|
20
|
+
crypto: Crypto,
|
22
21
|
});
|
23
|
-
|
22
|
+
if (!isControlledAccount(me)) { throw("me is not a controlled account") }
|
24
23
|
class TestStream extends CoStream.Of(co.string) {}
|
25
24
|
|
26
25
|
const stream = TestStream.create(["milk"], { owner: me });
|
@@ -57,16 +56,17 @@ describe("CoStream resolution", async () => {
|
|
57
56
|
const initNodeAndStream = async () => {
|
58
57
|
const me = await Account.create({
|
59
58
|
creationProps: { name: "Hermes Puggington" },
|
59
|
+
crypto: Crypto,
|
60
60
|
});
|
61
61
|
|
62
62
|
const stream = TestStream.create(
|
63
63
|
[
|
64
64
|
NestedStream.create(
|
65
65
|
[TwiceNestedStream.create(["milk"], { owner: me })],
|
66
|
-
{ owner: me }
|
66
|
+
{ owner: me },
|
67
67
|
),
|
68
68
|
],
|
69
|
-
{ owner: me }
|
69
|
+
{ owner: me },
|
70
70
|
);
|
71
71
|
|
72
72
|
return { me, stream };
|
@@ -75,7 +75,7 @@ describe("CoStream resolution", async () => {
|
|
75
75
|
test("Construction", async () => {
|
76
76
|
const { me, stream } = await initNodeAndStream();
|
77
77
|
expect(stream[me.id]?.value?.[me.id]?.value?.[me.id]?.value).toEqual(
|
78
|
-
"milk"
|
78
|
+
"milk",
|
79
79
|
);
|
80
80
|
});
|
81
81
|
|
@@ -84,80 +84,87 @@ describe("CoStream resolution", async () => {
|
|
84
84
|
const [initialAsPeer, secondPeer] = connectedPeers(
|
85
85
|
"initial",
|
86
86
|
"second",
|
87
|
-
{ peer1role: "server", peer2role: "client" }
|
87
|
+
{ peer1role: "server", peer2role: "client" },
|
88
88
|
);
|
89
|
+
if (!isControlledAccount(me)) { throw("me is not a controlled account") }
|
89
90
|
me._raw.core.node.syncManager.addPeer(secondPeer);
|
90
91
|
const meOnSecondPeer = await Account.become({
|
91
92
|
accountID: me.id,
|
92
93
|
accountSecret: me._raw.agentSecret,
|
93
94
|
peersToLoadFrom: [initialAsPeer],
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
94
96
|
sessionID: newRandomSessionID(me.id as any),
|
97
|
+
crypto: Crypto,
|
95
98
|
});
|
96
99
|
|
97
|
-
const loadedStream = await TestStream.load(
|
98
|
-
|
99
|
-
|
100
|
+
const loadedStream = await TestStream.load(
|
101
|
+
stream.id,
|
102
|
+
meOnSecondPeer,
|
103
|
+
[]
|
104
|
+
);
|
100
105
|
|
101
106
|
expect(loadedStream?.[me.id]?.value).toEqual(null);
|
102
107
|
expect(loadedStream?.[me.id]?.ref?.id).toEqual(
|
103
|
-
stream[me.id]?.value?.id
|
108
|
+
stream[me.id]?.value?.id,
|
104
109
|
);
|
105
110
|
|
106
111
|
const loadedNestedStream = await NestedStream.load(
|
107
112
|
stream[me.id]!.value!.id,
|
108
|
-
|
113
|
+
meOnSecondPeer,
|
114
|
+
[]
|
109
115
|
);
|
110
116
|
|
111
117
|
// expect(loadedStream?.[me.id]?.value).toEqual(loadedNestedStream);
|
112
118
|
expect(loadedStream?.[me.id]?.value?.id).toEqual(
|
113
|
-
loadedNestedStream?.id
|
119
|
+
loadedNestedStream?.id,
|
114
120
|
);
|
115
121
|
expect(loadedStream?.[me.id]?.value?.[me.id]?.value).toEqual(null);
|
116
122
|
// expect(loadedStream?.[me.id]?.ref?.value).toEqual(loadedNestedStream);
|
117
123
|
expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
|
118
|
-
loadedNestedStream?.id
|
124
|
+
loadedNestedStream?.id,
|
119
125
|
);
|
120
126
|
expect(loadedStream?.[me.id]?.value?.[me.id]?.ref?.id).toEqual(
|
121
|
-
stream[me.id]?.value?.[me.id]?.value?.id
|
127
|
+
stream[me.id]?.value?.[me.id]?.value?.id,
|
122
128
|
);
|
123
129
|
|
124
130
|
const loadedTwiceNestedStream = await TwiceNestedStream.load(
|
125
131
|
stream[me.id]!.value![me.id]!.value!.id,
|
126
|
-
|
132
|
+
meOnSecondPeer,
|
133
|
+
[]
|
127
134
|
);
|
128
135
|
|
129
136
|
// expect(loadedStream?.[me.id]?.value?.[me.id]?.value).toEqual(
|
130
137
|
// loadedTwiceNestedStream
|
131
138
|
// );
|
132
139
|
expect(loadedStream?.[me.id]?.value?.[me.id]?.value?.id).toEqual(
|
133
|
-
loadedTwiceNestedStream?.id
|
140
|
+
loadedTwiceNestedStream?.id,
|
134
141
|
);
|
135
142
|
expect(
|
136
|
-
loadedStream?.[me.id]?.value?.[me.id]?.value?.fancyValueOf(me.id)
|
143
|
+
loadedStream?.[me.id]?.value?.[me.id]?.value?.fancyValueOf(me.id),
|
137
144
|
).toEqual("Sir milk");
|
138
145
|
// expect(loadedStream?.[me.id]?.ref?.value).toEqual(loadedNestedStream);
|
139
146
|
expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
|
140
|
-
loadedNestedStream?.id
|
147
|
+
loadedNestedStream?.id,
|
141
148
|
);
|
142
149
|
expect(loadedStream?.[me.id]?.value?.[me.id]?.ref?.value?.id).toEqual(
|
143
|
-
loadedTwiceNestedStream?.id
|
150
|
+
loadedTwiceNestedStream?.id,
|
144
151
|
);
|
145
152
|
|
146
153
|
const otherNestedStream = NestedStream.create(
|
147
154
|
[TwiceNestedStream.create(["butter"], { owner: meOnSecondPeer })],
|
148
|
-
{ owner: meOnSecondPeer }
|
155
|
+
{ owner: meOnSecondPeer },
|
149
156
|
);
|
150
157
|
loadedStream?.push(otherNestedStream);
|
151
158
|
// expect(loadedStream?.[me.id]?.value).toEqual(otherNestedStream);
|
152
159
|
expect(loadedStream?.[me.id]?.value?.id).toEqual(otherNestedStream?.id);
|
153
160
|
expect(loadedStream?.[me.id]?.ref?.value?.id).toEqual(
|
154
|
-
otherNestedStream?.id
|
161
|
+
otherNestedStream?.id,
|
155
162
|
);
|
156
163
|
expect(loadedStream?.[me.id]?.value?.[me.id]?.value?.id).toEqual(
|
157
|
-
otherNestedStream[me.id]?.value?.id
|
164
|
+
otherNestedStream[me.id]?.value?.id,
|
158
165
|
);
|
159
166
|
expect(
|
160
|
-
loadedStream?.[me.id]?.value?.[me.id]?.value?.fancyValueOf(me.id)
|
167
|
+
loadedStream?.[me.id]?.value?.[me.id]?.value?.fancyValueOf(me.id),
|
161
168
|
).toEqual("Sir butter");
|
162
169
|
});
|
163
170
|
|
@@ -167,16 +174,17 @@ describe("CoStream resolution", async () => {
|
|
167
174
|
const [initialAsPeer, secondAsPeer] = connectedPeers(
|
168
175
|
"initial",
|
169
176
|
"second",
|
170
|
-
{ peer1role: "server", peer2role: "client" }
|
177
|
+
{ peer1role: "server", peer2role: "client" },
|
171
178
|
);
|
172
|
-
|
173
179
|
me._raw.core.node.syncManager.addPeer(secondAsPeer);
|
174
|
-
|
180
|
+
if (!isControlledAccount(me)) { throw("me is not a controlled account") }
|
175
181
|
const meOnSecondPeer = await Account.become({
|
176
182
|
accountID: me.id,
|
177
183
|
accountSecret: me._raw.agentSecret,
|
178
184
|
peersToLoadFrom: [initialAsPeer],
|
185
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
179
186
|
sessionID: newRandomSessionID(me.id as any),
|
187
|
+
crypto: Crypto,
|
180
188
|
});
|
181
189
|
|
182
190
|
await Effect.runPromise(
|
@@ -184,30 +192,28 @@ describe("CoStream resolution", async () => {
|
|
184
192
|
const queue = yield* $(Queue.unbounded<TestStream>());
|
185
193
|
|
186
194
|
TestStream.subscribe(
|
187
|
-
stream.id,
|
188
|
-
{ as: meOnSecondPeer },
|
195
|
+
stream.id, meOnSecondPeer , [],
|
189
196
|
(subscribedStream) => {
|
190
197
|
console.log(
|
191
198
|
"subscribedStream[me.id]",
|
192
|
-
subscribedStream[me.id]
|
199
|
+
subscribedStream[me.id],
|
193
200
|
);
|
194
201
|
console.log(
|
195
202
|
"subscribedStream[me.id]?.value?.[me.id]?.value",
|
196
|
-
subscribedStream[me.id]?.value?.[me.id]?.value
|
203
|
+
subscribedStream[me.id]?.value?.[me.id]?.value,
|
197
204
|
);
|
198
205
|
console.log(
|
199
206
|
"subscribedStream[me.id]?.value?.[me.id]?.value?.[me.id]?.value",
|
200
207
|
subscribedStream[me.id]?.value?.[me.id]?.value?.[
|
201
208
|
me.id
|
202
|
-
]?.value
|
209
|
+
]?.value,
|
203
210
|
);
|
204
|
-
Effect.runPromise(
|
205
|
-
|
211
|
+
void Effect.runPromise(
|
212
|
+
Queue.offer(queue, subscribedStream),
|
213
|
+
);
|
214
|
+
},
|
206
215
|
);
|
207
216
|
|
208
|
-
type T = Simplify<TestStream>;
|
209
|
-
const te: T = stream;
|
210
|
-
|
211
217
|
const update1 = yield* $(Queue.take(queue));
|
212
218
|
expect(update1[me.id]?.value).toEqual(null);
|
213
219
|
|
@@ -218,14 +224,14 @@ describe("CoStream resolution", async () => {
|
|
218
224
|
const update3 = yield* $(Queue.take(queue));
|
219
225
|
expect(update3[me.id]?.value?.[me.id]?.value).toBeDefined();
|
220
226
|
expect(
|
221
|
-
update3[me.id]?.value?.[me.id]?.value?.[me.id]?.value
|
227
|
+
update3[me.id]?.value?.[me.id]?.value?.[me.id]?.value,
|
222
228
|
).toBe("milk");
|
223
229
|
|
224
230
|
update3[me.id]!.value![me.id]!.value!.push("bread");
|
225
231
|
|
226
232
|
const update4 = yield* $(Queue.take(queue));
|
227
233
|
expect(
|
228
|
-
update4[me.id]?.value?.[me.id]?.value?.[me.id]?.value
|
234
|
+
update4[me.id]?.value?.[me.id]?.value?.[me.id]?.value,
|
229
235
|
).toBe("bread");
|
230
236
|
|
231
237
|
// When assigning a new nested stream, we get an update
|
@@ -241,16 +247,16 @@ describe("CoStream resolution", async () => {
|
|
241
247
|
|
242
248
|
const update5 = yield* $(Queue.take(queue));
|
243
249
|
expect(
|
244
|
-
update5[me.id]?.value?.[me.id]?.value?.[me.id]?.value
|
250
|
+
update5[me.id]?.value?.[me.id]?.value?.[me.id]?.value,
|
245
251
|
).toBe("butter");
|
246
252
|
|
247
253
|
// we get updates when the new nested stream changes
|
248
254
|
newTwiceNested.push("jam");
|
249
255
|
const update6 = yield* $(Queue.take(queue));
|
250
256
|
expect(
|
251
|
-
update6[me.id]?.value?.[me.id]?.value?.[me.id]?.value
|
257
|
+
update6[me.id]?.value?.[me.id]?.value?.[me.id]?.value,
|
252
258
|
).toBe("jam");
|
253
|
-
})
|
259
|
+
}),
|
254
260
|
);
|
255
261
|
});
|
256
262
|
});
|
@@ -258,6 +264,7 @@ describe("CoStream resolution", async () => {
|
|
258
264
|
describe("Simple BinaryCoStream operations", async () => {
|
259
265
|
const me = await Account.create({
|
260
266
|
creationProps: { name: "Hermes Puggington" },
|
267
|
+
crypto: Crypto,
|
261
268
|
});
|
262
269
|
|
263
270
|
const stream = BinaryCoStream.create({ owner: me });
|
@@ -286,6 +293,7 @@ describe("BinaryCoStream loading & Subscription", async () => {
|
|
286
293
|
const initNodeAndStream = async () => {
|
287
294
|
const me = await Account.create({
|
288
295
|
creationProps: { name: "Hermes Puggington" },
|
296
|
+
crypto: Crypto,
|
289
297
|
});
|
290
298
|
|
291
299
|
const stream = BinaryCoStream.create({ owner: me });
|
@@ -299,7 +307,7 @@ describe("BinaryCoStream loading & Subscription", async () => {
|
|
299
307
|
};
|
300
308
|
|
301
309
|
test("Construction", async () => {
|
302
|
-
const {
|
310
|
+
const { stream } = await initNodeAndStream();
|
303
311
|
expect(stream.getChunks()).toEqual({
|
304
312
|
mimeType: "text/plain",
|
305
313
|
chunks: [new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
|
@@ -312,19 +320,24 @@ describe("BinaryCoStream loading & Subscription", async () => {
|
|
312
320
|
const [initialAsPeer, secondAsPeer] = connectedPeers(
|
313
321
|
"initial",
|
314
322
|
"second",
|
315
|
-
{ peer1role: "server", peer2role: "client" }
|
323
|
+
{ peer1role: "server", peer2role: "client" },
|
316
324
|
);
|
325
|
+
if (!isControlledAccount(me)) { throw("me is not a controlled account") }
|
317
326
|
me._raw.core.node.syncManager.addPeer(secondAsPeer);
|
318
327
|
const meOnSecondPeer = await Account.become({
|
319
328
|
accountID: me.id,
|
320
329
|
accountSecret: me._raw.agentSecret,
|
321
330
|
peersToLoadFrom: [initialAsPeer],
|
331
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
322
332
|
sessionID: newRandomSessionID(me.id as any),
|
333
|
+
crypto: Crypto,
|
323
334
|
});
|
324
335
|
|
325
|
-
const loadedStream = await BinaryCoStream.load(
|
326
|
-
|
327
|
-
|
336
|
+
const loadedStream = await BinaryCoStream.load(
|
337
|
+
stream.id,
|
338
|
+
meOnSecondPeer,
|
339
|
+
[]
|
340
|
+
);
|
328
341
|
|
329
342
|
expect(loadedStream?.getChunks()).toEqual({
|
330
343
|
mimeType: "text/plain",
|
@@ -341,16 +354,17 @@ describe("BinaryCoStream loading & Subscription", async () => {
|
|
341
354
|
const [initialAsPeer, secondAsPeer] = connectedPeers(
|
342
355
|
"initial",
|
343
356
|
"second",
|
344
|
-
{ peer1role: "server", peer2role: "client" }
|
357
|
+
{ peer1role: "server", peer2role: "client" },
|
345
358
|
);
|
346
|
-
|
347
359
|
me._raw.core.node.syncManager.addPeer(secondAsPeer);
|
348
|
-
|
360
|
+
if (!isControlledAccount(me)) { throw("me is not a controlled account") }
|
349
361
|
const meOnSecondPeer = await Account.become({
|
350
362
|
accountID: me.id,
|
351
363
|
accountSecret: me._raw.agentSecret,
|
352
364
|
peersToLoadFrom: [initialAsPeer],
|
365
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
353
366
|
sessionID: newRandomSessionID(me.id as any),
|
367
|
+
crypto: Crypto,
|
354
368
|
});
|
355
369
|
|
356
370
|
await Effect.runPromise(
|
@@ -358,11 +372,12 @@ describe("BinaryCoStream loading & Subscription", async () => {
|
|
358
372
|
const queue = yield* $(Queue.unbounded<BinaryCoStream>());
|
359
373
|
|
360
374
|
BinaryCoStream.subscribe(
|
361
|
-
stream.id,
|
362
|
-
{ as: meOnSecondPeer },
|
375
|
+
stream.id, meOnSecondPeer, [],
|
363
376
|
(subscribedStream) => {
|
364
|
-
Effect.runPromise(
|
365
|
-
|
377
|
+
void Effect.runPromise(
|
378
|
+
Queue.offer(queue, subscribedStream),
|
379
|
+
);
|
380
|
+
},
|
366
381
|
);
|
367
382
|
|
368
383
|
const update1 = yield* $(Queue.take(queue));
|
@@ -417,7 +432,7 @@ describe("BinaryCoStream loading & Subscription", async () => {
|
|
417
432
|
totalSizeBytes: undefined,
|
418
433
|
finished: true,
|
419
434
|
});
|
420
|
-
})
|
435
|
+
}),
|
421
436
|
);
|
422
437
|
});
|
423
438
|
});
|
@@ -0,0 +1,301 @@
|
|
1
|
+
const Crypto = await WasmCrypto.create();
|
2
|
+
import { expect, describe, test, expectTypeOf } from "vitest";
|
3
|
+
import { connectedPeers } from "cojson/src/streamUtils.js";
|
4
|
+
import {
|
5
|
+
Account,
|
6
|
+
CoList,
|
7
|
+
CoMap,
|
8
|
+
CoStream,
|
9
|
+
SessionID,
|
10
|
+
WasmCrypto,
|
11
|
+
co,
|
12
|
+
Profile,
|
13
|
+
isControlledAccount,
|
14
|
+
ID,
|
15
|
+
} from "../index.js";
|
16
|
+
import { newRandomSessionID } from "cojson/src/coValueCore.js";
|
17
|
+
|
18
|
+
class TestMap extends CoMap {
|
19
|
+
list = co.ref(TestList);
|
20
|
+
optionalRef? = co.ref(InnermostMap);
|
21
|
+
}
|
22
|
+
|
23
|
+
class TestList extends CoList.Of(co.ref(() => InnerMap)) {}
|
24
|
+
|
25
|
+
class InnerMap extends CoMap {
|
26
|
+
stream = co.ref(TestStream);
|
27
|
+
}
|
28
|
+
|
29
|
+
class TestStream extends CoStream.Of(co.ref(() => InnermostMap)) {}
|
30
|
+
|
31
|
+
class InnermostMap extends CoMap {
|
32
|
+
value = co.string;
|
33
|
+
}
|
34
|
+
|
35
|
+
describe("Deep loading with depth arg", async () => {
|
36
|
+
const me = await Account.create({
|
37
|
+
creationProps: { name: "Hermes Puggington" },
|
38
|
+
crypto: Crypto,
|
39
|
+
});
|
40
|
+
|
41
|
+
const [initialAsPeer, secondPeer] = connectedPeers("initial", "second", {
|
42
|
+
peer1role: "server",
|
43
|
+
peer2role: "client",
|
44
|
+
});
|
45
|
+
if (!isControlledAccount(me)) {
|
46
|
+
throw "me is not a controlled account";
|
47
|
+
}
|
48
|
+
me._raw.core.node.syncManager.addPeer(secondPeer);
|
49
|
+
const meOnSecondPeer = await Account.become({
|
50
|
+
accountID: me.id,
|
51
|
+
accountSecret: me._raw.agentSecret,
|
52
|
+
peersToLoadFrom: [initialAsPeer],
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
54
|
+
sessionID: newRandomSessionID(me.id as any),
|
55
|
+
crypto: Crypto,
|
56
|
+
});
|
57
|
+
|
58
|
+
test("loading a deeply nested object will wait until all required refs are loaded", async () => {
|
59
|
+
const map = TestMap.create(
|
60
|
+
{
|
61
|
+
list: TestList.create(
|
62
|
+
[
|
63
|
+
InnerMap.create(
|
64
|
+
{
|
65
|
+
stream: TestStream.create(
|
66
|
+
[
|
67
|
+
InnermostMap.create(
|
68
|
+
{ value: "hello" },
|
69
|
+
{ owner: me },
|
70
|
+
),
|
71
|
+
],
|
72
|
+
{ owner: me },
|
73
|
+
),
|
74
|
+
},
|
75
|
+
{ owner: me },
|
76
|
+
),
|
77
|
+
],
|
78
|
+
{ owner: me },
|
79
|
+
),
|
80
|
+
},
|
81
|
+
{ owner: me },
|
82
|
+
);
|
83
|
+
|
84
|
+
const map1 = await TestMap.load(map.id, meOnSecondPeer, {});
|
85
|
+
expectTypeOf(map1).toEqualTypeOf<TestMap | undefined>();
|
86
|
+
if (map1 === undefined) {
|
87
|
+
throw new Error("map1 is undefined");
|
88
|
+
}
|
89
|
+
expect(map1.list).toBe(null);
|
90
|
+
|
91
|
+
const map2 = await TestMap.load(map.id, meOnSecondPeer, { list: [] });
|
92
|
+
expectTypeOf(map2).toEqualTypeOf<
|
93
|
+
| (TestMap & {
|
94
|
+
list: TestList;
|
95
|
+
})
|
96
|
+
| undefined
|
97
|
+
>();
|
98
|
+
if (map2 === undefined) {
|
99
|
+
throw new Error("map2 is undefined");
|
100
|
+
}
|
101
|
+
expect(map2.list).not.toBe(null);
|
102
|
+
expect(map2.list[0]).toBe(null);
|
103
|
+
|
104
|
+
const map3 = await TestMap.load(map.id, meOnSecondPeer, { list: [{}] });
|
105
|
+
expectTypeOf(map3).toEqualTypeOf<
|
106
|
+
| (TestMap & {
|
107
|
+
list: TestList & InnerMap[];
|
108
|
+
})
|
109
|
+
| undefined
|
110
|
+
>();
|
111
|
+
if (map3 === undefined) {
|
112
|
+
throw new Error("map3 is undefined");
|
113
|
+
}
|
114
|
+
expect(map3.list[0]).not.toBe(null);
|
115
|
+
expect(map3.list[0]?.stream).toBe(null);
|
116
|
+
|
117
|
+
const map3a = await TestMap.load(map.id, meOnSecondPeer, {
|
118
|
+
optionalRef: {},
|
119
|
+
});
|
120
|
+
expectTypeOf(map3a).toEqualTypeOf<
|
121
|
+
| (TestMap & {
|
122
|
+
optionalRef: InnermostMap | undefined;
|
123
|
+
})
|
124
|
+
| undefined
|
125
|
+
>();
|
126
|
+
|
127
|
+
const map4 = await TestMap.load(map.id, meOnSecondPeer, {
|
128
|
+
list: [{ stream: [] }],
|
129
|
+
});
|
130
|
+
expectTypeOf(map4).toEqualTypeOf<
|
131
|
+
| (TestMap & {
|
132
|
+
list: TestList & (InnerMap & { stream: TestStream })[];
|
133
|
+
})
|
134
|
+
| undefined
|
135
|
+
>();
|
136
|
+
if (map4 === undefined) {
|
137
|
+
throw new Error("map4 is undefined");
|
138
|
+
}
|
139
|
+
expect(map4.list[0]?.stream).not.toBe(null);
|
140
|
+
// TODO: we should expect null here, but apparently we don't even have the id/ref?
|
141
|
+
expect(map4.list[0]?.stream?.[me.id]?.value).not.toBeDefined();
|
142
|
+
expect(map4.list[0]?.stream?.byMe?.value).not.toBeDefined();
|
143
|
+
|
144
|
+
const map5 = await TestMap.load(map.id, meOnSecondPeer, {
|
145
|
+
list: [{ stream: [{}] }],
|
146
|
+
});
|
147
|
+
type ExpectedMap5 =
|
148
|
+
| (TestMap & {
|
149
|
+
list: TestList &
|
150
|
+
(InnerMap & {
|
151
|
+
stream: TestStream & {
|
152
|
+
byMe?: { value: InnermostMap };
|
153
|
+
inCurrentSession?: { value: InnermostMap };
|
154
|
+
perSession: {
|
155
|
+
[sessionID: SessionID]: {
|
156
|
+
value: InnermostMap;
|
157
|
+
};
|
158
|
+
};
|
159
|
+
} & {
|
160
|
+
[key: ID<Account>]: { value: InnermostMap };
|
161
|
+
};
|
162
|
+
})[];
|
163
|
+
})
|
164
|
+
| undefined;
|
165
|
+
|
166
|
+
expectTypeOf(map5).toEqualTypeOf<ExpectedMap5>();
|
167
|
+
if (map5 === undefined) {
|
168
|
+
throw new Error("map5 is undefined");
|
169
|
+
}
|
170
|
+
expect(map5.list[0]?.stream?.[me.id]?.value).not.toBe(null);
|
171
|
+
expect(map5.list[0]?.stream?.byMe?.value).not.toBe(null);
|
172
|
+
});
|
173
|
+
});
|
174
|
+
|
175
|
+
class CustomProfile extends Profile {
|
176
|
+
stream = co.ref(TestStream);
|
177
|
+
}
|
178
|
+
|
179
|
+
class CustomAccount extends Account {
|
180
|
+
profile = co.ref(CustomProfile);
|
181
|
+
root = co.ref(TestMap);
|
182
|
+
|
183
|
+
async migrate(creationProps?: { name: string } | undefined) {
|
184
|
+
if (creationProps) {
|
185
|
+
this.profile = CustomProfile.create(
|
186
|
+
{
|
187
|
+
name: creationProps.name,
|
188
|
+
stream: TestStream.create([], { owner: this }),
|
189
|
+
},
|
190
|
+
{ owner: this },
|
191
|
+
);
|
192
|
+
this.root = TestMap.create(
|
193
|
+
{ list: TestList.create([], { owner: this }) },
|
194
|
+
{ owner: this },
|
195
|
+
);
|
196
|
+
}
|
197
|
+
|
198
|
+
const thisLoaded = await CustomAccount.load(this, {
|
199
|
+
profile: { stream: [] },
|
200
|
+
root: { list: [] },
|
201
|
+
});
|
202
|
+
expectTypeOf(thisLoaded).toEqualTypeOf<
|
203
|
+
| (CustomAccount & {
|
204
|
+
profile: CustomProfile & {
|
205
|
+
stream: TestStream;
|
206
|
+
};
|
207
|
+
root: TestMap & {
|
208
|
+
list: TestList;
|
209
|
+
};
|
210
|
+
})
|
211
|
+
| undefined
|
212
|
+
>();
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
test("Deep loading within account", async () => {
|
217
|
+
const me = await CustomAccount.create({
|
218
|
+
creationProps: { name: "Hermes Puggington" },
|
219
|
+
crypto: Crypto,
|
220
|
+
});
|
221
|
+
|
222
|
+
const meLoaded = await CustomAccount.load(me, {
|
223
|
+
profile: { stream: [] },
|
224
|
+
root: { list: [] },
|
225
|
+
});
|
226
|
+
expectTypeOf(meLoaded).toEqualTypeOf<
|
227
|
+
| (CustomAccount & {
|
228
|
+
profile: CustomProfile & {
|
229
|
+
stream: TestStream;
|
230
|
+
};
|
231
|
+
root: TestMap & {
|
232
|
+
list: TestList;
|
233
|
+
};
|
234
|
+
})
|
235
|
+
| undefined
|
236
|
+
>();
|
237
|
+
if (meLoaded === undefined) {
|
238
|
+
throw new Error("meLoaded is undefined");
|
239
|
+
}
|
240
|
+
expect(meLoaded.profile.stream).not.toBe(null);
|
241
|
+
expect(meLoaded.root.list).not.toBe(null);
|
242
|
+
});
|
243
|
+
|
244
|
+
class RecordLike extends CoMap.Record(co.ref(TestMap)) {}
|
245
|
+
|
246
|
+
test("Deep loading a record-like coMap", async () => {
|
247
|
+
const me = await Account.create({
|
248
|
+
creationProps: { name: "Hermes Puggington" },
|
249
|
+
crypto: Crypto,
|
250
|
+
});
|
251
|
+
|
252
|
+
const [initialAsPeer, secondPeer] = connectedPeers("initial", "second", {
|
253
|
+
peer1role: "server",
|
254
|
+
peer2role: "client",
|
255
|
+
});
|
256
|
+
if (!isControlledAccount(me)) {
|
257
|
+
throw "me is not a controlled account";
|
258
|
+
}
|
259
|
+
me._raw.core.node.syncManager.addPeer(secondPeer);
|
260
|
+
const meOnSecondPeer = await Account.become({
|
261
|
+
accountID: me.id,
|
262
|
+
accountSecret: me._raw.agentSecret,
|
263
|
+
peersToLoadFrom: [initialAsPeer],
|
264
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
265
|
+
sessionID: newRandomSessionID(me.id as any),
|
266
|
+
crypto: Crypto,
|
267
|
+
});
|
268
|
+
|
269
|
+
const record = RecordLike.create(
|
270
|
+
{
|
271
|
+
key1: TestMap.create(
|
272
|
+
{ list: TestList.create([], { owner: me }) },
|
273
|
+
{ owner: me },
|
274
|
+
),
|
275
|
+
key2: TestMap.create(
|
276
|
+
{ list: TestList.create([], { owner: me }) },
|
277
|
+
{ owner: me },
|
278
|
+
),
|
279
|
+
},
|
280
|
+
{ owner: me },
|
281
|
+
);
|
282
|
+
|
283
|
+
const recordLoaded = await RecordLike.load(record.id, meOnSecondPeer, [
|
284
|
+
{ list: [{}] },
|
285
|
+
]);
|
286
|
+
expectTypeOf(recordLoaded).toEqualTypeOf<
|
287
|
+
| (RecordLike & {
|
288
|
+
[key: string]: TestMap & {
|
289
|
+
list: TestList & InnerMap[];
|
290
|
+
};
|
291
|
+
})
|
292
|
+
| undefined
|
293
|
+
>();
|
294
|
+
if (recordLoaded === undefined) {
|
295
|
+
throw new Error("recordLoaded is undefined");
|
296
|
+
}
|
297
|
+
expect(recordLoaded.key1?.list).not.toBe(null);
|
298
|
+
expect(recordLoaded.key1?.list).not.toBe(undefined);
|
299
|
+
expect(recordLoaded.key2?.list).not.toBe(null);
|
300
|
+
expect(recordLoaded.key2?.list).not.toBe(undefined);
|
301
|
+
});
|