cojson 0.0.11 → 0.0.12
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/README.md +2 -2
- package/dist/account.d.ts +57 -0
- package/dist/account.js +76 -0
- package/dist/account.js.map +1 -0
- package/dist/account.test.d.ts +1 -0
- package/dist/account.test.js +40 -0
- package/dist/account.test.js.map +1 -0
- package/dist/coValue.d.ts +16 -35
- package/dist/coValue.js +49 -112
- package/dist/coValue.js.map +1 -1
- package/dist/coValue.test.js +16 -16
- package/dist/coValue.test.js.map +1 -1
- package/dist/contentType.d.ts +9 -9
- package/dist/contentType.js.map +1 -1
- package/dist/contentType.test.js +13 -17
- package/dist/contentType.test.js.map +1 -1
- package/dist/contentTypes/coList.d.ts +3 -3
- package/dist/contentTypes/coList.js.map +1 -1
- package/dist/contentTypes/coMap.d.ts +31 -21
- package/dist/contentTypes/coMap.js +28 -0
- package/dist/contentTypes/coMap.js.map +1 -1
- package/dist/contentTypes/coStream.d.ts +3 -3
- package/dist/contentTypes/coStream.js.map +1 -1
- package/dist/contentTypes/static.d.ts +4 -4
- package/dist/contentTypes/static.js.map +1 -1
- package/dist/crypto.d.ts +45 -39
- package/dist/crypto.js +68 -49
- package/dist/crypto.js.map +1 -1
- package/dist/crypto.test.js +45 -49
- package/dist/crypto.test.js.map +1 -1
- package/dist/ids.d.ts +5 -3
- package/dist/ids.js +3 -1
- package/dist/ids.js.map +1 -1
- package/dist/index.d.ts +12 -14
- package/dist/index.js +6 -8
- package/dist/index.js.map +1 -1
- package/dist/jsonValue.d.ts +2 -2
- package/dist/node.d.ts +25 -15
- package/dist/node.js +88 -33
- package/dist/node.js.map +1 -1
- package/dist/permissions.d.ts +27 -33
- package/dist/permissions.js +55 -47
- package/dist/permissions.js.map +1 -1
- package/dist/permissions.test.js +231 -314
- package/dist/permissions.test.js.map +1 -1
- package/dist/sync.d.ts +26 -28
- package/dist/sync.js +67 -63
- package/dist/sync.js.map +1 -1
- package/dist/sync.test.js +181 -298
- package/dist/sync.test.js.map +1 -1
- package/dist/testUtils.d.ts +37 -0
- package/dist/testUtils.js +157 -0
- package/dist/testUtils.js.map +1 -0
- package/package.json +1 -1
- package/src/account.test.ts +67 -0
- package/src/account.ts +152 -0
- package/src/coValue.test.ts +17 -31
- package/src/coValue.ts +93 -179
- package/src/contentType.test.ts +18 -45
- package/src/contentType.ts +15 -13
- package/src/contentTypes/coList.ts +4 -4
- package/src/contentTypes/coMap.ts +55 -29
- package/src/contentTypes/coStream.ts +4 -4
- package/src/contentTypes/static.ts +5 -5
- package/src/crypto.test.ts +53 -59
- package/src/crypto.ts +123 -95
- package/src/ids.ts +9 -3
- package/src/index.ts +14 -25
- package/src/jsonValue.ts +2 -2
- package/src/node.ts +189 -61
- package/src/permissions.test.ts +370 -404
- package/src/permissions.ts +126 -109
- package/src/sync.test.ts +258 -432
- package/src/sync.ts +95 -98
- package/src/testUtils.ts +229 -0
package/dist/sync.test.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { LocalNode } from
|
|
3
|
-
import { expectMap } from
|
|
4
|
-
import {
|
|
1
|
+
import { newRandomSessionID } from "./coValue.js";
|
|
2
|
+
import { LocalNode } from "./node.js";
|
|
3
|
+
import { expectMap } from "./contentType.js";
|
|
4
|
+
import { connectedPeers, newStreamPair, randomAnonymousAccountAndSessionID, shouldNotResolve } from "./testUtils.js";
|
|
5
5
|
test("Node replies with initial tx and header to empty subscribe", async () => {
|
|
6
|
-
const admin =
|
|
7
|
-
const
|
|
8
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
6
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
7
|
+
const node = new LocalNode(admin, session);
|
|
9
8
|
const team = node.createTeam();
|
|
10
9
|
const map = team.createMap();
|
|
11
10
|
map.edit((editable) => {
|
|
@@ -21,34 +20,33 @@ test("Node replies with initial tx and header to empty subscribe", async () => {
|
|
|
21
20
|
});
|
|
22
21
|
const writer = inTx.getWriter();
|
|
23
22
|
await writer.write({
|
|
24
|
-
action: "
|
|
25
|
-
|
|
23
|
+
action: "load",
|
|
24
|
+
id: map.coValue.id,
|
|
26
25
|
header: false,
|
|
27
26
|
sessions: {},
|
|
28
27
|
});
|
|
29
28
|
const reader = outRx.getReader();
|
|
30
|
-
expect((await reader.read()).value).toMatchObject(admStateEx(
|
|
29
|
+
// expect((await reader.read()).value).toMatchObject(admStateEx(admin.id));
|
|
31
30
|
expect((await reader.read()).value).toMatchObject(teamStateEx(team));
|
|
32
31
|
const mapTellKnownStateMsg = await reader.read();
|
|
33
32
|
expect(mapTellKnownStateMsg.value).toEqual({
|
|
34
|
-
action: "
|
|
33
|
+
action: "known",
|
|
35
34
|
...map.coValue.knownState(),
|
|
36
35
|
});
|
|
37
|
-
expect((await reader.read()).value).toMatchObject(admContEx(
|
|
36
|
+
// expect((await reader.read()).value).toMatchObject(admContEx(admin.id));
|
|
38
37
|
expect((await reader.read()).value).toMatchObject(teamContentEx(team));
|
|
39
38
|
const newContentMsg = await reader.read();
|
|
40
39
|
expect(newContentMsg.value).toEqual({
|
|
41
|
-
action: "
|
|
42
|
-
|
|
40
|
+
action: "content",
|
|
41
|
+
id: map.coValue.id,
|
|
43
42
|
header: {
|
|
44
43
|
type: "comap",
|
|
45
44
|
ruleset: { type: "ownedByTeam", team: team.id },
|
|
46
45
|
meta: null,
|
|
47
46
|
createdAt: map.coValue.header.createdAt,
|
|
48
47
|
uniqueness: map.coValue.header.uniqueness,
|
|
49
|
-
publicNickname: "map",
|
|
50
48
|
},
|
|
51
|
-
|
|
49
|
+
new: {
|
|
52
50
|
[node.ownSessionID]: {
|
|
53
51
|
after: 0,
|
|
54
52
|
newTransactions: [
|
|
@@ -72,9 +70,8 @@ test("Node replies with initial tx and header to empty subscribe", async () => {
|
|
|
72
70
|
});
|
|
73
71
|
});
|
|
74
72
|
test("Node replies with only new tx to subscribe with some known state", async () => {
|
|
75
|
-
const admin =
|
|
76
|
-
const
|
|
77
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
73
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
74
|
+
const node = new LocalNode(admin, session);
|
|
78
75
|
const team = node.createTeam();
|
|
79
76
|
const map = team.createMap();
|
|
80
77
|
map.edit((editable) => {
|
|
@@ -91,29 +88,29 @@ test("Node replies with only new tx to subscribe with some known state", async (
|
|
|
91
88
|
});
|
|
92
89
|
const writer = inTx.getWriter();
|
|
93
90
|
await writer.write({
|
|
94
|
-
action: "
|
|
95
|
-
|
|
91
|
+
action: "load",
|
|
92
|
+
id: map.coValue.id,
|
|
96
93
|
header: true,
|
|
97
94
|
sessions: {
|
|
98
95
|
[node.ownSessionID]: 1,
|
|
99
96
|
},
|
|
100
97
|
});
|
|
101
98
|
const reader = outRx.getReader();
|
|
102
|
-
expect((await reader.read()).value).toMatchObject(admStateEx(
|
|
99
|
+
// expect((await reader.read()).value).toMatchObject(admStateEx(admin.id));
|
|
103
100
|
expect((await reader.read()).value).toMatchObject(teamStateEx(team));
|
|
104
101
|
const mapTellKnownStateMsg = await reader.read();
|
|
105
102
|
expect(mapTellKnownStateMsg.value).toEqual({
|
|
106
|
-
action: "
|
|
103
|
+
action: "known",
|
|
107
104
|
...map.coValue.knownState(),
|
|
108
105
|
});
|
|
109
|
-
expect((await reader.read()).value).toMatchObject(admContEx(
|
|
106
|
+
// expect((await reader.read()).value).toMatchObject(admContEx(admin.id));
|
|
110
107
|
expect((await reader.read()).value).toMatchObject(teamContentEx(team));
|
|
111
108
|
const mapNewContentMsg = await reader.read();
|
|
112
109
|
expect(mapNewContentMsg.value).toEqual({
|
|
113
|
-
action: "
|
|
114
|
-
|
|
110
|
+
action: "content",
|
|
111
|
+
id: map.coValue.id,
|
|
115
112
|
header: undefined,
|
|
116
|
-
|
|
113
|
+
new: {
|
|
117
114
|
[node.ownSessionID]: {
|
|
118
115
|
after: 1,
|
|
119
116
|
newTransactions: [
|
|
@@ -138,9 +135,8 @@ test("Node replies with only new tx to subscribe with some known state", async (
|
|
|
138
135
|
});
|
|
139
136
|
test.todo("TODO: node only replies with new tx to subscribe with some known state, even in the depended on coValues");
|
|
140
137
|
test("After subscribing, node sends own known state and new txs to peer", async () => {
|
|
141
|
-
const admin =
|
|
142
|
-
const
|
|
143
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
138
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
139
|
+
const node = new LocalNode(admin, session);
|
|
144
140
|
const team = node.createTeam();
|
|
145
141
|
const map = team.createMap();
|
|
146
142
|
const [inRx, inTx] = newStreamPair();
|
|
@@ -153,38 +149,38 @@ test("After subscribing, node sends own known state and new txs to peer", async
|
|
|
153
149
|
});
|
|
154
150
|
const writer = inTx.getWriter();
|
|
155
151
|
await writer.write({
|
|
156
|
-
action: "
|
|
157
|
-
|
|
152
|
+
action: "load",
|
|
153
|
+
id: map.coValue.id,
|
|
158
154
|
header: false,
|
|
159
155
|
sessions: {
|
|
160
156
|
[node.ownSessionID]: 0,
|
|
161
157
|
},
|
|
162
158
|
});
|
|
163
159
|
const reader = outRx.getReader();
|
|
164
|
-
expect((await reader.read()).value).toMatchObject(admStateEx(
|
|
160
|
+
// expect((await reader.read()).value).toMatchObject(admStateEx(admin.id));
|
|
165
161
|
expect((await reader.read()).value).toMatchObject(teamStateEx(team));
|
|
166
162
|
const mapTellKnownStateMsg = await reader.read();
|
|
167
163
|
expect(mapTellKnownStateMsg.value).toEqual({
|
|
168
|
-
action: "
|
|
164
|
+
action: "known",
|
|
169
165
|
...map.coValue.knownState(),
|
|
170
166
|
});
|
|
171
|
-
expect((await reader.read()).value).toMatchObject(admContEx(
|
|
167
|
+
// expect((await reader.read()).value).toMatchObject(admContEx(admin.id));
|
|
172
168
|
expect((await reader.read()).value).toMatchObject(teamContentEx(team));
|
|
173
169
|
const mapNewContentHeaderOnlyMsg = await reader.read();
|
|
174
170
|
expect(mapNewContentHeaderOnlyMsg.value).toEqual({
|
|
175
|
-
action: "
|
|
176
|
-
|
|
171
|
+
action: "content",
|
|
172
|
+
id: map.coValue.id,
|
|
177
173
|
header: map.coValue.header,
|
|
178
|
-
|
|
174
|
+
new: {},
|
|
179
175
|
});
|
|
180
176
|
map.edit((editable) => {
|
|
181
177
|
editable.set("hello", "world", "trusting");
|
|
182
178
|
});
|
|
183
179
|
const mapEditMsg1 = await reader.read();
|
|
184
180
|
expect(mapEditMsg1.value).toEqual({
|
|
185
|
-
action: "
|
|
186
|
-
|
|
187
|
-
|
|
181
|
+
action: "content",
|
|
182
|
+
id: map.coValue.id,
|
|
183
|
+
new: {
|
|
188
184
|
[node.ownSessionID]: {
|
|
189
185
|
after: 0,
|
|
190
186
|
newTransactions: [
|
|
@@ -211,9 +207,9 @@ test("After subscribing, node sends own known state and new txs to peer", async
|
|
|
211
207
|
});
|
|
212
208
|
const mapEditMsg2 = await reader.read();
|
|
213
209
|
expect(mapEditMsg2.value).toEqual({
|
|
214
|
-
action: "
|
|
215
|
-
|
|
216
|
-
|
|
210
|
+
action: "content",
|
|
211
|
+
id: map.coValue.id,
|
|
212
|
+
new: {
|
|
217
213
|
[node.ownSessionID]: {
|
|
218
214
|
after: 1,
|
|
219
215
|
newTransactions: [
|
|
@@ -237,9 +233,8 @@ test("After subscribing, node sends own known state and new txs to peer", async
|
|
|
237
233
|
});
|
|
238
234
|
});
|
|
239
235
|
test("Client replies with known new content to tellKnownState from server", async () => {
|
|
240
|
-
const admin =
|
|
241
|
-
const
|
|
242
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
236
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
237
|
+
const node = new LocalNode(admin, session);
|
|
243
238
|
const team = node.createTeam();
|
|
244
239
|
const map = team.createMap();
|
|
245
240
|
map.edit((editable) => {
|
|
@@ -257,28 +252,28 @@ test("Client replies with known new content to tellKnownState from server", asyn
|
|
|
257
252
|
// expect((await reader.read()).value).toMatchObject(teamStateEx(team));
|
|
258
253
|
const writer = inTx.getWriter();
|
|
259
254
|
await writer.write({
|
|
260
|
-
action: "
|
|
261
|
-
|
|
255
|
+
action: "known",
|
|
256
|
+
id: map.coValue.id,
|
|
262
257
|
header: false,
|
|
263
258
|
sessions: {
|
|
264
259
|
[node.ownSessionID]: 0,
|
|
265
260
|
},
|
|
266
261
|
});
|
|
267
|
-
expect((await reader.read()).value).toMatchObject(admStateEx(
|
|
262
|
+
// expect((await reader.read()).value).toMatchObject(admStateEx(admin.id));
|
|
268
263
|
expect((await reader.read()).value).toMatchObject(teamStateEx(team));
|
|
269
264
|
const mapTellKnownStateMsg = await reader.read();
|
|
270
265
|
expect(mapTellKnownStateMsg.value).toEqual({
|
|
271
|
-
action: "
|
|
266
|
+
action: "known",
|
|
272
267
|
...map.coValue.knownState(),
|
|
273
268
|
});
|
|
274
|
-
expect((await reader.read()).value).toMatchObject(admContEx(
|
|
269
|
+
// expect((await reader.read()).value).toMatchObject(admContEx(admin.id));
|
|
275
270
|
expect((await reader.read()).value).toMatchObject(teamContentEx(team));
|
|
276
271
|
const mapNewContentMsg = await reader.read();
|
|
277
272
|
expect(mapNewContentMsg.value).toEqual({
|
|
278
|
-
action: "
|
|
279
|
-
|
|
273
|
+
action: "content",
|
|
274
|
+
id: map.coValue.id,
|
|
280
275
|
header: map.coValue.header,
|
|
281
|
-
|
|
276
|
+
new: {
|
|
282
277
|
[node.ownSessionID]: {
|
|
283
278
|
after: 0,
|
|
284
279
|
newTransactions: [
|
|
@@ -302,9 +297,8 @@ test("Client replies with known new content to tellKnownState from server", asyn
|
|
|
302
297
|
});
|
|
303
298
|
});
|
|
304
299
|
test("No matter the optimistic known state, node respects invalid known state messages and resyncs", async () => {
|
|
305
|
-
const admin =
|
|
306
|
-
const
|
|
307
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
300
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
301
|
+
const node = new LocalNode(admin, session);
|
|
308
302
|
const team = node.createTeam();
|
|
309
303
|
const map = team.createMap();
|
|
310
304
|
const [inRx, inTx] = newStreamPair();
|
|
@@ -317,29 +311,29 @@ test("No matter the optimistic known state, node respects invalid known state me
|
|
|
317
311
|
});
|
|
318
312
|
const writer = inTx.getWriter();
|
|
319
313
|
await writer.write({
|
|
320
|
-
action: "
|
|
321
|
-
|
|
314
|
+
action: "load",
|
|
315
|
+
id: map.coValue.id,
|
|
322
316
|
header: false,
|
|
323
317
|
sessions: {
|
|
324
318
|
[node.ownSessionID]: 0,
|
|
325
319
|
},
|
|
326
320
|
});
|
|
327
321
|
const reader = outRx.getReader();
|
|
328
|
-
expect((await reader.read()).value).toMatchObject(admStateEx(
|
|
322
|
+
// expect((await reader.read()).value).toMatchObject(admStateEx(admin.id));
|
|
329
323
|
expect((await reader.read()).value).toMatchObject(teamStateEx(team));
|
|
330
324
|
const mapTellKnownStateMsg = await reader.read();
|
|
331
325
|
expect(mapTellKnownStateMsg.value).toEqual({
|
|
332
|
-
action: "
|
|
326
|
+
action: "known",
|
|
333
327
|
...map.coValue.knownState(),
|
|
334
328
|
});
|
|
335
|
-
expect((await reader.read()).value).toMatchObject(admContEx(
|
|
329
|
+
// expect((await reader.read()).value).toMatchObject(admContEx(admin.id));
|
|
336
330
|
expect((await reader.read()).value).toMatchObject(teamContentEx(team));
|
|
337
331
|
const mapNewContentHeaderOnlyMsg = await reader.read();
|
|
338
332
|
expect(mapNewContentHeaderOnlyMsg.value).toEqual({
|
|
339
|
-
action: "
|
|
340
|
-
|
|
333
|
+
action: "content",
|
|
334
|
+
id: map.coValue.id,
|
|
341
335
|
header: map.coValue.header,
|
|
342
|
-
|
|
336
|
+
new: {},
|
|
343
337
|
});
|
|
344
338
|
map.edit((editable) => {
|
|
345
339
|
editable.set("hello", "world", "trusting");
|
|
@@ -350,8 +344,9 @@ test("No matter the optimistic known state, node respects invalid known state me
|
|
|
350
344
|
const _mapEditMsg1 = await reader.read();
|
|
351
345
|
const _mapEditMsg2 = await reader.read();
|
|
352
346
|
await writer.write({
|
|
353
|
-
action: "
|
|
354
|
-
|
|
347
|
+
action: "known",
|
|
348
|
+
isCorrection: true,
|
|
349
|
+
id: map.coValue.id,
|
|
355
350
|
header: true,
|
|
356
351
|
sessions: {
|
|
357
352
|
[node.ownSessionID]: 1,
|
|
@@ -359,10 +354,10 @@ test("No matter the optimistic known state, node respects invalid known state me
|
|
|
359
354
|
});
|
|
360
355
|
const newContentAfterWrongAssumedState = await reader.read();
|
|
361
356
|
expect(newContentAfterWrongAssumedState.value).toEqual({
|
|
362
|
-
action: "
|
|
363
|
-
|
|
357
|
+
action: "content",
|
|
358
|
+
id: map.coValue.id,
|
|
364
359
|
header: undefined,
|
|
365
|
-
|
|
360
|
+
new: {
|
|
366
361
|
[node.ownSessionID]: {
|
|
367
362
|
after: 1,
|
|
368
363
|
newTransactions: [
|
|
@@ -386,9 +381,8 @@ test("No matter the optimistic known state, node respects invalid known state me
|
|
|
386
381
|
});
|
|
387
382
|
});
|
|
388
383
|
test("If we add a peer, but it never subscribes to a coValue, it won't get any messages", async () => {
|
|
389
|
-
const admin =
|
|
390
|
-
const
|
|
391
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
384
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
385
|
+
const node = new LocalNode(admin, session);
|
|
392
386
|
const team = node.createTeam();
|
|
393
387
|
const map = team.createMap();
|
|
394
388
|
const [inRx, _inTx] = newStreamPair();
|
|
@@ -406,9 +400,8 @@ test("If we add a peer, but it never subscribes to a coValue, it won't get any m
|
|
|
406
400
|
await expect(shouldNotResolve(reader.read(), { timeout: 100 })).resolves.toBeUndefined();
|
|
407
401
|
});
|
|
408
402
|
test("If we add a server peer, all updates to all coValues are sent to it, even if it doesn't subscribe", async () => {
|
|
409
|
-
const admin =
|
|
410
|
-
const
|
|
411
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
403
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
404
|
+
const node = new LocalNode(admin, session);
|
|
412
405
|
const team = node.createTeam();
|
|
413
406
|
const map = team.createMap();
|
|
414
407
|
const [inRx, _inTx] = newStreamPair();
|
|
@@ -420,32 +413,32 @@ test("If we add a server peer, all updates to all coValues are sent to it, even
|
|
|
420
413
|
role: "server",
|
|
421
414
|
});
|
|
422
415
|
const reader = outRx.getReader();
|
|
416
|
+
// expect((await reader.read()).value).toMatchObject({
|
|
417
|
+
// action: "load",
|
|
418
|
+
// id: adminID,
|
|
419
|
+
// });
|
|
423
420
|
expect((await reader.read()).value).toMatchObject({
|
|
424
|
-
action: "
|
|
425
|
-
|
|
426
|
-
});
|
|
427
|
-
expect((await reader.read()).value).toMatchObject({
|
|
428
|
-
action: "subscribe",
|
|
429
|
-
coValueID: team.teamMap.coValue.id,
|
|
421
|
+
action: "load",
|
|
422
|
+
id: team.teamMap.coValue.id,
|
|
430
423
|
});
|
|
431
424
|
const mapSubscribeMsg = await reader.read();
|
|
432
425
|
expect(mapSubscribeMsg.value).toEqual({
|
|
433
|
-
action: "
|
|
434
|
-
|
|
426
|
+
action: "load",
|
|
427
|
+
id: map.coValue.id,
|
|
435
428
|
header: true,
|
|
436
429
|
sessions: {},
|
|
437
430
|
});
|
|
438
431
|
map.edit((editable) => {
|
|
439
432
|
editable.set("hello", "world", "trusting");
|
|
440
433
|
});
|
|
441
|
-
expect((await reader.read()).value).toMatchObject(admContEx(
|
|
434
|
+
// expect((await reader.read()).value).toMatchObject(admContEx(admin.id));
|
|
442
435
|
expect((await reader.read()).value).toMatchObject(teamContentEx(team));
|
|
443
436
|
const mapNewContentMsg = await reader.read();
|
|
444
437
|
expect(mapNewContentMsg.value).toEqual({
|
|
445
|
-
action: "
|
|
446
|
-
|
|
438
|
+
action: "content",
|
|
439
|
+
id: map.coValue.id,
|
|
447
440
|
header: map.coValue.header,
|
|
448
|
-
|
|
441
|
+
new: {
|
|
449
442
|
[node.ownSessionID]: {
|
|
450
443
|
after: 0,
|
|
451
444
|
newTransactions: [
|
|
@@ -469,9 +462,8 @@ test("If we add a server peer, all updates to all coValues are sent to it, even
|
|
|
469
462
|
});
|
|
470
463
|
});
|
|
471
464
|
test("If we add a server peer, newly created coValues are auto-subscribed to", async () => {
|
|
472
|
-
const admin =
|
|
473
|
-
const
|
|
474
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
465
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
466
|
+
const node = new LocalNode(admin, session);
|
|
475
467
|
const team = node.createTeam();
|
|
476
468
|
const [inRx, _inTx] = newStreamPair();
|
|
477
469
|
const [outRx, outTx] = newStreamPair();
|
|
@@ -482,35 +474,34 @@ test("If we add a server peer, newly created coValues are auto-subscribed to", a
|
|
|
482
474
|
role: "server",
|
|
483
475
|
});
|
|
484
476
|
const reader = outRx.getReader();
|
|
477
|
+
// expect((await reader.read()).value).toMatchObject({
|
|
478
|
+
// action: "load",
|
|
479
|
+
// id: admin.id,
|
|
480
|
+
// });
|
|
485
481
|
expect((await reader.read()).value).toMatchObject({
|
|
486
|
-
action: "
|
|
487
|
-
|
|
488
|
-
});
|
|
489
|
-
expect((await reader.read()).value).toMatchObject({
|
|
490
|
-
action: "subscribe",
|
|
491
|
-
coValueID: team.teamMap.coValue.id,
|
|
482
|
+
action: "load",
|
|
483
|
+
id: team.teamMap.coValue.id,
|
|
492
484
|
});
|
|
493
485
|
const map = team.createMap();
|
|
494
486
|
const mapSubscribeMsg = await reader.read();
|
|
495
487
|
expect(mapSubscribeMsg.value).toEqual({
|
|
496
|
-
action: "
|
|
488
|
+
action: "load",
|
|
497
489
|
...map.coValue.knownState(),
|
|
498
490
|
});
|
|
499
|
-
expect((await reader.read()).value).toMatchObject(admContEx(adminID));
|
|
491
|
+
// expect((await reader.read()).value).toMatchObject(admContEx(adminID));
|
|
500
492
|
expect((await reader.read()).value).toMatchObject(teamContentEx(team));
|
|
501
493
|
const mapContentMsg = await reader.read();
|
|
502
494
|
expect(mapContentMsg.value).toEqual({
|
|
503
|
-
action: "
|
|
504
|
-
|
|
495
|
+
action: "content",
|
|
496
|
+
id: map.coValue.id,
|
|
505
497
|
header: map.coValue.header,
|
|
506
|
-
|
|
498
|
+
new: {},
|
|
507
499
|
});
|
|
508
500
|
});
|
|
509
501
|
test.todo("TODO: when receiving a subscribe response that is behind our optimistic state (due to already sent content), we ignore it");
|
|
510
502
|
test("When we connect a new server peer, we try to sync all existing coValues to it", async () => {
|
|
511
|
-
const admin =
|
|
512
|
-
const
|
|
513
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
503
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
504
|
+
const node = new LocalNode(admin, session);
|
|
514
505
|
const team = node.createTeam();
|
|
515
506
|
const map = team.createMap();
|
|
516
507
|
const [inRx, _inTx] = newStreamPair();
|
|
@@ -522,22 +513,21 @@ test("When we connect a new server peer, we try to sync all existing coValues to
|
|
|
522
513
|
role: "server",
|
|
523
514
|
});
|
|
524
515
|
const reader = outRx.getReader();
|
|
525
|
-
const _adminSubscribeMessage = await reader.read();
|
|
516
|
+
// const _adminSubscribeMessage = await reader.read();
|
|
526
517
|
const teamSubscribeMessage = await reader.read();
|
|
527
518
|
expect(teamSubscribeMessage.value).toEqual({
|
|
528
|
-
action: "
|
|
519
|
+
action: "load",
|
|
529
520
|
...team.teamMap.coValue.knownState(),
|
|
530
521
|
});
|
|
531
522
|
const secondMessage = await reader.read();
|
|
532
523
|
expect(secondMessage.value).toEqual({
|
|
533
|
-
action: "
|
|
524
|
+
action: "load",
|
|
534
525
|
...map.coValue.knownState(),
|
|
535
526
|
});
|
|
536
527
|
});
|
|
537
528
|
test("When receiving a subscribe with a known state that is ahead of our own, peers should respond with a corresponding subscribe response message", async () => {
|
|
538
|
-
const admin =
|
|
539
|
-
const
|
|
540
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
529
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
530
|
+
const node = new LocalNode(admin, session);
|
|
541
531
|
const team = node.createTeam();
|
|
542
532
|
const map = team.createMap();
|
|
543
533
|
const [inRx, inTx] = newStreamPair();
|
|
@@ -550,27 +540,26 @@ test("When receiving a subscribe with a known state that is ahead of our own, pe
|
|
|
550
540
|
});
|
|
551
541
|
const writer = inTx.getWriter();
|
|
552
542
|
await writer.write({
|
|
553
|
-
action: "
|
|
554
|
-
|
|
543
|
+
action: "load",
|
|
544
|
+
id: map.coValue.id,
|
|
555
545
|
header: true,
|
|
556
546
|
sessions: {
|
|
557
547
|
[node.ownSessionID]: 1,
|
|
558
548
|
},
|
|
559
549
|
});
|
|
560
550
|
const reader = outRx.getReader();
|
|
561
|
-
expect((await reader.read()).value).toMatchObject(admStateEx(
|
|
551
|
+
// expect((await reader.read()).value).toMatchObject(admStateEx(admin.id));
|
|
562
552
|
expect((await reader.read()).value).toMatchObject(teamStateEx(team));
|
|
563
553
|
const mapTellKnownState = await reader.read();
|
|
564
554
|
expect(mapTellKnownState.value).toEqual({
|
|
565
|
-
action: "
|
|
555
|
+
action: "known",
|
|
566
556
|
...map.coValue.knownState(),
|
|
567
557
|
});
|
|
568
558
|
});
|
|
569
559
|
test.skip("When replaying creation and transactions of a coValue as new content, the receiving peer integrates this information", async () => {
|
|
570
560
|
// TODO: this test is mostly correct but also slightly unrealistic, make sure we pass all messages back and forth as expected and then it should work
|
|
571
|
-
const admin =
|
|
572
|
-
const
|
|
573
|
-
const node1 = new LocalNode(admin, newRandomSessionID(adminID));
|
|
561
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
562
|
+
const node1 = new LocalNode(admin, session);
|
|
574
563
|
const team = node1.createTeam();
|
|
575
564
|
const [inRx1, inTx1] = newStreamPair();
|
|
576
565
|
const [outRx1, outTx1] = newStreamPair();
|
|
@@ -582,7 +571,7 @@ test.skip("When replaying creation and transactions of a coValue as new content,
|
|
|
582
571
|
});
|
|
583
572
|
const to1 = inTx1.getWriter();
|
|
584
573
|
const from1 = outRx1.getReader();
|
|
585
|
-
const node2 = new LocalNode(admin, newRandomSessionID(
|
|
574
|
+
const node2 = new LocalNode(admin, newRandomSessionID(admin.id));
|
|
586
575
|
const [inRx2, inTx2] = newStreamPair();
|
|
587
576
|
const [outRx2, outTx2] = newStreamPair();
|
|
588
577
|
node2.sync.addPeer({
|
|
@@ -595,47 +584,47 @@ test.skip("When replaying creation and transactions of a coValue as new content,
|
|
|
595
584
|
const from2 = outRx2.getReader();
|
|
596
585
|
const adminSubscribeMessage = await from1.read();
|
|
597
586
|
expect(adminSubscribeMessage.value).toMatchObject({
|
|
598
|
-
action: "
|
|
599
|
-
|
|
587
|
+
action: "load",
|
|
588
|
+
id: admin.id,
|
|
600
589
|
});
|
|
601
590
|
const teamSubscribeMsg = await from1.read();
|
|
602
591
|
expect(teamSubscribeMsg.value).toMatchObject({
|
|
603
|
-
action: "
|
|
604
|
-
|
|
592
|
+
action: "load",
|
|
593
|
+
id: team.teamMap.coValue.id,
|
|
605
594
|
});
|
|
606
595
|
await to2.write(adminSubscribeMessage.value);
|
|
607
596
|
await to2.write(teamSubscribeMsg.value);
|
|
608
|
-
const adminTellKnownStateMsg = await from2.read();
|
|
609
|
-
expect(adminTellKnownStateMsg.value).toMatchObject(admStateEx(
|
|
597
|
+
// const adminTellKnownStateMsg = await from2.read();
|
|
598
|
+
// expect(adminTellKnownStateMsg.value).toMatchObject(admStateEx(admin.id));
|
|
610
599
|
const teamTellKnownStateMsg = await from2.read();
|
|
611
600
|
expect(teamTellKnownStateMsg.value).toMatchObject(teamStateEx(team));
|
|
612
601
|
expect(node2.sync.peers["test1"].optimisticKnownStates[team.teamMap.coValue.id]).toBeDefined();
|
|
613
|
-
await to1.write(adminTellKnownStateMsg.value);
|
|
602
|
+
// await to1.write(adminTellKnownStateMsg.value!);
|
|
614
603
|
await to1.write(teamTellKnownStateMsg.value);
|
|
615
|
-
const adminContentMsg = await from1.read();
|
|
616
|
-
expect(adminContentMsg.value).toMatchObject(admContEx(
|
|
604
|
+
// const adminContentMsg = await from1.read();
|
|
605
|
+
// expect(adminContentMsg.value).toMatchObject(admContEx(admin.id));
|
|
617
606
|
const teamContentMsg = await from1.read();
|
|
618
607
|
expect(teamContentMsg.value).toMatchObject(teamContentEx(team));
|
|
619
|
-
await to2.write(adminContentMsg.value);
|
|
608
|
+
// await to2.write(adminContentMsg.value!);
|
|
620
609
|
await to2.write(teamContentMsg.value);
|
|
621
610
|
const map = team.createMap();
|
|
622
611
|
const mapSubscriptionMsg = await from1.read();
|
|
623
612
|
expect(mapSubscriptionMsg.value).toMatchObject({
|
|
624
|
-
action: "
|
|
625
|
-
|
|
613
|
+
action: "load",
|
|
614
|
+
id: map.coValue.id,
|
|
626
615
|
});
|
|
627
616
|
const mapNewContentMsg = await from1.read();
|
|
628
617
|
expect(mapNewContentMsg.value).toEqual({
|
|
629
|
-
action: "
|
|
630
|
-
|
|
618
|
+
action: "content",
|
|
619
|
+
id: map.coValue.id,
|
|
631
620
|
header: map.coValue.header,
|
|
632
|
-
|
|
621
|
+
new: {},
|
|
633
622
|
});
|
|
634
623
|
await to2.write(mapSubscriptionMsg.value);
|
|
635
624
|
const mapTellKnownStateMsg = await from2.read();
|
|
636
625
|
expect(mapTellKnownStateMsg.value).toEqual({
|
|
637
|
-
action: "
|
|
638
|
-
|
|
626
|
+
action: "known",
|
|
627
|
+
id: map.coValue.id,
|
|
639
628
|
header: false,
|
|
640
629
|
sessions: {},
|
|
641
630
|
});
|
|
@@ -651,15 +640,14 @@ test.skip("When replaying creation and transactions of a coValue as new content,
|
|
|
651
640
|
});
|
|
652
641
|
test.skip("When loading a coValue on one node, the server node it is requested from replies with all the necessary depended on coValues to make it work", async () => {
|
|
653
642
|
// TODO: this test is mostly correct but also slightly unrealistic, make sure we pass all messages back and forth as expected and then it should work
|
|
654
|
-
const admin =
|
|
655
|
-
const
|
|
656
|
-
const node1 = new LocalNode(admin, newRandomSessionID(adminID));
|
|
643
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
644
|
+
const node1 = new LocalNode(admin, session);
|
|
657
645
|
const team = node1.createTeam();
|
|
658
646
|
const map = team.createMap();
|
|
659
647
|
map.edit((editable) => {
|
|
660
648
|
editable.set("hello", "world", "trusting");
|
|
661
649
|
});
|
|
662
|
-
const node2 = new LocalNode(admin, newRandomSessionID(
|
|
650
|
+
const node2 = new LocalNode(admin, newRandomSessionID(admin.id));
|
|
663
651
|
const [node1asPeer, node2asPeer] = connectedPeers("peer1", "peer2");
|
|
664
652
|
node1.sync.addPeer(node2asPeer);
|
|
665
653
|
node2.sync.addPeer(node1asPeer);
|
|
@@ -667,24 +655,22 @@ test.skip("When loading a coValue on one node, the server node it is requested f
|
|
|
667
655
|
expect(expectMap(node2.expectCoValueLoaded(map.coValue.id).getCurrentContent()).get("hello")).toEqual("world");
|
|
668
656
|
});
|
|
669
657
|
test("Can sync a coValue through a server to another client", async () => {
|
|
670
|
-
const admin =
|
|
671
|
-
const
|
|
672
|
-
const client1 = new LocalNode(admin, newRandomSessionID(adminID));
|
|
658
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
659
|
+
const client1 = new LocalNode(admin, session);
|
|
673
660
|
const team = client1.createTeam();
|
|
674
661
|
const map = team.createMap();
|
|
675
662
|
map.edit((editable) => {
|
|
676
663
|
editable.set("hello", "world", "trusting");
|
|
677
664
|
});
|
|
678
|
-
const serverUser =
|
|
679
|
-
const
|
|
680
|
-
const server = new LocalNode(serverUser, newRandomSessionID(serverUserID));
|
|
665
|
+
const [serverUser, serverSession] = randomAnonymousAccountAndSessionID();
|
|
666
|
+
const server = new LocalNode(serverUser, serverSession);
|
|
681
667
|
const [serverAsPeer, client1AsPeer] = connectedPeers("server", "client1", {
|
|
682
668
|
peer1role: "server",
|
|
683
669
|
peer2role: "client",
|
|
684
670
|
});
|
|
685
671
|
client1.sync.addPeer(serverAsPeer);
|
|
686
672
|
server.sync.addPeer(client1AsPeer);
|
|
687
|
-
const client2 = new LocalNode(admin, newRandomSessionID(
|
|
673
|
+
const client2 = new LocalNode(admin, newRandomSessionID(admin.id));
|
|
688
674
|
const [serverAsOtherPeer, client2AsPeer] = connectedPeers("server", "client2", { peer1role: "server", peer2role: "client" });
|
|
689
675
|
client2.sync.addPeer(serverAsOtherPeer);
|
|
690
676
|
server.sync.addPeer(client2AsPeer);
|
|
@@ -692,17 +678,15 @@ test("Can sync a coValue through a server to another client", async () => {
|
|
|
692
678
|
expect(expectMap(mapOnClient2.getCurrentContent()).get("hello")).toEqual("world");
|
|
693
679
|
});
|
|
694
680
|
test("Can sync a coValue with private transactions through a server to another client", async () => {
|
|
695
|
-
const admin =
|
|
696
|
-
const
|
|
697
|
-
const client1 = new LocalNode(admin, newRandomSessionID(adminID));
|
|
681
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
682
|
+
const client1 = new LocalNode(admin, session);
|
|
698
683
|
const team = client1.createTeam();
|
|
699
684
|
const map = team.createMap();
|
|
700
685
|
map.edit((editable) => {
|
|
701
686
|
editable.set("hello", "world", "private");
|
|
702
687
|
});
|
|
703
|
-
const serverUser =
|
|
704
|
-
const
|
|
705
|
-
const server = new LocalNode(serverUser, newRandomSessionID(serverUserID));
|
|
688
|
+
const [serverUser, serverSession] = randomAnonymousAccountAndSessionID();
|
|
689
|
+
const server = new LocalNode(serverUser, serverSession);
|
|
706
690
|
const [serverAsPeer, client1AsPeer] = connectedPeers("server", "client1", {
|
|
707
691
|
trace: true,
|
|
708
692
|
peer1role: "server",
|
|
@@ -710,7 +694,7 @@ test("Can sync a coValue with private transactions through a server to another c
|
|
|
710
694
|
});
|
|
711
695
|
client1.sync.addPeer(serverAsPeer);
|
|
712
696
|
server.sync.addPeer(client1AsPeer);
|
|
713
|
-
const client2 = new LocalNode(admin, newRandomSessionID(
|
|
697
|
+
const client2 = new LocalNode(admin, newRandomSessionID(admin.id));
|
|
714
698
|
const [serverAsOtherPeer, client2AsPeer] = connectedPeers("server", "client2", { trace: true, peer1role: "server", peer2role: "client" });
|
|
715
699
|
client2.sync.addPeer(serverAsOtherPeer);
|
|
716
700
|
server.sync.addPeer(client2AsPeer);
|
|
@@ -718,9 +702,8 @@ test("Can sync a coValue with private transactions through a server to another c
|
|
|
718
702
|
expect(expectMap(mapOnClient2.getCurrentContent()).get("hello")).toEqual("world");
|
|
719
703
|
});
|
|
720
704
|
test("When a peer's incoming/readable stream closes, we remove the peer", async () => {
|
|
721
|
-
const admin =
|
|
722
|
-
const
|
|
723
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
705
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
706
|
+
const node = new LocalNode(admin, session);
|
|
724
707
|
const team = node.createTeam();
|
|
725
708
|
const [inRx, inTx] = newStreamPair();
|
|
726
709
|
const [outRx, outTx] = newStreamPair();
|
|
@@ -731,37 +714,36 @@ test("When a peer's incoming/readable stream closes, we remove the peer", async
|
|
|
731
714
|
role: "server",
|
|
732
715
|
});
|
|
733
716
|
const reader = outRx.getReader();
|
|
717
|
+
// expect((await reader.read()).value).toMatchObject({
|
|
718
|
+
// action: "load",
|
|
719
|
+
// id: admin.id,
|
|
720
|
+
// });
|
|
734
721
|
expect((await reader.read()).value).toMatchObject({
|
|
735
|
-
action: "
|
|
736
|
-
|
|
737
|
-
});
|
|
738
|
-
expect((await reader.read()).value).toMatchObject({
|
|
739
|
-
action: "subscribe",
|
|
740
|
-
coValueID: team.teamMap.coValue.id,
|
|
722
|
+
action: "load",
|
|
723
|
+
id: team.teamMap.coValue.id,
|
|
741
724
|
});
|
|
742
725
|
const map = team.createMap();
|
|
743
726
|
const mapSubscribeMsg = await reader.read();
|
|
744
727
|
expect(mapSubscribeMsg.value).toEqual({
|
|
745
|
-
action: "
|
|
728
|
+
action: "load",
|
|
746
729
|
...map.coValue.knownState(),
|
|
747
730
|
});
|
|
748
|
-
expect((await reader.read()).value).toMatchObject(admContEx(
|
|
731
|
+
// expect((await reader.read()).value).toMatchObject(admContEx(admin.id));
|
|
749
732
|
expect((await reader.read()).value).toMatchObject(teamContentEx(team));
|
|
750
733
|
const mapContentMsg = await reader.read();
|
|
751
734
|
expect(mapContentMsg.value).toEqual({
|
|
752
|
-
action: "
|
|
753
|
-
|
|
735
|
+
action: "content",
|
|
736
|
+
id: map.coValue.id,
|
|
754
737
|
header: map.coValue.header,
|
|
755
|
-
|
|
738
|
+
new: {},
|
|
756
739
|
});
|
|
757
740
|
await inTx.abort();
|
|
758
741
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
759
742
|
expect(node.sync.peers["test"]).toBeUndefined();
|
|
760
743
|
});
|
|
761
744
|
test("When a peer's outgoing/writable stream closes, we remove the peer", async () => {
|
|
762
|
-
const admin =
|
|
763
|
-
const
|
|
764
|
-
const node = new LocalNode(admin, newRandomSessionID(adminID));
|
|
745
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
746
|
+
const node = new LocalNode(admin, session);
|
|
765
747
|
const team = node.createTeam();
|
|
766
748
|
const [inRx, inTx] = newStreamPair();
|
|
767
749
|
const [outRx, outTx] = newStreamPair();
|
|
@@ -772,28 +754,28 @@ test("When a peer's outgoing/writable stream closes, we remove the peer", async
|
|
|
772
754
|
role: "server",
|
|
773
755
|
});
|
|
774
756
|
const reader = outRx.getReader();
|
|
757
|
+
// expect((await reader.read()).value).toMatchObject({
|
|
758
|
+
// action: "load",
|
|
759
|
+
// id: admin.id,
|
|
760
|
+
// });
|
|
775
761
|
expect((await reader.read()).value).toMatchObject({
|
|
776
|
-
action: "
|
|
777
|
-
|
|
778
|
-
});
|
|
779
|
-
expect((await reader.read()).value).toMatchObject({
|
|
780
|
-
action: "subscribe",
|
|
781
|
-
coValueID: team.teamMap.coValue.id,
|
|
762
|
+
action: "load",
|
|
763
|
+
id: team.teamMap.coValue.id,
|
|
782
764
|
});
|
|
783
765
|
const map = team.createMap();
|
|
784
766
|
const mapSubscribeMsg = await reader.read();
|
|
785
767
|
expect(mapSubscribeMsg.value).toEqual({
|
|
786
|
-
action: "
|
|
768
|
+
action: "load",
|
|
787
769
|
...map.coValue.knownState(),
|
|
788
770
|
});
|
|
789
|
-
expect((await reader.read()).value).toMatchObject(admContEx(
|
|
771
|
+
// expect((await reader.read()).value).toMatchObject(admContEx(admin.id));
|
|
790
772
|
expect((await reader.read()).value).toMatchObject(teamContentEx(team));
|
|
791
773
|
const mapContentMsg = await reader.read();
|
|
792
774
|
expect(mapContentMsg.value).toEqual({
|
|
793
|
-
action: "
|
|
794
|
-
|
|
775
|
+
action: "content",
|
|
776
|
+
id: map.coValue.id,
|
|
795
777
|
header: map.coValue.header,
|
|
796
|
-
|
|
778
|
+
new: {},
|
|
797
779
|
});
|
|
798
780
|
reader.releaseLock();
|
|
799
781
|
await outRx.cancel();
|
|
@@ -804,16 +786,19 @@ test("When a peer's outgoing/writable stream closes, we remove the peer", async
|
|
|
804
786
|
expect(node.sync.peers["test"]).toBeUndefined();
|
|
805
787
|
});
|
|
806
788
|
test("If we start loading a coValue before connecting to a peer that has it, it will load it once we connect", async () => {
|
|
807
|
-
const admin =
|
|
808
|
-
const
|
|
809
|
-
const node1 = new LocalNode(admin, newRandomSessionID(adminID));
|
|
789
|
+
const [admin, session] = randomAnonymousAccountAndSessionID();
|
|
790
|
+
const node1 = new LocalNode(admin, session);
|
|
810
791
|
const team = node1.createTeam();
|
|
811
792
|
const map = team.createMap();
|
|
812
793
|
map.edit((editable) => {
|
|
813
794
|
editable.set("hello", "world", "trusting");
|
|
814
795
|
});
|
|
815
|
-
const node2 = new LocalNode(admin, newRandomSessionID(
|
|
816
|
-
const [node1asPeer, node2asPeer] = connectedPeers("peer1", "peer2", {
|
|
796
|
+
const node2 = new LocalNode(admin, newRandomSessionID(admin.id));
|
|
797
|
+
const [node1asPeer, node2asPeer] = connectedPeers("peer1", "peer2", {
|
|
798
|
+
peer1role: "server",
|
|
799
|
+
peer2role: "client",
|
|
800
|
+
trace: true,
|
|
801
|
+
});
|
|
817
802
|
node1.sync.addPeer(node2asPeer);
|
|
818
803
|
const mapOnNode2Promise = node2.loadCoValue(map.coValue.id);
|
|
819
804
|
expect(node2.coValues[map.coValue.id]?.state).toEqual("loading");
|
|
@@ -823,128 +808,26 @@ test("If we start loading a coValue before connecting to a peer that has it, it
|
|
|
823
808
|
});
|
|
824
809
|
function teamContentEx(team) {
|
|
825
810
|
return {
|
|
826
|
-
action: "
|
|
827
|
-
|
|
811
|
+
action: "content",
|
|
812
|
+
id: team.teamMap.coValue.id,
|
|
828
813
|
};
|
|
829
814
|
}
|
|
830
815
|
function admContEx(adminID) {
|
|
831
816
|
return {
|
|
832
|
-
action: "
|
|
833
|
-
|
|
817
|
+
action: "content",
|
|
818
|
+
id: adminID,
|
|
834
819
|
};
|
|
835
820
|
}
|
|
836
821
|
function teamStateEx(team) {
|
|
837
822
|
return {
|
|
838
|
-
action: "
|
|
839
|
-
|
|
823
|
+
action: "known",
|
|
824
|
+
id: team.teamMap.coValue.id,
|
|
840
825
|
};
|
|
841
826
|
}
|
|
842
827
|
function admStateEx(adminID) {
|
|
843
828
|
return {
|
|
844
|
-
action: "
|
|
845
|
-
|
|
846
|
-
};
|
|
847
|
-
}
|
|
848
|
-
function newStreamPair() {
|
|
849
|
-
const queue = [];
|
|
850
|
-
let resolveNextItemReady = () => { };
|
|
851
|
-
let nextItemReady = new Promise((resolve) => {
|
|
852
|
-
resolveNextItemReady = resolve;
|
|
853
|
-
});
|
|
854
|
-
let writerClosed = false;
|
|
855
|
-
let readerClosed = false;
|
|
856
|
-
const readable = new ReadableStream({
|
|
857
|
-
async pull(controller) {
|
|
858
|
-
let retriesLeft = 3;
|
|
859
|
-
while (retriesLeft > 0) {
|
|
860
|
-
if (writerClosed) {
|
|
861
|
-
controller.close();
|
|
862
|
-
return;
|
|
863
|
-
}
|
|
864
|
-
retriesLeft--;
|
|
865
|
-
if (queue.length > 0) {
|
|
866
|
-
controller.enqueue(queue.shift());
|
|
867
|
-
if (queue.length === 0) {
|
|
868
|
-
nextItemReady = new Promise((resolve) => {
|
|
869
|
-
resolveNextItemReady = resolve;
|
|
870
|
-
});
|
|
871
|
-
}
|
|
872
|
-
return;
|
|
873
|
-
}
|
|
874
|
-
else {
|
|
875
|
-
await nextItemReady;
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
throw new Error("Should only use one retry to get next item in queue.");
|
|
879
|
-
},
|
|
880
|
-
cancel(reason) {
|
|
881
|
-
console.log("Manually closing reader");
|
|
882
|
-
readerClosed = true;
|
|
883
|
-
},
|
|
884
|
-
});
|
|
885
|
-
const writable = new WritableStream({
|
|
886
|
-
write(chunk, controller) {
|
|
887
|
-
if (readerClosed) {
|
|
888
|
-
console.log("Reader closed, not writing chunk", chunk);
|
|
889
|
-
throw new Error("Reader closed, not writing chunk");
|
|
890
|
-
}
|
|
891
|
-
queue.push(chunk);
|
|
892
|
-
if (queue.length === 1) {
|
|
893
|
-
// make sure that await write resolves before corresponding read
|
|
894
|
-
process.nextTick(() => resolveNextItemReady());
|
|
895
|
-
}
|
|
896
|
-
},
|
|
897
|
-
abort(reason) {
|
|
898
|
-
console.log("Manually closing writer");
|
|
899
|
-
writerClosed = true;
|
|
900
|
-
resolveNextItemReady();
|
|
901
|
-
return Promise.resolve();
|
|
902
|
-
},
|
|
903
|
-
});
|
|
904
|
-
return [readable, writable];
|
|
905
|
-
}
|
|
906
|
-
function shouldNotResolve(promise, ops) {
|
|
907
|
-
return new Promise((resolve, reject) => {
|
|
908
|
-
promise
|
|
909
|
-
.then((v) => reject(new Error("Should not have resolved, but resolved to " +
|
|
910
|
-
JSON.stringify(v))))
|
|
911
|
-
.catch(reject);
|
|
912
|
-
setTimeout(resolve, ops.timeout);
|
|
913
|
-
});
|
|
914
|
-
}
|
|
915
|
-
function connectedPeers(peer1id, peer2id, { trace = false, peer1role = "peer", peer2role = "peer", } = {}) {
|
|
916
|
-
const [inRx1, inTx1] = newStreamPair();
|
|
917
|
-
const [outRx1, outTx1] = newStreamPair();
|
|
918
|
-
const [inRx2, inTx2] = newStreamPair();
|
|
919
|
-
const [outRx2, outTx2] = newStreamPair();
|
|
920
|
-
void outRx2
|
|
921
|
-
.pipeThrough(new TransformStream({
|
|
922
|
-
transform(chunk, controller) {
|
|
923
|
-
trace && console.log(`${peer2id} -> ${peer1id}`, chunk);
|
|
924
|
-
controller.enqueue(chunk);
|
|
925
|
-
},
|
|
926
|
-
}))
|
|
927
|
-
.pipeTo(inTx1);
|
|
928
|
-
void outRx1
|
|
929
|
-
.pipeThrough(new TransformStream({
|
|
930
|
-
transform(chunk, controller) {
|
|
931
|
-
trace && console.log(`${peer1id} -> ${peer2id}`, chunk);
|
|
932
|
-
controller.enqueue(chunk);
|
|
933
|
-
},
|
|
934
|
-
}))
|
|
935
|
-
.pipeTo(inTx2);
|
|
936
|
-
const peer2AsPeer = {
|
|
937
|
-
id: peer2id,
|
|
938
|
-
incoming: inRx1,
|
|
939
|
-
outgoing: outTx1,
|
|
940
|
-
role: peer2role,
|
|
941
|
-
};
|
|
942
|
-
const peer1AsPeer = {
|
|
943
|
-
id: peer1id,
|
|
944
|
-
incoming: inRx2,
|
|
945
|
-
outgoing: outTx2,
|
|
946
|
-
role: peer1role,
|
|
829
|
+
action: "known",
|
|
830
|
+
id: adminID,
|
|
947
831
|
};
|
|
948
|
-
return [peer1AsPeer, peer2AsPeer];
|
|
949
832
|
}
|
|
950
833
|
//# sourceMappingURL=sync.test.js.map
|