@automerge/automerge-repo 1.0.0-alpha.4 → 1.0.0
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/.eslintrc +2 -2
- package/dist/DocHandle.d.ts +5 -1
- package/dist/DocHandle.d.ts.map +1 -1
- package/dist/DocHandle.js +11 -3
- package/dist/Repo.d.ts +38 -4
- package/dist/Repo.d.ts.map +1 -1
- package/dist/Repo.js +95 -3
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/network/NetworkAdapter.d.ts +2 -3
- package/dist/network/NetworkAdapter.d.ts.map +1 -1
- package/dist/network/NetworkSubsystem.d.ts +1 -3
- package/dist/network/NetworkSubsystem.d.ts.map +1 -1
- package/dist/network/NetworkSubsystem.js +0 -9
- package/dist/storage/StorageSubsystem.d.ts.map +1 -1
- package/dist/storage/StorageSubsystem.js +8 -2
- package/dist/synchronizer/CollectionSynchronizer.d.ts +2 -2
- package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/DocHandle.ts +13 -5
- package/src/Repo.ts +130 -4
- package/src/index.ts +0 -1
- package/src/network/NetworkAdapter.ts +2 -4
- package/src/network/NetworkSubsystem.ts +14 -23
- package/src/storage/StorageSubsystem.ts +9 -2
- package/src/synchronizer/CollectionSynchronizer.ts +2 -2
- package/test/CollectionSynchronizer.test.ts +12 -11
- package/test/DocHandle.test.ts +2 -1
- package/test/Repo.test.ts +26 -5
- package/test/helpers/DummyNetworkAdapter.ts +2 -3
- package/test/helpers/generate-large-object.ts +13 -0
- package/dist/DocCollection.d.ts +0 -46
- package/dist/DocCollection.d.ts.map +0 -1
- package/dist/DocCollection.js +0 -102
- package/src/DocCollection.ts +0 -144
- package/test/DocCollection.test.ts +0 -20
package/.eslintrc
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"plugin:@typescript-eslint/eslint-recommended",
|
|
9
9
|
"plugin:@typescript-eslint/recommended"
|
|
10
10
|
],
|
|
11
|
-
"ignorePatterns": ["dist/**"],
|
|
11
|
+
"ignorePatterns": ["dist/**", "test/**", "node_modules/**"],
|
|
12
12
|
"parser": "@typescript-eslint/parser",
|
|
13
13
|
"plugins": ["@typescript-eslint", "mocha"],
|
|
14
14
|
"parserOptions": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"import/extensions": 0,
|
|
22
22
|
"lines-between-class-members": 0,
|
|
23
23
|
"@typescript-eslint/no-floating-promises": "error",
|
|
24
|
-
"@typescript-eslint/no-empty-function": ["warn", { "allow": ["methods"]}],
|
|
24
|
+
"@typescript-eslint/no-empty-function": ["warn", { "allow": ["methods"] }],
|
|
25
25
|
"no-param-reassign": 0,
|
|
26
26
|
"no-use-before-define": 0
|
|
27
27
|
}
|
package/dist/DocHandle.d.ts
CHANGED
|
@@ -55,7 +55,11 @@ export declare class DocHandle<T>//
|
|
|
55
55
|
update(callback: (doc: A.Doc<T>) => A.Doc<T>): void;
|
|
56
56
|
/** `change` is called by the repo when the document is changed locally */
|
|
57
57
|
change(callback: A.ChangeFn<T>, options?: A.ChangeOptions<T>): void;
|
|
58
|
-
|
|
58
|
+
/** Make a change as if the document were at `heads`
|
|
59
|
+
*
|
|
60
|
+
* @returns A set of heads representing the concurrent change that was made.
|
|
61
|
+
*/
|
|
62
|
+
changeAt(heads: A.Heads, callback: A.ChangeFn<T>, options?: A.ChangeOptions<T>): string[] | undefined;
|
|
59
63
|
unavailable(): void;
|
|
60
64
|
/** `request` is called by the repo when the document is not found in storage */
|
|
61
65
|
request(): void;
|
package/dist/DocHandle.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,2BAA2B,CAAA;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EASL,UAAU,EAEX,MAAM,QAAQ,CAAA;AAKf,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAIlE,iGAAiG;AACjG,qBAAa,SAAS,CAAC,CAAC,CAAE,EAAE;AAC1B,SAAQ,YAAY,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;;IAY/B,UAAU,EAAE,UAAU;IAL/B,IAAI,GAAG,IAAI,YAAY,CAEtB;gBAGQ,UAAU,EAAE,UAAU,EAC7B,EAAE,KAAa,EAAE,YAAqB,EAAE,GAAE,gBAAqB;IAmMjE;;;;OAIG;IACH,OAAO,gBAA0C;IACjD;;;;;OAKG;IACH,SAAS,gBAA4C;IACrD,aAAa,gBAAgD;IAC7D,OAAO,WAAY,WAAW,EAAE,aACmB;IAEnD,IAAI,KAAK,eAER;IAED;;;;;OAKG;IACG,SAAS,CAAC,WAAW,GAAE,WAAW,EAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE;;;;;;OAMG;IACG,GAAG,CACP,WAAW,GAAE,WAAW,EAAyB,GAChD,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IAchC;;;;;;;;;OASG;IACH,OAAO,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS;IAQ/B,8EAA8E;IAC9E,MAAM,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAM5C,2EAA2E;IAC3E,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAM;IAehE,QAAQ,CACN,KAAK,EAAE,CAAC,CAAC,KAAK,EACd,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EACvB,OAAO,GAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAM;
|
|
1
|
+
{"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"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"}
|
package/dist/DocHandle.js
CHANGED
|
@@ -77,7 +77,7 @@ export class DocHandle//
|
|
|
77
77
|
awaitingNetwork: {
|
|
78
78
|
on: {
|
|
79
79
|
NETWORK_READY: { target: REQUESTING },
|
|
80
|
-
}
|
|
80
|
+
},
|
|
81
81
|
},
|
|
82
82
|
requesting: {
|
|
83
83
|
on: {
|
|
@@ -269,17 +269,25 @@ export class DocHandle//
|
|
|
269
269
|
},
|
|
270
270
|
});
|
|
271
271
|
}
|
|
272
|
+
/** Make a change as if the document were at `heads`
|
|
273
|
+
*
|
|
274
|
+
* @returns A set of heads representing the concurrent change that was made.
|
|
275
|
+
*/
|
|
272
276
|
changeAt(heads, callback, options = {}) {
|
|
273
277
|
if (!this.isReady()) {
|
|
274
278
|
throw new Error(`DocHandle#${this.documentId} is not ready. Check \`handle.isReady()\` before accessing the document.`);
|
|
275
279
|
}
|
|
280
|
+
let resultHeads = undefined;
|
|
276
281
|
this.#machine.send(UPDATE, {
|
|
277
282
|
payload: {
|
|
278
283
|
callback: (doc) => {
|
|
279
|
-
|
|
284
|
+
const result = A.changeAt(doc, heads, options, callback);
|
|
285
|
+
resultHeads = result.newHeads;
|
|
286
|
+
return result.newDoc;
|
|
280
287
|
},
|
|
281
288
|
},
|
|
282
289
|
});
|
|
290
|
+
return resultHeads;
|
|
283
291
|
}
|
|
284
292
|
unavailable() {
|
|
285
293
|
this.#machine.send(MARK_UNAVAILABLE);
|
|
@@ -341,4 +349,4 @@ export const Event = {
|
|
|
341
349
|
};
|
|
342
350
|
// CONSTANTS
|
|
343
351
|
export const { IDLE, LOADING, AWAITING_NETWORK, REQUESTING, READY, FAILED, DELETED, UNAVAILABLE, } = HandleState;
|
|
344
|
-
const { CREATE, FIND, REQUEST, UPDATE, TIMEOUT, DELETE, REQUEST_COMPLETE, MARK_UNAVAILABLE, AWAIT_NETWORK, NETWORK_READY } = Event;
|
|
352
|
+
const { CREATE, FIND, REQUEST, UPDATE, TIMEOUT, DELETE, REQUEST_COMPLETE, MARK_UNAVAILABLE, AWAIT_NETWORK, NETWORK_READY, } = Event;
|
package/dist/Repo.d.ts
CHANGED
|
@@ -1,15 +1,36 @@
|
|
|
1
|
-
import { DocCollection } from "./DocCollection.js";
|
|
2
1
|
import { NetworkAdapter } from "./network/NetworkAdapter.js";
|
|
3
2
|
import { NetworkSubsystem } from "./network/NetworkSubsystem.js";
|
|
4
3
|
import { StorageAdapter } from "./storage/StorageAdapter.js";
|
|
5
4
|
import { StorageSubsystem } from "./storage/StorageSubsystem.js";
|
|
6
|
-
import { DocumentId, PeerId } from "./types.js";
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import { type AutomergeUrl, DocumentId, PeerId } from "./types.js";
|
|
6
|
+
import { DocHandle } from "./DocHandle.js";
|
|
7
|
+
import { EventEmitter } from "eventemitter3";
|
|
8
|
+
/** A Repo is a collection of documents with networking, syncing, and storage capabilities. */
|
|
9
|
+
export declare class Repo extends EventEmitter<DocCollectionEvents> {
|
|
9
10
|
#private;
|
|
10
11
|
networkSubsystem: NetworkSubsystem;
|
|
11
12
|
storageSubsystem?: StorageSubsystem;
|
|
13
|
+
/** By default, we share generously with all peers. */
|
|
14
|
+
sharePolicy: SharePolicy;
|
|
12
15
|
constructor({ storage, network, peerId, sharePolicy }: RepoConfig);
|
|
16
|
+
/** Returns all the handles we have cached. */
|
|
17
|
+
get handles(): Record<DocumentId, DocHandle<any>>;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new document and returns a handle to it. The initial value of the document is
|
|
20
|
+
* an empty object `{}`. Its documentId is generated by the system. we emit a `document` event
|
|
21
|
+
* to advertise interest in the document.
|
|
22
|
+
*/
|
|
23
|
+
create<T>(): DocHandle<T>;
|
|
24
|
+
/**
|
|
25
|
+
* Retrieves a document by id. It gets data from the local system, but also emits a `document`
|
|
26
|
+
* event to advertise interest in the document.
|
|
27
|
+
*/
|
|
28
|
+
find<T>(
|
|
29
|
+
/** The documentId of the handle to retrieve */
|
|
30
|
+
automergeUrl: AutomergeUrl): DocHandle<T>;
|
|
31
|
+
delete(
|
|
32
|
+
/** The documentId of the handle to delete */
|
|
33
|
+
id: DocumentId | AutomergeUrl): void;
|
|
13
34
|
}
|
|
14
35
|
export interface RepoConfig {
|
|
15
36
|
/** Our unique identifier */
|
|
@@ -25,4 +46,17 @@ export interface RepoConfig {
|
|
|
25
46
|
sharePolicy?: SharePolicy;
|
|
26
47
|
}
|
|
27
48
|
export type SharePolicy = (peerId: PeerId, documentId?: DocumentId) => Promise<boolean>;
|
|
49
|
+
interface DocCollectionEvents {
|
|
50
|
+
document: (arg: DocumentPayload) => void;
|
|
51
|
+
"delete-document": (arg: DeleteDocumentPayload) => void;
|
|
52
|
+
"unavailable-document": (arg: DeleteDocumentPayload) => void;
|
|
53
|
+
}
|
|
54
|
+
interface DocumentPayload {
|
|
55
|
+
handle: DocHandle<any>;
|
|
56
|
+
isNew: boolean;
|
|
57
|
+
}
|
|
58
|
+
interface DeleteDocumentPayload {
|
|
59
|
+
documentId: DocumentId;
|
|
60
|
+
}
|
|
61
|
+
export {};
|
|
28
62
|
//# sourceMappingURL=Repo.d.ts.map
|
package/dist/Repo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAEhE,OAAO,EAAE,KAAK,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAIlE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAE5C,8FAA8F;AAC9F,qBAAa,IAAK,SAAQ,YAAY,CAAC,mBAAmB,CAAC;;IAGzD,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IAGnC,sDAAsD;IACtD,WAAW,EAAE,WAAW,CAAmB;gBAE/B,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,UAAU;IAoHjE,8CAA8C;IAC9C,IAAI,OAAO,uCAEV;IAED;;;;OAIG;IACH,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;IA0BzB;;;OAGG;IACH,IAAI,CAAC,CAAC;IACJ,+CAA+C;IAC/C,YAAY,EAAE,YAAY,GACzB,SAAS,CAAC,CAAC,CAAC;IAwBf,MAAM;IACJ,6CAA6C;IAC7C,EAAE,EAAE,UAAU,GAAG,YAAY;CAchC;AAED,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,gDAAgD;IAChD,OAAO,CAAC,EAAE,cAAc,CAAA;IAExB,oDAAoD;IACpD,OAAO,EAAE,cAAc,EAAE,CAAA;IAEzB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED,MAAM,MAAM,WAAW,GAAG,CACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,UAAU,KACpB,OAAO,CAAC,OAAO,CAAC,CAAA;AAGrB,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;IACxC,iBAAiB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACvD,sBAAsB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;CAC7D;AAED,UAAU,eAAe;IACvB,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf;AAED,UAAU,qBAAqB;IAC7B,UAAU,EAAE,UAAU,CAAA;CACvB"}
|
package/dist/Repo.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import debug from "debug";
|
|
2
|
-
import { DocCollection } from "./DocCollection.js";
|
|
3
2
|
import { NetworkSubsystem } from "./network/NetworkSubsystem.js";
|
|
4
3
|
import { StorageSubsystem } from "./storage/StorageSubsystem.js";
|
|
5
4
|
import { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js";
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
import { parseAutomergeUrl, generateAutomergeUrl, isValidAutomergeUrl } from "./DocUrl.js";
|
|
6
|
+
import { DocHandle } from "./DocHandle.js";
|
|
7
|
+
import { EventEmitter } from "eventemitter3";
|
|
8
|
+
/** A Repo is a collection of documents with networking, syncing, and storage capabilities. */
|
|
9
|
+
export class Repo extends EventEmitter {
|
|
8
10
|
#log;
|
|
9
11
|
networkSubsystem;
|
|
10
12
|
storageSubsystem;
|
|
13
|
+
#handleCache = {};
|
|
14
|
+
/** By default, we share generously with all peers. */
|
|
15
|
+
sharePolicy = async () => true;
|
|
11
16
|
constructor({ storage, network, peerId, sharePolicy }) {
|
|
12
17
|
super();
|
|
13
18
|
this.#log = debug(`automerge-repo:repo`);
|
|
@@ -92,4 +97,91 @@ export class Repo extends DocCollection {
|
|
|
92
97
|
await synchronizer.receiveMessage(msg);
|
|
93
98
|
});
|
|
94
99
|
}
|
|
100
|
+
/** Returns an existing handle if we have it; creates one otherwise. */
|
|
101
|
+
#getHandle(
|
|
102
|
+
/** The documentId of the handle to look up or create */
|
|
103
|
+
documentId,
|
|
104
|
+
/** If we know we're creating a new document, specify this so we can have access to it immediately */
|
|
105
|
+
isNew) {
|
|
106
|
+
// If we have the handle cached, return it
|
|
107
|
+
if (this.#handleCache[documentId])
|
|
108
|
+
return this.#handleCache[documentId];
|
|
109
|
+
// If not, create a new handle, cache it, and return it
|
|
110
|
+
if (!documentId)
|
|
111
|
+
throw new Error(`Invalid documentId ${documentId}`);
|
|
112
|
+
const handle = new DocHandle(documentId, { isNew });
|
|
113
|
+
this.#handleCache[documentId] = handle;
|
|
114
|
+
return handle;
|
|
115
|
+
}
|
|
116
|
+
/** Returns all the handles we have cached. */
|
|
117
|
+
get handles() {
|
|
118
|
+
return this.#handleCache;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Creates a new document and returns a handle to it. The initial value of the document is
|
|
122
|
+
* an empty object `{}`. Its documentId is generated by the system. we emit a `document` event
|
|
123
|
+
* to advertise interest in the document.
|
|
124
|
+
*/
|
|
125
|
+
create() {
|
|
126
|
+
// TODO:
|
|
127
|
+
// either
|
|
128
|
+
// - pass an initial value and do something like this to ensure that you get a valid initial value
|
|
129
|
+
// const myInitialValue = {
|
|
130
|
+
// tasks: [],
|
|
131
|
+
// filter: "all",
|
|
132
|
+
//
|
|
133
|
+
// const guaranteeInitialValue = (doc: any) => {
|
|
134
|
+
// if (!doc.tasks) doc.tasks = []
|
|
135
|
+
// if (!doc.filter) doc.filter = "all"
|
|
136
|
+
// return { ...myInitialValue, ...doc }
|
|
137
|
+
// }
|
|
138
|
+
// or
|
|
139
|
+
// - pass a "reify" function that takes a `<any>` and returns `<T>`
|
|
140
|
+
// Generate a new UUID and store it in the buffer
|
|
141
|
+
const { documentId } = parseAutomergeUrl(generateAutomergeUrl());
|
|
142
|
+
const handle = this.#getHandle(documentId, true);
|
|
143
|
+
this.emit("document", { handle, isNew: true });
|
|
144
|
+
return handle;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Retrieves a document by id. It gets data from the local system, but also emits a `document`
|
|
148
|
+
* event to advertise interest in the document.
|
|
149
|
+
*/
|
|
150
|
+
find(
|
|
151
|
+
/** The documentId of the handle to retrieve */
|
|
152
|
+
automergeUrl) {
|
|
153
|
+
if (!isValidAutomergeUrl(automergeUrl)) {
|
|
154
|
+
throw new Error(`Invalid AutomergeUrl: '${automergeUrl}'`);
|
|
155
|
+
}
|
|
156
|
+
const { documentId } = parseAutomergeUrl(automergeUrl);
|
|
157
|
+
// If we have the handle cached, return it
|
|
158
|
+
if (this.#handleCache[documentId]) {
|
|
159
|
+
if (this.#handleCache[documentId].isUnavailable()) {
|
|
160
|
+
// this ensures that the event fires after the handle has been returned
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
this.#handleCache[documentId].emit("unavailable", {
|
|
163
|
+
handle: this.#handleCache[documentId],
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return this.#handleCache[documentId];
|
|
168
|
+
}
|
|
169
|
+
const handle = this.#getHandle(documentId, false);
|
|
170
|
+
this.emit("document", { handle, isNew: false });
|
|
171
|
+
return handle;
|
|
172
|
+
}
|
|
173
|
+
delete(
|
|
174
|
+
/** The documentId of the handle to delete */
|
|
175
|
+
id) {
|
|
176
|
+
if (isValidAutomergeUrl(id)) {
|
|
177
|
+
;
|
|
178
|
+
({ documentId: id } = parseAutomergeUrl(id));
|
|
179
|
+
}
|
|
180
|
+
const handle = this.#getHandle(id, false);
|
|
181
|
+
handle.delete();
|
|
182
|
+
delete this.#handleCache[id];
|
|
183
|
+
this.emit("delete-document", {
|
|
184
|
+
documentId: id,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
95
187
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACvD,YAAY,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,YAAY,EACV,WAAW,EACX,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,6BAA6B,CAAA;AAMpC,YAAY,EACV,OAAO,EACP,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,GACZ,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,IAAI,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAA;AACjF,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,IAAI,oBAAoB,GAC9C,MAAM,aAAa,CAAA;AACpB,cAAc,YAAY,CAAA;AAE1B,OAAO,KAAK,IAAI,MAAM,mBAAmB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -3,10 +3,9 @@ import { PeerId } from "../types.js";
|
|
|
3
3
|
import { Message } from "./messages.js";
|
|
4
4
|
export declare abstract class NetworkAdapter extends EventEmitter<NetworkAdapterEvents> {
|
|
5
5
|
peerId?: PeerId;
|
|
6
|
-
abstract connect(
|
|
6
|
+
abstract connect(peerId: PeerId): void;
|
|
7
7
|
abstract send(message: Message): void;
|
|
8
|
-
abstract
|
|
9
|
-
abstract leave(): void;
|
|
8
|
+
abstract disconnect(): void;
|
|
10
9
|
}
|
|
11
10
|
export interface NetworkAdapterEvents {
|
|
12
11
|
ready: (payload: OpenPayload) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkAdapter.d.ts","sourceRoot":"","sources":["../../src/network/NetworkAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,8BAAsB,cAAe,SAAQ,YAAY,CAAC,oBAAoB,CAAC;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,QAAQ,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"NetworkAdapter.d.ts","sourceRoot":"","sources":["../../src/network/NetworkAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAEvC,8BAAsB,cAAe,SAAQ,YAAY,CAAC,oBAAoB,CAAC;IAC7E,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAEtC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAErC,QAAQ,CAAC,UAAU,IAAI,IAAI;CAC5B;AAID,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAA;IACrC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,gBAAgB,EAAE,CAAC,OAAO,EAAE,oBAAoB,KAAK,IAAI,CAAA;IACzD,mBAAmB,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAA;IAC/D,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;CACpC;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,cAAc,CAAA;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,CAAA;CACf"}
|
|
@@ -8,8 +8,6 @@ export declare class NetworkSubsystem extends EventEmitter<NetworkSubsystemEvent
|
|
|
8
8
|
constructor(adapters: NetworkAdapter[], peerId?: PeerId);
|
|
9
9
|
addNetworkAdapter(networkAdapter: NetworkAdapter): void;
|
|
10
10
|
send(message: MessageContents): void;
|
|
11
|
-
join(): void;
|
|
12
|
-
leave(): void;
|
|
13
11
|
isReady: () => boolean;
|
|
14
12
|
whenReady: () => Promise<void>;
|
|
15
13
|
}
|
|
@@ -17,7 +15,7 @@ export interface NetworkSubsystemEvents {
|
|
|
17
15
|
peer: (payload: PeerPayload) => void;
|
|
18
16
|
"peer-disconnected": (payload: PeerDisconnectedPayload) => void;
|
|
19
17
|
message: (payload: Message) => void;
|
|
20
|
-
|
|
18
|
+
ready: () => void;
|
|
21
19
|
}
|
|
22
20
|
export interface PeerPayload {
|
|
23
21
|
peerId: PeerId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkSubsystem.d.ts","sourceRoot":"","sources":["../../src/network/NetworkSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAE7E,OAAO,EAIL,OAAO,EACP,eAAe,EAChB,MAAM,eAAe,CAAA;AAUtB,qBAAa,gBAAiB,SAAQ,YAAY,CAAC,sBAAsB,CAAC;;
|
|
1
|
+
{"version":3,"file":"NetworkSubsystem.d.ts","sourceRoot":"","sources":["../../src/network/NetworkSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,OAAO,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAE7E,OAAO,EAIL,OAAO,EACP,eAAe,EAChB,MAAM,eAAe,CAAA;AAUtB,qBAAa,gBAAiB,SAAQ,YAAY,CAAC,sBAAsB,CAAC;;IAUzB,MAAM;gBAAzC,QAAQ,EAAE,cAAc,EAAE,EAAS,MAAM,SAAiB;IAMtE,iBAAiB,CAAC,cAAc,EAAE,cAAc;IAsEhD,IAAI,CAAC,OAAO,EAAE,eAAe;IA2B7B,OAAO,gBAEN;IAED,SAAS,sBAUR;CACF;AAQD,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAA;IACpC,mBAAmB,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,IAAI,CAAA;IAC/D,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IACnC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf"}
|
|
@@ -66,7 +66,6 @@ export class NetworkSubsystem extends EventEmitter {
|
|
|
66
66
|
});
|
|
67
67
|
});
|
|
68
68
|
networkAdapter.connect(this.peerId);
|
|
69
|
-
networkAdapter.join();
|
|
70
69
|
}
|
|
71
70
|
send(message) {
|
|
72
71
|
const peer = this.#adaptersByPeer[message.targetId];
|
|
@@ -93,14 +92,6 @@ export class NetworkSubsystem extends EventEmitter {
|
|
|
93
92
|
peer.send(outbound);
|
|
94
93
|
}
|
|
95
94
|
}
|
|
96
|
-
join() {
|
|
97
|
-
this.#log(`Joining network`);
|
|
98
|
-
this.#adapters.forEach(a => a.join());
|
|
99
|
-
}
|
|
100
|
-
leave() {
|
|
101
|
-
this.#log(`Leaving network`);
|
|
102
|
-
this.#adapters.forEach(a => a.leave());
|
|
103
|
-
}
|
|
104
95
|
isReady = () => {
|
|
105
96
|
return this.#readyAdapterCount === this.#adapters.length;
|
|
106
97
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StorageSubsystem.d.ts","sourceRoot":"","sources":["../../src/storage/StorageSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,2BAA2B,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAc,MAAM,qBAAqB,CAAA;AAEhE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAa7C,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,CAAA;AAelD,qBAAa,gBAAgB;;
|
|
1
|
+
{"version":3,"file":"StorageSubsystem.d.ts","sourceRoot":"","sources":["../../src/storage/StorageSubsystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,2BAA2B,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAc,MAAM,qBAAqB,CAAA;AAEhE,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAA;AAa7C,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,aAAa,CAAA;AAelD,qBAAa,gBAAgB;;gBAQf,cAAc,EAAE,cAAc;IAuDpC,OAAO,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC;IA0B/D,OAAO,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAanE,MAAM,CAAC,UAAU,EAAE,UAAU;CAmCpC"}
|
|
@@ -19,6 +19,7 @@ export class StorageSubsystem {
|
|
|
19
19
|
#chunkInfos = new Map();
|
|
20
20
|
#storedHeads = new Map();
|
|
21
21
|
#log = debug(`automerge-repo:storage-subsystem`);
|
|
22
|
+
#snapshotting = false;
|
|
22
23
|
constructor(storageAdapter) {
|
|
23
24
|
this.#storageAdapter = storageAdapter;
|
|
24
25
|
}
|
|
@@ -43,6 +44,7 @@ export class StorageSubsystem {
|
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
async #saveTotal(documentId, doc, sourceChunks) {
|
|
47
|
+
this.#snapshotting = true;
|
|
46
48
|
const binary = A.save(doc);
|
|
47
49
|
const snapshotHash = headsHash(A.getHeads(doc));
|
|
48
50
|
const key = [documentId, "snapshot", snapshotHash];
|
|
@@ -56,6 +58,7 @@ export class StorageSubsystem {
|
|
|
56
58
|
const newChunkInfos = this.#chunkInfos.get(documentId)?.filter(c => !oldKeys.has(c.key)) ?? [];
|
|
57
59
|
newChunkInfos.push({ key, type: "snapshot", size: binary.length });
|
|
58
60
|
this.#chunkInfos.set(documentId, newChunkInfos);
|
|
61
|
+
this.#snapshotting = false;
|
|
59
62
|
}
|
|
60
63
|
async loadDoc(documentId) {
|
|
61
64
|
const loaded = await this.#storageAdapter.loadRange([documentId]);
|
|
@@ -96,7 +99,7 @@ export class StorageSubsystem {
|
|
|
96
99
|
this.#storedHeads.set(documentId, A.getHeads(doc));
|
|
97
100
|
}
|
|
98
101
|
async remove(documentId) {
|
|
99
|
-
this.#storageAdapter.
|
|
102
|
+
this.#storageAdapter.removeRange([documentId, "snapshot"]);
|
|
100
103
|
this.#storageAdapter.removeRange([documentId, "incremental"]);
|
|
101
104
|
}
|
|
102
105
|
#shouldSave(documentId, doc) {
|
|
@@ -111,6 +114,9 @@ export class StorageSubsystem {
|
|
|
111
114
|
return true;
|
|
112
115
|
}
|
|
113
116
|
#shouldCompact(sourceChunks) {
|
|
117
|
+
if (this.#snapshotting) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
114
120
|
// compact if the incremental size is greater than the snapshot size
|
|
115
121
|
let snapshotSize = 0;
|
|
116
122
|
let incrementalSize = 0;
|
|
@@ -122,7 +128,7 @@ export class StorageSubsystem {
|
|
|
122
128
|
incrementalSize += chunk.size;
|
|
123
129
|
}
|
|
124
130
|
}
|
|
125
|
-
return incrementalSize
|
|
131
|
+
return incrementalSize >= snapshotSize;
|
|
126
132
|
}
|
|
127
133
|
}
|
|
128
134
|
function chunkTypeFromKey(key) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Repo } from "../Repo.js";
|
|
2
2
|
import { PeerId, DocumentId } from "../types.js";
|
|
3
3
|
import { Synchronizer } from "./Synchronizer.js";
|
|
4
4
|
import { SynchronizerMessage } from "../network/messages.js";
|
|
@@ -6,7 +6,7 @@ import { SynchronizerMessage } from "../network/messages.js";
|
|
|
6
6
|
export declare class CollectionSynchronizer extends Synchronizer {
|
|
7
7
|
#private;
|
|
8
8
|
private repo;
|
|
9
|
-
constructor(repo:
|
|
9
|
+
constructor(repo: Repo);
|
|
10
10
|
/**
|
|
11
11
|
* When we receive a sync message for a document we haven't got in memory, we
|
|
12
12
|
* register it with the repo and start synchronizing
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollectionSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/CollectionSynchronizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"CollectionSynchronizer.d.ts","sourceRoot":"","sources":["../../src/synchronizer/CollectionSynchronizer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAOjC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EAGL,mBAAmB,EAEpB,MAAM,wBAAwB,CAAA;AAG/B,4FAA4F;AAC5F,qBAAa,sBAAuB,SAAQ,YAAY;;IAU1C,OAAO,CAAC,IAAI;gBAAJ,IAAI,EAAE,IAAI;IAiC9B;;;OAGG;IACG,cAAc,CAAC,OAAO,EAAE,mBAAmB;IAyBjD;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,UAAU;IAYlC,cAAc,CAAC,UAAU,EAAE,UAAU;IAIrC,2DAA2D;IAC3D,OAAO,CAAC,MAAM,EAAE,MAAM;IAgBtB,uDAAuD;IACvD,UAAU,CAAC,MAAM,EAAE,MAAM;CAQ1B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automerge/automerge-repo",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "A repository object to manage a collection of automerge documents",
|
|
5
5
|
"repository": "https://github.com/automerge/automerge-repo",
|
|
6
6
|
"author": "Peter van Hardenberg <pvh@pvh.ca>",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"typescript": "^5.1.6"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@automerge/automerge": "^2.1.0
|
|
34
|
+
"@automerge/automerge": "^2.1.0"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"bs58check": "^3.0.1",
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"publishConfig": {
|
|
66
66
|
"access": "public"
|
|
67
67
|
},
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "89c6ee2714d43dbebd69c7a62f148d17869608d6"
|
|
69
69
|
}
|
package/src/DocHandle.ts
CHANGED
|
@@ -101,7 +101,7 @@ export class DocHandle<T> //
|
|
|
101
101
|
awaitingNetwork: {
|
|
102
102
|
on: {
|
|
103
103
|
NETWORK_READY: { target: REQUESTING },
|
|
104
|
-
}
|
|
104
|
+
},
|
|
105
105
|
},
|
|
106
106
|
requesting: {
|
|
107
107
|
on: {
|
|
@@ -326,23 +326,31 @@ export class DocHandle<T> //
|
|
|
326
326
|
})
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
+
/** Make a change as if the document were at `heads`
|
|
330
|
+
*
|
|
331
|
+
* @returns A set of heads representing the concurrent change that was made.
|
|
332
|
+
*/
|
|
329
333
|
changeAt(
|
|
330
334
|
heads: A.Heads,
|
|
331
335
|
callback: A.ChangeFn<T>,
|
|
332
336
|
options: A.ChangeOptions<T> = {}
|
|
333
|
-
) {
|
|
337
|
+
): string[] | undefined {
|
|
334
338
|
if (!this.isReady()) {
|
|
335
339
|
throw new Error(
|
|
336
340
|
`DocHandle#${this.documentId} is not ready. Check \`handle.isReady()\` before accessing the document.`
|
|
337
341
|
)
|
|
338
342
|
}
|
|
343
|
+
let resultHeads: string[] | undefined = undefined
|
|
339
344
|
this.#machine.send(UPDATE, {
|
|
340
345
|
payload: {
|
|
341
346
|
callback: (doc: A.Doc<T>) => {
|
|
342
|
-
|
|
347
|
+
const result = A.changeAt(doc, heads, options, callback)
|
|
348
|
+
resultHeads = result.newHeads
|
|
349
|
+
return result.newDoc
|
|
343
350
|
},
|
|
344
351
|
},
|
|
345
352
|
})
|
|
353
|
+
return resultHeads
|
|
346
354
|
}
|
|
347
355
|
|
|
348
356
|
unavailable() {
|
|
@@ -501,7 +509,7 @@ type DocHandleEvent<T> =
|
|
|
501
509
|
| TimeoutEvent
|
|
502
510
|
| DeleteEvent
|
|
503
511
|
| MarkUnavailableEvent
|
|
504
|
-
| AwaitNetworkEvent
|
|
512
|
+
| AwaitNetworkEvent
|
|
505
513
|
| NetworkReadyEvent
|
|
506
514
|
|
|
507
515
|
type DocHandleXstateMachine<T> = Interpreter<
|
|
@@ -541,5 +549,5 @@ const {
|
|
|
541
549
|
REQUEST_COMPLETE,
|
|
542
550
|
MARK_UNAVAILABLE,
|
|
543
551
|
AWAIT_NETWORK,
|
|
544
|
-
NETWORK_READY
|
|
552
|
+
NETWORK_READY,
|
|
545
553
|
} = Event
|