@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.
Files changed (37) hide show
  1. package/.eslintrc +2 -2
  2. package/dist/DocHandle.d.ts +5 -1
  3. package/dist/DocHandle.d.ts.map +1 -1
  4. package/dist/DocHandle.js +11 -3
  5. package/dist/Repo.d.ts +38 -4
  6. package/dist/Repo.d.ts.map +1 -1
  7. package/dist/Repo.js +95 -3
  8. package/dist/index.d.ts +0 -1
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +0 -1
  11. package/dist/network/NetworkAdapter.d.ts +2 -3
  12. package/dist/network/NetworkAdapter.d.ts.map +1 -1
  13. package/dist/network/NetworkSubsystem.d.ts +1 -3
  14. package/dist/network/NetworkSubsystem.d.ts.map +1 -1
  15. package/dist/network/NetworkSubsystem.js +0 -9
  16. package/dist/storage/StorageSubsystem.d.ts.map +1 -1
  17. package/dist/storage/StorageSubsystem.js +8 -2
  18. package/dist/synchronizer/CollectionSynchronizer.d.ts +2 -2
  19. package/dist/synchronizer/CollectionSynchronizer.d.ts.map +1 -1
  20. package/package.json +3 -3
  21. package/src/DocHandle.ts +13 -5
  22. package/src/Repo.ts +130 -4
  23. package/src/index.ts +0 -1
  24. package/src/network/NetworkAdapter.ts +2 -4
  25. package/src/network/NetworkSubsystem.ts +14 -23
  26. package/src/storage/StorageSubsystem.ts +9 -2
  27. package/src/synchronizer/CollectionSynchronizer.ts +2 -2
  28. package/test/CollectionSynchronizer.test.ts +12 -11
  29. package/test/DocHandle.test.ts +2 -1
  30. package/test/Repo.test.ts +26 -5
  31. package/test/helpers/DummyNetworkAdapter.ts +2 -3
  32. package/test/helpers/generate-large-object.ts +13 -0
  33. package/dist/DocCollection.d.ts +0 -46
  34. package/dist/DocCollection.d.ts.map +0 -1
  35. package/dist/DocCollection.js +0 -102
  36. package/src/DocCollection.ts +0 -144
  37. 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
  }
@@ -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
- changeAt(heads: A.Heads, callback: A.ChangeFn<T>, options?: A.ChangeOptions<T>): void;
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;
@@ -1 +1 @@
1
- {"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"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"}
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
- return A.changeAt(doc, heads, options, callback).newDoc;
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
- /** A Repo is a DocCollection with networking, syncing, and storage capabilities. */
8
- export declare class Repo extends DocCollection {
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
@@ -1 +1 @@
1
- {"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,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,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAE/C,oFAAoF;AACpF,qBAAa,IAAK,SAAQ,aAAa;;IAGrC,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;gBAEvB,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,UAAU;CAiGlE;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"}
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
- /** A Repo is a DocCollection with networking, syncing, and storage capabilities. */
7
- export class Repo extends DocCollection {
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
@@ -1,4 +1,3 @@
1
- export { DocCollection } from "./DocCollection.js";
2
1
  export { DocHandle, HandleState } from "./DocHandle.js";
3
2
  export type { DocHandleChangePayload } from "./DocHandle.js";
4
3
  export { NetworkAdapter } from "./network/NetworkAdapter.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,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"}
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
@@ -1,4 +1,3 @@
1
- export { DocCollection } from "./DocCollection.js";
2
1
  export { DocHandle, HandleState } from "./DocHandle.js";
3
2
  export { NetworkAdapter } from "./network/NetworkAdapter.js";
4
3
  export { NetworkSubsystem } from "./network/NetworkSubsystem.js";
@@ -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(url?: string): void;
6
+ abstract connect(peerId: PeerId): void;
7
7
  abstract send(message: Message): void;
8
- abstract join(): void;
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,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAEpC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAErC,QAAQ,CAAC,IAAI,IAAI,IAAI;IAErB,QAAQ,CAAC,KAAK,IAAI,IAAI;CACvB;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"}
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
- "ready": () => void;
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;;IAY/D,MAAM;gBADb,QAAQ,EAAE,cAAc,EAAE,EACnB,MAAM,SAAiB;IAOhC,iBAAiB,CAAC,cAAc,EAAE,cAAc;IAkEhD,IAAI,CAAC,OAAO,EAAE,eAAe;IA2B7B,IAAI;IAKJ,KAAK;IAKL,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,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAA;CACf"}
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;;gBAMf,cAAc,EAAE,cAAc;IAqDpC,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;CAgCpC"}
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.remove([documentId, "snapshot"]);
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 > snapshotSize;
131
+ return incrementalSize >= snapshotSize;
126
132
  }
127
133
  }
128
134
  function chunkTypeFromKey(key) {
@@ -1,4 +1,4 @@
1
- import { DocCollection } from "../DocCollection.js";
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: DocCollection);
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,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAOnD,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,aAAa;IAiCvC;;;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"}
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-alpha.4",
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-alpha.12"
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": "fbf71f0c3aaa2786a4e279f336f01d665f53ce5b"
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
- return A.changeAt(doc, heads, options, callback).newDoc
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