@automerge/automerge-repo 1.0.0-alpha.3 → 1.0.0-alpha.5
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/dist/DocCollection.d.ts +2 -1
- package/dist/DocCollection.d.ts.map +1 -1
- package/dist/DocCollection.js +3 -3
- package/dist/DocHandle.d.ts +8 -3
- package/dist/DocHandle.d.ts.map +1 -1
- package/dist/DocHandle.js +28 -6
- package/dist/DocUrl.d.ts +1 -1
- package/dist/DocUrl.d.ts.map +1 -1
- package/dist/Repo.d.ts.map +1 -1
- package/dist/Repo.js +25 -7
- package/dist/helpers/cbor.d.ts +4 -0
- package/dist/helpers/cbor.d.ts.map +1 -0
- package/dist/helpers/cbor.js +8 -0
- package/dist/helpers/eventPromise.d.ts +1 -1
- package/dist/helpers/eventPromise.d.ts.map +1 -1
- package/dist/helpers/headsAreSame.d.ts +0 -1
- package/dist/helpers/headsAreSame.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/network/NetworkAdapter.d.ts +4 -5
- package/dist/network/NetworkAdapter.d.ts.map +1 -1
- package/dist/network/NetworkAdapter.js +1 -1
- package/dist/network/NetworkSubsystem.d.ts +4 -4
- package/dist/network/NetworkSubsystem.d.ts.map +1 -1
- package/dist/network/NetworkSubsystem.js +28 -14
- package/dist/network/messages.d.ts +2 -2
- package/dist/network/messages.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.d.ts +1 -1
- package/dist/storage/StorageSubsystem.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.js +10 -4
- package/dist/synchronizer/DocSynchronizer.d.ts.map +1 -1
- package/dist/synchronizer/DocSynchronizer.js +11 -12
- package/dist/synchronizer/Synchronizer.d.ts +1 -1
- package/dist/synchronizer/Synchronizer.d.ts.map +1 -1
- package/dist/synchronizer/Synchronizer.js +1 -1
- package/fuzz/fuzz.ts +1 -1
- package/package.json +3 -3
- package/src/DocCollection.ts +4 -3
- package/src/DocHandle.ts +34 -4
- package/src/DocUrl.ts +1 -1
- package/src/Repo.ts +23 -7
- package/src/helpers/cbor.ts +10 -0
- package/src/helpers/eventPromise.ts +1 -1
- package/src/helpers/headsAreSame.ts +1 -1
- package/src/index.ts +2 -0
- package/src/network/NetworkAdapter.ts +4 -6
- package/src/network/NetworkSubsystem.ts +37 -19
- package/src/network/messages.ts +2 -2
- package/src/storage/StorageSubsystem.ts +11 -4
- package/src/synchronizer/DocSynchronizer.ts +14 -14
- package/src/synchronizer/Synchronizer.ts +1 -1
- package/test/CollectionSynchronizer.test.ts +1 -1
- package/test/DocCollection.test.ts +2 -2
- package/test/DocHandle.test.ts +5 -5
- package/test/Repo.test.ts +75 -13
- package/test/StorageSubsystem.test.ts +2 -3
- package/test/helpers/DummyNetworkAdapter.ts +13 -5
- package/test/helpers/DummyStorageAdapter.ts +1 -1
- package/test/helpers/generate-large-object.ts +13 -0
- package/tsconfig.json +2 -2
package/test/Repo.test.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
DocumentId,
|
|
9
9
|
PeerId,
|
|
10
10
|
SharePolicy,
|
|
11
|
-
} from "../src"
|
|
11
|
+
} from "../src/index.js"
|
|
12
12
|
import { eventPromise } from "../src/helpers/eventPromise.js"
|
|
13
13
|
import { pause, rejectOnTimeout } from "../src/helpers/pause.js"
|
|
14
14
|
import { Repo } from "../src/Repo.js"
|
|
@@ -16,19 +16,24 @@ import { DummyNetworkAdapter } from "./helpers/DummyNetworkAdapter.js"
|
|
|
16
16
|
import { DummyStorageAdapter } from "./helpers/DummyStorageAdapter.js"
|
|
17
17
|
import { getRandomItem } from "./helpers/getRandomItem.js"
|
|
18
18
|
import { TestDoc } from "./types.js"
|
|
19
|
-
import { generateAutomergeUrl, stringifyAutomergeUrl } from "../src/DocUrl"
|
|
20
|
-
import { READY } from "../src/DocHandle"
|
|
19
|
+
import { generateAutomergeUrl, stringifyAutomergeUrl } from "../src/DocUrl.js"
|
|
20
|
+
import { READY, AWAITING_NETWORK } from "../src/DocHandle.js"
|
|
21
|
+
import {
|
|
22
|
+
generateLargeObject,
|
|
23
|
+
LargeObject,
|
|
24
|
+
} from "./helpers/generate-large-object.js"
|
|
21
25
|
|
|
22
26
|
describe("Repo", () => {
|
|
23
27
|
describe("single repo", () => {
|
|
24
|
-
const setup = () => {
|
|
28
|
+
const setup = (networkReady = true) => {
|
|
25
29
|
const storageAdapter = new DummyStorageAdapter()
|
|
30
|
+
const networkAdapter = new DummyNetworkAdapter(networkReady)
|
|
26
31
|
|
|
27
32
|
const repo = new Repo({
|
|
28
33
|
storage: storageAdapter,
|
|
29
|
-
network: [
|
|
34
|
+
network: [networkAdapter],
|
|
30
35
|
})
|
|
31
|
-
return { repo, storageAdapter }
|
|
36
|
+
return { repo, storageAdapter, networkAdapter }
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
it("can instantiate a Repo", () => {
|
|
@@ -83,6 +88,22 @@ describe("Repo", () => {
|
|
|
83
88
|
await eventPromise(handle, "unavailable")
|
|
84
89
|
})
|
|
85
90
|
|
|
91
|
+
it("doesn't mark a document as unavailable until network adapters are ready", async () => {
|
|
92
|
+
const { repo, networkAdapter } = setup(false)
|
|
93
|
+
const url = generateAutomergeUrl()
|
|
94
|
+
const handle = repo.find<TestDoc>(url)
|
|
95
|
+
|
|
96
|
+
let wasUnavailable = false
|
|
97
|
+
handle.on("unavailable", () => {
|
|
98
|
+
wasUnavailable = true
|
|
99
|
+
})
|
|
100
|
+
await pause(50)
|
|
101
|
+
assert.equal(wasUnavailable, false)
|
|
102
|
+
|
|
103
|
+
networkAdapter.emit("ready", { network: networkAdapter })
|
|
104
|
+
await eventPromise(handle, "unavailable")
|
|
105
|
+
})
|
|
106
|
+
|
|
86
107
|
it("can find a created document", async () => {
|
|
87
108
|
const { repo } = setup()
|
|
88
109
|
const handle = repo.create<TestDoc>()
|
|
@@ -100,6 +121,20 @@ describe("Repo", () => {
|
|
|
100
121
|
assert.equal(v?.foo, "bar")
|
|
101
122
|
})
|
|
102
123
|
|
|
124
|
+
it("saves the document when creating it", async () => {
|
|
125
|
+
const { repo, storageAdapter } = setup()
|
|
126
|
+
const handle = repo.create<TestDoc>()
|
|
127
|
+
|
|
128
|
+
const repo2 = new Repo({
|
|
129
|
+
storage: storageAdapter,
|
|
130
|
+
network: [],
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
const bobHandle = repo2.find<TestDoc>(handle.url)
|
|
134
|
+
await bobHandle.whenReady()
|
|
135
|
+
assert.equal(bobHandle.isReady(), true)
|
|
136
|
+
})
|
|
137
|
+
|
|
103
138
|
it("saves the document when changed and can find it again", async () => {
|
|
104
139
|
const { repo, storageAdapter } = setup()
|
|
105
140
|
const handle = repo.create<TestDoc>()
|
|
@@ -129,6 +164,7 @@ describe("Repo", () => {
|
|
|
129
164
|
handle.change(d => {
|
|
130
165
|
d.foo = "bar"
|
|
131
166
|
})
|
|
167
|
+
// we now have a snapshot and an incremental change in storage
|
|
132
168
|
assert.equal(handle.isReady(), true)
|
|
133
169
|
await handle.doc()
|
|
134
170
|
repo.delete(handle.documentId)
|
|
@@ -241,6 +277,21 @@ describe("Repo", () => {
|
|
|
241
277
|
assert(storage.keys().length !== 0)
|
|
242
278
|
}
|
|
243
279
|
})
|
|
280
|
+
|
|
281
|
+
it("doesn't create multiple snapshots in storage when a series of large changes are made in succession", async () => {
|
|
282
|
+
const { repo, storageAdapter } = setup()
|
|
283
|
+
const handle = repo.create<{ objects: LargeObject[] }>()
|
|
284
|
+
|
|
285
|
+
for (let i = 0; i < 5; i++) {
|
|
286
|
+
handle.change(d => {
|
|
287
|
+
d.objects = []
|
|
288
|
+
d.objects.push(generateLargeObject(100))
|
|
289
|
+
})
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const storageKeyTypes = storageAdapter.keys().map(k => k.split(".")[1])
|
|
293
|
+
assert(storageKeyTypes.filter(k => k === "snapshot").length === 1)
|
|
294
|
+
})
|
|
244
295
|
})
|
|
245
296
|
|
|
246
297
|
describe("sync", async () => {
|
|
@@ -297,17 +348,28 @@ describe("Repo", () => {
|
|
|
297
348
|
bobCharlieChannel.port1.close()
|
|
298
349
|
}
|
|
299
350
|
|
|
351
|
+
function doConnectAlice() {
|
|
352
|
+
aliceRepo.networkSubsystem.addNetworkAdapter(
|
|
353
|
+
new MessageChannelNetworkAdapter(aliceToBob)
|
|
354
|
+
)
|
|
355
|
+
//bobRepo.networkSubsystem.addNetworkAdapter(new MessageChannelNetworkAdapter(bobToAlice))
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (connectAlice) {
|
|
359
|
+
doConnectAlice()
|
|
360
|
+
}
|
|
361
|
+
|
|
300
362
|
return {
|
|
301
363
|
teardown,
|
|
302
364
|
aliceRepo,
|
|
303
365
|
bobRepo,
|
|
304
366
|
charlieRepo,
|
|
305
|
-
|
|
367
|
+
connectAliceToBob: doConnectAlice,
|
|
306
368
|
}
|
|
307
369
|
}
|
|
308
370
|
|
|
309
371
|
const setup = async (connectAlice = true) => {
|
|
310
|
-
const { teardown, aliceRepo, bobRepo, charlieRepo,
|
|
372
|
+
const { teardown, aliceRepo, bobRepo, charlieRepo, connectAliceToBob } =
|
|
311
373
|
setupRepos(connectAlice)
|
|
312
374
|
|
|
313
375
|
const aliceHandle = aliceRepo.create<TestDoc>()
|
|
@@ -345,7 +407,7 @@ describe("Repo", () => {
|
|
|
345
407
|
notForCharlie,
|
|
346
408
|
notForBob,
|
|
347
409
|
teardown,
|
|
348
|
-
|
|
410
|
+
connectAliceToBob,
|
|
349
411
|
}
|
|
350
412
|
}
|
|
351
413
|
|
|
@@ -443,7 +505,7 @@ describe("Repo", () => {
|
|
|
443
505
|
notForCharlie,
|
|
444
506
|
aliceRepo,
|
|
445
507
|
teardown,
|
|
446
|
-
|
|
508
|
+
connectAliceToBob,
|
|
447
509
|
} = await setup(false)
|
|
448
510
|
|
|
449
511
|
const url = stringifyAutomergeUrl({ documentId: notForCharlie })
|
|
@@ -452,7 +514,7 @@ describe("Repo", () => {
|
|
|
452
514
|
|
|
453
515
|
await eventPromise(handle, "unavailable")
|
|
454
516
|
|
|
455
|
-
|
|
517
|
+
connectAliceToBob()
|
|
456
518
|
|
|
457
519
|
await eventPromise(aliceRepo.networkSubsystem, "peer")
|
|
458
520
|
|
|
@@ -538,9 +600,9 @@ describe("Repo", () => {
|
|
|
538
600
|
const doc =
|
|
539
601
|
Math.random() < 0.5
|
|
540
602
|
? // heads, create a new doc
|
|
541
|
-
|
|
603
|
+
repo.create<TestDoc>()
|
|
542
604
|
: // tails, pick a random doc
|
|
543
|
-
|
|
605
|
+
(getRandomItem(docs) as DocHandle<TestDoc>)
|
|
544
606
|
|
|
545
607
|
// make sure the doc is ready
|
|
546
608
|
if (!doc.isReady()) {
|
|
@@ -4,13 +4,12 @@ import path from "path"
|
|
|
4
4
|
|
|
5
5
|
import assert from "assert"
|
|
6
6
|
|
|
7
|
-
import A from "@automerge/automerge"
|
|
7
|
+
import * as A from "@automerge/automerge/next"
|
|
8
8
|
|
|
9
9
|
import { DummyStorageAdapter } from "./helpers/DummyStorageAdapter.js"
|
|
10
10
|
import { NodeFSStorageAdapter } from "@automerge/automerge-repo-storage-nodefs"
|
|
11
11
|
|
|
12
|
-
import { StorageSubsystem } from "../src"
|
|
13
|
-
import { TestDoc } from "./types.js"
|
|
12
|
+
import { StorageSubsystem } from "../src/index.js"
|
|
14
13
|
import { generateAutomergeUrl, parseAutomergeUrl } from "../src/DocUrl.js"
|
|
15
14
|
|
|
16
15
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "automerge-repo-tests"))
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import { NetworkAdapter } from "../../src"
|
|
1
|
+
import { NetworkAdapter } from "../../src/index.js"
|
|
2
2
|
|
|
3
3
|
export class DummyNetworkAdapter extends NetworkAdapter {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
#startReady = true
|
|
5
|
+
constructor(startReady: boolean) {
|
|
6
|
+
super()
|
|
7
|
+
this.#startReady = startReady
|
|
8
|
+
}
|
|
9
|
+
send() { }
|
|
10
|
+
connect(_: string) {
|
|
11
|
+
if (this.#startReady) {
|
|
12
|
+
this.emit("ready", { network: this })
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
disconnect() { }
|
|
8
16
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type LargeObject = { [key: string]: number }
|
|
2
|
+
|
|
3
|
+
export function generateLargeObject(size: number): LargeObject {
|
|
4
|
+
const largeObject: LargeObject = {}
|
|
5
|
+
|
|
6
|
+
for (let i = 0; i < size; i++) {
|
|
7
|
+
const key = `key${i}`
|
|
8
|
+
const value = Math.random()
|
|
9
|
+
largeObject[key] = value
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return largeObject
|
|
13
|
+
}
|
package/tsconfig.json
CHANGED