@automerge/automerge-repo 2.4.0-alpha.0 → 2.4.0-alpha.1
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/AutomergeUrl.d.ts.map +1 -1
- package/dist/AutomergeUrl.js +1 -5
- package/dist/Repo.d.ts +10 -2
- package/dist/Repo.d.ts.map +1 -1
- package/dist/Repo.js +17 -11
- package/package.json +2 -2
- package/src/AutomergeUrl.ts +1 -5
- package/src/Repo.ts +30 -10
- package/test/AutomergeUrl.test.ts +10 -5
- package/test/Repo.test.ts +45 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutomergeUrl.d.ts","sourceRoot":"","sources":["../src/AutomergeUrl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,QAAQ,EACT,MAAM,YAAY,CAAA;AASnB,OAAO,KAAK,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAExE,eAAO,MAAM,SAAS,eAAe,CAAA;AAErC,UAAU,kBAAkB;IAC1B,2BAA2B;IAC3B,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,8BAA8B;IAC9B,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,sGAAsG;AACtG,eAAO,MAAM,iBAAiB,GAAI,KAAK,YAAY,KAAG,kBAsBrD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAChC,KAAK,UAAU,GAAG,UAAU,GAAG,gBAAgB,KAC9C,YAgCF,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,eAAe,GAAI,KAAK,YAAY,KAAG,MAAM,EAAE,GAAG,SAG9D,CAAA;AAED,eAAO,MAAM,2BAA2B,GAAI,IAAI,aAAa,6BAO9C,CAAA;AAEf;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,KAAK,OAAO,KAAG,GAAG,IAAI,YAsBzD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,KAAK,OAAO,KAAG,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"AutomergeUrl.d.ts","sourceRoot":"","sources":["../src/AutomergeUrl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,QAAQ,EACT,MAAM,YAAY,CAAA;AASnB,OAAO,KAAK,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAExE,eAAO,MAAM,SAAS,eAAe,CAAA;AAErC,UAAU,kBAAkB;IAC1B,2BAA2B;IAC3B,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,8BAA8B;IAC9B,UAAU,EAAE,UAAU,CAAA;IACtB,mDAAmD;IACnD,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,sGAAsG;AACtG,eAAO,MAAM,iBAAiB,GAAI,KAAK,YAAY,KAAG,kBAsBrD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAChC,KAAK,UAAU,GAAG,UAAU,GAAG,gBAAgB,KAC9C,YAgCF,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,eAAe,GAAI,KAAK,YAAY,KAAG,MAAM,EAAE,GAAG,SAG9D,CAAA;AAED,eAAO,MAAM,2BAA2B,GAAI,IAAI,aAAa,6BAO9C,CAAA;AAEf;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,KAAK,OAAO,KAAG,GAAG,IAAI,YAsBzD,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,KAAK,OAAO,KAAG,GAAG,IAAI,UAKvD,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,KAAK,OAAO,KAAG,GAAG,IAAI,gBACH,CAAA;AAE/C;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAO,YAGvC,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,OAAO,UAAU,KACjB,gBAAgB,GAAG,SAAS,CAAA;AAE/D,eAAO,MAAM,kBAAkB,GAAI,OAAO,gBAAgB,KAC7B,UAAU,CAAA;AAEvC,eAAO,MAAM,WAAW,GAAI,OAAO,cAAc,KAAG,QACsB,CAAA;AAE1E,eAAO,MAAM,WAAW,GAAI,OAAO,QAAQ,KAAG,cACgC,CAAA;AAE9E,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,6BAI1C,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAAI,IAAI,aAAa,eAqBtD,CAAA;AAID,KAAK,UAAU,GAAG;IAChB,UAAU,EAAE,UAAU,GAAG,gBAAgB,CAAA;IACzC,KAAK,CAAC,EAAE,QAAQ,CAAA;CACjB,CAAA"}
|
package/dist/AutomergeUrl.js
CHANGED
|
@@ -103,11 +103,7 @@ export const isValidDocumentId = (str) => {
|
|
|
103
103
|
return false;
|
|
104
104
|
// try to decode from base58
|
|
105
105
|
const binaryDocumentID = documentIdToBinary(str);
|
|
106
|
-
|
|
107
|
-
return false; // invalid base58check encoding
|
|
108
|
-
// confirm that the document ID is a valid UUID
|
|
109
|
-
const documentId = Uuid.stringify(binaryDocumentID);
|
|
110
|
-
return Uuid.validate(documentId);
|
|
106
|
+
return binaryDocumentID !== undefined;
|
|
111
107
|
};
|
|
112
108
|
export const isValidUuid = (str) => typeof str === "string" && Uuid.validate(str);
|
|
113
109
|
/**
|
package/dist/Repo.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Heads } from "@automerge/automerge/slim";
|
|
1
2
|
import { EventEmitter } from "eventemitter3";
|
|
2
3
|
import { DocHandle } from "./DocHandle.js";
|
|
3
4
|
import { NetworkAdapterInterface, type PeerMetadata } from "./network/NetworkAdapterInterface.js";
|
|
@@ -39,7 +40,7 @@ export declare class Repo extends EventEmitter<RepoEvents> {
|
|
|
39
40
|
/** maps peer id to to persistence information (storageId, isEphemeral), access by collection synchronizer */
|
|
40
41
|
/** @hidden */
|
|
41
42
|
peerMetadataByPeerId: Record<PeerId, PeerMetadata>;
|
|
42
|
-
constructor({ storage, network, peerId, sharePolicy, shareConfig, isEphemeral, enableRemoteHeadsGossiping, denylist, saveDebounceRate, }?: RepoConfig);
|
|
43
|
+
constructor({ storage, network, peerId, sharePolicy, shareConfig, isEphemeral, enableRemoteHeadsGossiping, denylist, saveDebounceRate, idFactory, }?: RepoConfig);
|
|
43
44
|
/** Returns all the handles we have cached. */
|
|
44
45
|
get handles(): Record<DocumentId, DocHandle<any>>;
|
|
45
46
|
/** Returns a list of all connected peer ids */
|
|
@@ -149,13 +150,16 @@ export interface RepoConfig {
|
|
|
149
150
|
/**
|
|
150
151
|
* Normal peers typically share generously with everyone (meaning we sync all our documents with
|
|
151
152
|
* all peers). A server only syncs documents that a peer explicitly requests by ID.
|
|
152
|
-
* @deprecated Use `shareConfig` instead
|
|
153
153
|
*/
|
|
154
154
|
sharePolicy?: SharePolicy;
|
|
155
155
|
/**
|
|
156
156
|
* Whether to share documents with other peers. By default we announce new
|
|
157
157
|
* documents to everyone and allow everyone access to documents, see the
|
|
158
158
|
* documentation for {@link ShareConfig} to override this
|
|
159
|
+
*
|
|
160
|
+
* Note that this is currently an experimental API and will very likely change
|
|
161
|
+
* without a major release.
|
|
162
|
+
* @experimental
|
|
159
163
|
*/
|
|
160
164
|
shareConfig?: ShareConfig;
|
|
161
165
|
/**
|
|
@@ -172,6 +176,10 @@ export interface RepoConfig {
|
|
|
172
176
|
* The debounce rate in milliseconds for saving documents. Defaults to 100ms.
|
|
173
177
|
*/
|
|
174
178
|
saveDebounceRate?: number;
|
|
179
|
+
/**
|
|
180
|
+
* @hidden
|
|
181
|
+
*/
|
|
182
|
+
idFactory?: (initialHeads: Heads) => Uint8Array;
|
|
175
183
|
}
|
|
176
184
|
/** A function that determines whether we should share a document with a peer
|
|
177
185
|
*
|
package/dist/Repo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"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"}
|
package/dist/Repo.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { next as Automerge } from "@automerge/automerge/slim";
|
|
2
2
|
import debug from "debug";
|
|
3
3
|
import { EventEmitter } from "eventemitter3";
|
|
4
|
-
import { encodeHeads, generateAutomergeUrl, interpretAsDocumentId, isValidAutomergeUrl, parseAutomergeUrl, } from "./AutomergeUrl.js";
|
|
4
|
+
import { binaryToDocumentId, encodeHeads, generateAutomergeUrl, interpretAsDocumentId, isValidAutomergeUrl, parseAutomergeUrl, } from "./AutomergeUrl.js";
|
|
5
5
|
import { DELETED, DocHandle, READY, UNAVAILABLE, UNLOADED, } from "./DocHandle.js";
|
|
6
6
|
import { RemoteHeadsSubscriptions } from "./RemoteHeadsSubscriptions.js";
|
|
7
7
|
import { headsAreSame } from "./helpers/headsAreSame.js";
|
|
@@ -45,10 +45,12 @@ export class Repo extends EventEmitter {
|
|
|
45
45
|
#remoteHeadsGossipingEnabled = false;
|
|
46
46
|
#progressCache = {};
|
|
47
47
|
#saveFns = {};
|
|
48
|
-
|
|
48
|
+
#idFactory;
|
|
49
|
+
constructor({ storage, network = [], peerId = randomPeerId(), sharePolicy, shareConfig, isEphemeral = storage === undefined, enableRemoteHeadsGossiping = false, denylist = [], saveDebounceRate = 100, idFactory, } = {}) {
|
|
49
50
|
super();
|
|
50
51
|
this.#remoteHeadsGossipingEnabled = enableRemoteHeadsGossiping;
|
|
51
52
|
this.#log = debug(`automerge-repo:repo`);
|
|
53
|
+
this.#idFactory = idFactory || null;
|
|
52
54
|
// Handle legacy sharePolicy
|
|
53
55
|
if (sharePolicy != null && shareConfig != null) {
|
|
54
56
|
throw new Error("cannot provide both sharePolicy and shareConfig at once");
|
|
@@ -300,21 +302,25 @@ export class Repo extends EventEmitter {
|
|
|
300
302
|
* system. we emit a `document` event to advertise interest in the document.
|
|
301
303
|
*/
|
|
302
304
|
create(initialValue) {
|
|
305
|
+
let initialDoc;
|
|
306
|
+
if (initialValue) {
|
|
307
|
+
initialDoc = Automerge.from(initialValue);
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
initialDoc = Automerge.emptyChange(Automerge.init());
|
|
311
|
+
}
|
|
303
312
|
// Generate a new UUID and store it in the buffer
|
|
304
|
-
|
|
313
|
+
let { documentId } = parseAutomergeUrl(generateAutomergeUrl());
|
|
314
|
+
if (this.#idFactory) {
|
|
315
|
+
const rawDocId = this.#idFactory(Automerge.getHeads(initialDoc));
|
|
316
|
+
documentId = binaryToDocumentId(rawDocId);
|
|
317
|
+
}
|
|
305
318
|
const handle = this.#getHandle({
|
|
306
319
|
documentId,
|
|
307
320
|
});
|
|
308
321
|
this.#registerHandleWithSubsystems(handle);
|
|
309
322
|
handle.update(() => {
|
|
310
|
-
|
|
311
|
-
if (initialValue) {
|
|
312
|
-
nextDoc = Automerge.from(initialValue);
|
|
313
|
-
}
|
|
314
|
-
else {
|
|
315
|
-
nextDoc = Automerge.emptyChange(Automerge.init());
|
|
316
|
-
}
|
|
317
|
-
return nextDoc;
|
|
323
|
+
return initialDoc;
|
|
318
324
|
});
|
|
319
325
|
handle.doneLoading();
|
|
320
326
|
return handle;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automerge/automerge-repo",
|
|
3
|
-
"version": "2.4.0-alpha.
|
|
3
|
+
"version": "2.4.0-alpha.1",
|
|
4
4
|
"description": "A repository object to manage a collection of automerge documents",
|
|
5
5
|
"repository": "https://github.com/automerge/automerge-repo/tree/master/packages/automerge-repo",
|
|
6
6
|
"author": "Peter van Hardenberg <pvh@pvh.ca>",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "a2d02ab1494cd2d47825844316fff9b3c43951c1"
|
|
63
63
|
}
|
package/src/AutomergeUrl.ts
CHANGED
|
@@ -141,11 +141,7 @@ export const isValidDocumentId = (str: unknown): str is DocumentId => {
|
|
|
141
141
|
if (typeof str !== "string") return false
|
|
142
142
|
// try to decode from base58
|
|
143
143
|
const binaryDocumentID = documentIdToBinary(str as DocumentId)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// confirm that the document ID is a valid UUID
|
|
147
|
-
const documentId = Uuid.stringify(binaryDocumentID)
|
|
148
|
-
return Uuid.validate(documentId)
|
|
144
|
+
return binaryDocumentID !== undefined
|
|
149
145
|
}
|
|
150
146
|
|
|
151
147
|
export const isValidUuid = (str: unknown): str is LegacyDocumentId =>
|
package/src/Repo.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { next as Automerge } from "@automerge/automerge/slim"
|
|
1
|
+
import { next as Automerge, Heads } from "@automerge/automerge/slim"
|
|
2
2
|
import debug from "debug"
|
|
3
3
|
import { EventEmitter } from "eventemitter3"
|
|
4
4
|
import {
|
|
5
|
+
binaryToDocumentId,
|
|
5
6
|
encodeHeads,
|
|
6
7
|
generateAutomergeUrl,
|
|
7
8
|
interpretAsDocumentId,
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
import type {
|
|
37
38
|
AnyDocumentId,
|
|
38
39
|
AutomergeUrl,
|
|
40
|
+
BinaryDocumentId,
|
|
39
41
|
DocumentId,
|
|
40
42
|
PeerId,
|
|
41
43
|
} from "./types.js"
|
|
@@ -101,6 +103,7 @@ export class Repo extends EventEmitter<RepoEvents> {
|
|
|
101
103
|
DocumentId,
|
|
102
104
|
(payload: DocHandleEncodedChangePayload<any>) => void
|
|
103
105
|
> = {}
|
|
106
|
+
#idFactory: ((initialHeads: Heads) => Uint8Array) | null
|
|
104
107
|
|
|
105
108
|
constructor({
|
|
106
109
|
storage,
|
|
@@ -112,11 +115,13 @@ export class Repo extends EventEmitter<RepoEvents> {
|
|
|
112
115
|
enableRemoteHeadsGossiping = false,
|
|
113
116
|
denylist = [],
|
|
114
117
|
saveDebounceRate = 100,
|
|
118
|
+
idFactory,
|
|
115
119
|
}: RepoConfig = {}) {
|
|
116
120
|
super()
|
|
117
121
|
this.#remoteHeadsGossipingEnabled = enableRemoteHeadsGossiping
|
|
118
122
|
this.#log = debug(`automerge-repo:repo`)
|
|
119
123
|
|
|
124
|
+
this.#idFactory = idFactory || null
|
|
120
125
|
// Handle legacy sharePolicy
|
|
121
126
|
if (sharePolicy != null && shareConfig != null) {
|
|
122
127
|
throw new Error("cannot provide both sharePolicy and shareConfig at once")
|
|
@@ -446,8 +451,19 @@ export class Repo extends EventEmitter<RepoEvents> {
|
|
|
446
451
|
* system. we emit a `document` event to advertise interest in the document.
|
|
447
452
|
*/
|
|
448
453
|
create<T>(initialValue?: T): DocHandle<T> {
|
|
454
|
+
let initialDoc: Automerge.Doc<T>
|
|
455
|
+
if (initialValue) {
|
|
456
|
+
initialDoc = Automerge.from(initialValue)
|
|
457
|
+
} else {
|
|
458
|
+
initialDoc = Automerge.emptyChange(Automerge.init())
|
|
459
|
+
}
|
|
460
|
+
|
|
449
461
|
// Generate a new UUID and store it in the buffer
|
|
450
|
-
|
|
462
|
+
let { documentId } = parseAutomergeUrl(generateAutomergeUrl())
|
|
463
|
+
if (this.#idFactory) {
|
|
464
|
+
const rawDocId = this.#idFactory(Automerge.getHeads(initialDoc))
|
|
465
|
+
documentId = binaryToDocumentId(rawDocId as BinaryDocumentId)
|
|
466
|
+
}
|
|
451
467
|
const handle = this.#getHandle<T>({
|
|
452
468
|
documentId,
|
|
453
469
|
}) as DocHandle<T>
|
|
@@ -455,13 +471,7 @@ export class Repo extends EventEmitter<RepoEvents> {
|
|
|
455
471
|
this.#registerHandleWithSubsystems(handle)
|
|
456
472
|
|
|
457
473
|
handle.update(() => {
|
|
458
|
-
|
|
459
|
-
if (initialValue) {
|
|
460
|
-
nextDoc = Automerge.from(initialValue)
|
|
461
|
-
} else {
|
|
462
|
-
nextDoc = Automerge.emptyChange(Automerge.init())
|
|
463
|
-
}
|
|
464
|
-
return nextDoc
|
|
474
|
+
return initialDoc
|
|
465
475
|
})
|
|
466
476
|
|
|
467
477
|
handle.doneLoading()
|
|
@@ -937,7 +947,6 @@ export interface RepoConfig {
|
|
|
937
947
|
/**
|
|
938
948
|
* Normal peers typically share generously with everyone (meaning we sync all our documents with
|
|
939
949
|
* all peers). A server only syncs documents that a peer explicitly requests by ID.
|
|
940
|
-
* @deprecated Use `shareConfig` instead
|
|
941
950
|
*/
|
|
942
951
|
sharePolicy?: SharePolicy
|
|
943
952
|
|
|
@@ -945,6 +954,10 @@ export interface RepoConfig {
|
|
|
945
954
|
* Whether to share documents with other peers. By default we announce new
|
|
946
955
|
* documents to everyone and allow everyone access to documents, see the
|
|
947
956
|
* documentation for {@link ShareConfig} to override this
|
|
957
|
+
*
|
|
958
|
+
* Note that this is currently an experimental API and will very likely change
|
|
959
|
+
* without a major release.
|
|
960
|
+
* @experimental
|
|
948
961
|
*/
|
|
949
962
|
shareConfig?: ShareConfig
|
|
950
963
|
|
|
@@ -964,6 +977,13 @@ export interface RepoConfig {
|
|
|
964
977
|
* The debounce rate in milliseconds for saving documents. Defaults to 100ms.
|
|
965
978
|
*/
|
|
966
979
|
saveDebounceRate?: number
|
|
980
|
+
|
|
981
|
+
// This is hidden for now because it's an experimental API, mostly here in order
|
|
982
|
+
// for keyhive to be able to control the ID generation
|
|
983
|
+
/**
|
|
984
|
+
* @hidden
|
|
985
|
+
*/
|
|
986
|
+
idFactory?: (initialHeads: Heads) => Uint8Array
|
|
967
987
|
}
|
|
968
988
|
|
|
969
989
|
/** A function that determines whether we should share a document with a peer
|
|
@@ -2,6 +2,7 @@ import assert from "assert"
|
|
|
2
2
|
import bs58check from "bs58check"
|
|
3
3
|
import { describe, it } from "vitest"
|
|
4
4
|
import {
|
|
5
|
+
binaryToDocumentId,
|
|
5
6
|
generateAutomergeUrl,
|
|
6
7
|
getHeadsFromUrl,
|
|
7
8
|
isValidAutomergeUrl,
|
|
@@ -14,6 +15,7 @@ import type {
|
|
|
14
15
|
BinaryDocumentId,
|
|
15
16
|
DocumentId,
|
|
16
17
|
} from "../src/types.js"
|
|
18
|
+
import { interpretAsDocumentId } from "../src/AutomergeUrl.js"
|
|
17
19
|
|
|
18
20
|
const goodUrl = "automerge:4NMNnkMhL8jXrdJ9jamS58PAVdXu" as AutomergeUrl
|
|
19
21
|
const badChecksumUrl = "automerge:badbadbad" as AutomergeUrl
|
|
@@ -94,15 +96,18 @@ describe("AutomergeUrl", () => {
|
|
|
94
96
|
assert(isValidAutomergeUrl(url) === false)
|
|
95
97
|
})
|
|
96
98
|
|
|
97
|
-
it("should return false for a documentId that is not a valid UUID ", () => {
|
|
98
|
-
const url = stringifyAutomergeUrl({ documentId: badUuidDocumentId })
|
|
99
|
-
assert(isValidAutomergeUrl(url) === false)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
99
|
it("should return false for a documentId that is just some random type", () => {
|
|
103
100
|
assert(isValidAutomergeUrl({ foo: "bar" } as unknown) === false)
|
|
104
101
|
})
|
|
105
102
|
})
|
|
103
|
+
|
|
104
|
+
it("should allow arbitrary uint8array ids", () => {
|
|
105
|
+
const raw = new Uint8Array("custom-id".split("").map(c => c.charCodeAt(0)))
|
|
106
|
+
const documentId = binaryToDocumentId(raw as BinaryDocumentId)
|
|
107
|
+
const url = stringifyAutomergeUrl({ documentId })
|
|
108
|
+
const interpreted = interpretAsDocumentId(url)
|
|
109
|
+
assert.deepStrictEqual(interpreted, documentId)
|
|
110
|
+
})
|
|
106
111
|
})
|
|
107
112
|
|
|
108
113
|
describe("AutomergeUrl with heads", () => {
|
package/test/Repo.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { next as A } from "@automerge/automerge"
|
|
1
|
+
import { next as A, Heads } from "@automerge/automerge"
|
|
2
2
|
import { MessageChannelNetworkAdapter } from "../../automerge-repo-network-messagechannel/src/index.js"
|
|
3
3
|
import assert from "assert"
|
|
4
4
|
import * as Uuid from "uuid"
|
|
@@ -2027,6 +2027,50 @@ describe("Repo.find() abort behavior", () => {
|
|
|
2027
2027
|
controller.abort()
|
|
2028
2028
|
expect(handle.url).toBe(url)
|
|
2029
2029
|
})
|
|
2030
|
+
|
|
2031
|
+
describe("creating a document with a custom ID factory", () => {
|
|
2032
|
+
it("creates a document with the custom ID", async () => {
|
|
2033
|
+
const id = new Uint8Array("custom-id".split("").map(c => c.charCodeAt(0)))
|
|
2034
|
+
const repo = new Repo({
|
|
2035
|
+
idFactory: () => id,
|
|
2036
|
+
})
|
|
2037
|
+
const handle = repo.create()
|
|
2038
|
+
expect(handle.documentId).toBe("9HUp4wuzRMx9MRvN4x")
|
|
2039
|
+
})
|
|
2040
|
+
|
|
2041
|
+
it("passes the heads of the document to the callback", async () => {
|
|
2042
|
+
const id = new Uint8Array("custom-id".split("").map(c => c.charCodeAt(0)))
|
|
2043
|
+
let calledHeads: Heads | null = null
|
|
2044
|
+
const repo = new Repo({
|
|
2045
|
+
idFactory: (heads: Heads) => {
|
|
2046
|
+
calledHeads = heads
|
|
2047
|
+
return id
|
|
2048
|
+
},
|
|
2049
|
+
})
|
|
2050
|
+
const handle = repo.create()
|
|
2051
|
+
const actualHeads = A.getHeads(handle.doc())
|
|
2052
|
+
assert.deepStrictEqual(actualHeads, calledHeads)
|
|
2053
|
+
})
|
|
2054
|
+
|
|
2055
|
+
it("allows syncing documents with a custom ID", async () => {
|
|
2056
|
+
const [aliceToBob, bobToAlice] = DummyNetworkAdapter.createConnectedPair()
|
|
2057
|
+
const alice = new Repo({
|
|
2058
|
+
peerId: "alice" as PeerId,
|
|
2059
|
+
idFactory: () =>
|
|
2060
|
+
new Uint8Array("custom-id".split("").map(c => c.charCodeAt(0))),
|
|
2061
|
+
network: [aliceToBob],
|
|
2062
|
+
})
|
|
2063
|
+
const bob = new Repo({ peerId: "bob" as PeerId, network: [bobToAlice] })
|
|
2064
|
+
aliceToBob.peerCandidate("bob" as PeerId)
|
|
2065
|
+
bobToAlice.peerCandidate("alice" as PeerId)
|
|
2066
|
+
|
|
2067
|
+
await pause(50)
|
|
2068
|
+
|
|
2069
|
+
const handle = alice.create({ foo: "bar" })
|
|
2070
|
+
const bobHandle = await bob.find(handle.url)
|
|
2071
|
+
assert.deepStrictEqual(bobHandle.doc(), { foo: "bar" })
|
|
2072
|
+
})
|
|
2073
|
+
})
|
|
2030
2074
|
})
|
|
2031
2075
|
|
|
2032
2076
|
const warn = console.warn
|