@automerge/automerge-repo 2.0.0-alpha.14 → 2.0.0-alpha.16

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 (35) hide show
  1. package/dist/AutomergeUrl.d.ts +19 -4
  2. package/dist/AutomergeUrl.d.ts.map +1 -1
  3. package/dist/AutomergeUrl.js +71 -24
  4. package/dist/DocHandle.d.ts +21 -17
  5. package/dist/DocHandle.d.ts.map +1 -1
  6. package/dist/DocHandle.js +83 -26
  7. package/dist/RemoteHeadsSubscriptions.d.ts +4 -4
  8. package/dist/RemoteHeadsSubscriptions.d.ts.map +1 -1
  9. package/dist/RemoteHeadsSubscriptions.js +4 -1
  10. package/dist/Repo.d.ts.map +1 -1
  11. package/dist/Repo.js +17 -12
  12. package/dist/helpers/bufferFromHex.d.ts +3 -0
  13. package/dist/helpers/bufferFromHex.d.ts.map +1 -0
  14. package/dist/helpers/bufferFromHex.js +13 -0
  15. package/dist/helpers/headsAreSame.d.ts +2 -2
  16. package/dist/helpers/headsAreSame.d.ts.map +1 -1
  17. package/dist/helpers/mergeArrays.d.ts +1 -1
  18. package/dist/helpers/mergeArrays.d.ts.map +1 -1
  19. package/dist/helpers/tests/storage-adapter-tests.d.ts.map +1 -1
  20. package/dist/helpers/tests/storage-adapter-tests.js +6 -9
  21. package/dist/storage/StorageSubsystem.d.ts.map +1 -1
  22. package/dist/storage/StorageSubsystem.js +2 -1
  23. package/package.json +2 -2
  24. package/src/AutomergeUrl.ts +103 -26
  25. package/src/DocHandle.ts +130 -37
  26. package/src/RemoteHeadsSubscriptions.ts +11 -8
  27. package/src/Repo.ts +22 -11
  28. package/src/helpers/bufferFromHex.ts +14 -0
  29. package/src/helpers/headsAreSame.ts +2 -2
  30. package/src/helpers/tests/storage-adapter-tests.ts +13 -24
  31. package/src/storage/StorageSubsystem.ts +3 -1
  32. package/test/AutomergeUrl.test.ts +130 -0
  33. package/test/DocHandle.test.ts +70 -4
  34. package/test/DocSynchronizer.test.ts +10 -3
  35. package/test/Repo.test.ts +117 -3
@@ -1,17 +1,29 @@
1
1
  import type { LegacyDocumentId, AutomergeUrl, BinaryDocumentId, DocumentId, AnyDocumentId } from "./types.js";
2
+ import type { Heads as AutomergeHeads } from "@automerge/automerge/slim";
2
3
  export declare const urlPrefix = "automerge:";
3
- /** Given an Automerge URL, returns the DocumentId in both base58check-encoded form and binary form */
4
- export declare const parseAutomergeUrl: (url: AutomergeUrl) => {
4
+ export type UrlHeads = string[] & {
5
+ __automergeUrlHeadsBrand: unknown;
6
+ };
7
+ interface ParsedAutomergeUrl {
5
8
  /** unencoded DocumentId */
6
9
  binaryDocumentId: BinaryDocumentId;
7
- /** encoded DocumentId */
10
+ /** bs58 encoded DocumentId */
8
11
  documentId: DocumentId;
9
- };
12
+ /** Optional array of heads, if specified in URL */
13
+ heads?: UrlHeads;
14
+ /** Optional hex array of heads, in Automerge core format */
15
+ hexHeads?: string[];
16
+ }
17
+ /** Given an Automerge URL, returns the DocumentId in both base58check-encoded form and binary form */
18
+ export declare const parseAutomergeUrl: (url: AutomergeUrl) => ParsedAutomergeUrl;
10
19
  /**
11
20
  * Given a documentId in either binary or base58check-encoded form, returns an Automerge URL.
12
21
  * Throws on invalid input.
13
22
  */
14
23
  export declare const stringifyAutomergeUrl: (arg: UrlOptions | DocumentId | BinaryDocumentId) => AutomergeUrl;
24
+ /** Helper to extract just the heads from a URL if they exist */
25
+ export declare const getHeadsFromUrl: (url: AutomergeUrl) => string[] | undefined;
26
+ export declare const anyDocumentIdToAutomergeUrl: (id: AnyDocumentId) => AutomergeUrl | undefined;
15
27
  /**
16
28
  * Given a string, returns true if it is a valid Automerge URL. This function also acts as a type
17
29
  * discriminator in Typescript.
@@ -25,6 +37,8 @@ export declare const isValidUuid: (str: unknown) => str is LegacyDocumentId;
25
37
  export declare const generateAutomergeUrl: () => AutomergeUrl;
26
38
  export declare const documentIdToBinary: (docId: DocumentId) => BinaryDocumentId | undefined;
27
39
  export declare const binaryToDocumentId: (docId: BinaryDocumentId) => DocumentId;
40
+ export declare const encodeHeads: (heads: AutomergeHeads) => UrlHeads;
41
+ export declare const decodeHeads: (heads: UrlHeads) => AutomergeHeads;
28
42
  export declare const parseLegacyUUID: (str: string) => AutomergeUrl | undefined;
29
43
  /**
30
44
  * Given any valid expression of a document ID, returns a DocumentId in base58check-encoded form.
@@ -40,6 +54,7 @@ export declare const parseLegacyUUID: (str: string) => AutomergeUrl | undefined;
40
54
  export declare const interpretAsDocumentId: (id: AnyDocumentId) => DocumentId;
41
55
  type UrlOptions = {
42
56
  documentId: DocumentId | BinaryDocumentId;
57
+ heads?: UrlHeads;
43
58
  };
44
59
  export {};
45
60
  //# sourceMappingURL=AutomergeUrl.d.ts.map
@@ -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,EACd,MAAM,YAAY,CAAA;AAInB,eAAO,MAAM,SAAS,eAAe,CAAA;AAErC,sGAAsG;AACtG,eAAO,MAAM,iBAAiB,QAAS,YAAY;IAQ/C,2BAA2B;;IAE3B,yBAAyB;;CAG5B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAC3B,UAAU,GAAG,UAAU,GAAG,gBAAgB,KAmBL,YAC3C,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAAS,OAAO,KAAG,GAAG,IAAI,YAUzD,CAAA;AAED,eAAO,MAAM,iBAAiB,QAAS,OAAO,KAAG,GAAG,IAAI,UASvD,CAAA;AAED,eAAO,MAAM,WAAW,QAAS,OAAO,KAAG,GAAG,IAAI,gBACH,CAAA;AAE/C;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAO,YAGvC,CAAA;AAED,eAAO,MAAM,kBAAkB,UAAW,UAAU,KACjB,gBAAgB,GAAG,SAAS,CAAA;AAE/D,eAAO,MAAM,kBAAkB,UAAW,gBAAgB,KAC7B,UAAU,CAAA;AAEvC,eAAO,MAAM,eAAe,QAAS,MAAM,6BAI1C,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,OAAQ,aAAa,eAqBtD,CAAA;AAID,KAAK,UAAU,GAAG;IAChB,UAAU,EAAE,UAAU,GAAG,gBAAgB,CAAA;CAC1C,CAAA"}
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,EACd,MAAM,YAAY,CAAA;AASnB,OAAO,KAAK,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAExE,eAAO,MAAM,SAAS,eAAe,CAAA;AAGrC,MAAM,MAAM,QAAQ,GAAG,MAAM,EAAE,GAAG;IAAE,wBAAwB,EAAE,OAAO,CAAA;CAAE,CAAA;AAEvE,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,QAAS,YAAY,KAAG,kBAsBrD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,QAC3B,UAAU,GAAG,UAAU,GAAG,gBAAgB,KAC9C,YAgCF,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,eAAe,QAAS,YAAY,KAAG,MAAM,EAAE,GAAG,SAG9D,CAAA;AAED,eAAO,MAAM,2BAA2B,OAAQ,aAAa,6BAO9C,CAAA;AAEf;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAAS,OAAO,KAAG,GAAG,IAAI,YAsBzD,CAAA;AAED,eAAO,MAAM,iBAAiB,QAAS,OAAO,KAAG,GAAG,IAAI,UASvD,CAAA;AAED,eAAO,MAAM,WAAW,QAAS,OAAO,KAAG,GAAG,IAAI,gBACH,CAAA;AAE/C;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAO,YAGvC,CAAA;AAED,eAAO,MAAM,kBAAkB,UAAW,UAAU,KACjB,gBAAgB,GAAG,SAAS,CAAA;AAE/D,eAAO,MAAM,kBAAkB,UAAW,gBAAgB,KAC7B,UAAU,CAAA;AAEvC,eAAO,MAAM,WAAW,UAAW,cAAc,KAAG,QACsB,CAAA;AAE1E,eAAO,MAAM,WAAW,UAAW,QAAQ,KAAG,cACgC,CAAA;AAE9E,eAAO,MAAM,eAAe,QAAS,MAAM,6BAI1C,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,OAAQ,aAAa,eAqBtD,CAAA;AAID,KAAK,UAAU,GAAG;IAChB,UAAU,EAAE,UAAU,GAAG,gBAAgB,CAAA;IACzC,KAAK,CAAC,EAAE,QAAQ,CAAA;CACjB,CAAA"}
@@ -1,53 +1,98 @@
1
1
  import * as Uuid from "uuid";
2
2
  import bs58check from "bs58check";
3
+ import { uint8ArrayFromHexString, uint8ArrayToHexString, } from "./helpers/bufferFromHex.js";
3
4
  export const urlPrefix = "automerge:";
4
5
  /** Given an Automerge URL, returns the DocumentId in both base58check-encoded form and binary form */
5
6
  export const parseAutomergeUrl = (url) => {
7
+ const [baseUrl, headsSection, ...rest] = url.split("#");
8
+ if (rest.length > 0) {
9
+ throw new Error("Invalid URL: contains multiple heads sections");
10
+ }
6
11
  const regex = new RegExp(`^${urlPrefix}(\\w+)$`);
7
- const [, docMatch] = url.match(regex) || [];
12
+ const [, docMatch] = baseUrl.match(regex) || [];
8
13
  const documentId = docMatch;
9
14
  const binaryDocumentId = documentIdToBinary(documentId);
10
15
  if (!binaryDocumentId)
11
16
  throw new Error("Invalid document URL: " + url);
12
- return {
13
- /** unencoded DocumentId */
14
- binaryDocumentId,
15
- /** encoded DocumentId */
16
- documentId,
17
- };
17
+ if (headsSection === undefined)
18
+ return { binaryDocumentId, documentId };
19
+ const heads = (headsSection === "" ? [] : headsSection.split("|"));
20
+ const hexHeads = heads.map(head => {
21
+ try {
22
+ return uint8ArrayToHexString(bs58check.decode(head));
23
+ }
24
+ catch (e) {
25
+ throw new Error(`Invalid head in URL: ${head}`);
26
+ }
27
+ });
28
+ return { binaryDocumentId, hexHeads, documentId, heads };
18
29
  };
19
30
  /**
20
31
  * Given a documentId in either binary or base58check-encoded form, returns an Automerge URL.
21
32
  * Throws on invalid input.
22
33
  */
23
34
  export const stringifyAutomergeUrl = (arg) => {
24
- const documentId = arg instanceof Uint8Array || typeof arg === "string"
25
- ? arg
26
- : "documentId" in arg
27
- ? arg.documentId
28
- : undefined;
35
+ if (arg instanceof Uint8Array || typeof arg === "string") {
36
+ return (urlPrefix +
37
+ (arg instanceof Uint8Array
38
+ ? binaryToDocumentId(arg)
39
+ : arg));
40
+ }
41
+ const { documentId, heads = undefined } = arg;
42
+ if (documentId === undefined)
43
+ throw new Error("Invalid documentId: " + documentId);
29
44
  const encodedDocumentId = documentId instanceof Uint8Array
30
45
  ? binaryToDocumentId(documentId)
31
- : typeof documentId === "string"
32
- ? documentId
33
- : undefined;
34
- if (encodedDocumentId === undefined)
35
- throw new Error("Invalid documentId: " + documentId);
36
- return (urlPrefix + encodedDocumentId);
46
+ : documentId;
47
+ let url = `${urlPrefix}${encodedDocumentId}`;
48
+ if (heads !== undefined) {
49
+ heads.forEach(head => {
50
+ try {
51
+ bs58check.decode(head);
52
+ }
53
+ catch (e) {
54
+ throw new Error(`Invalid head: ${head}`);
55
+ }
56
+ });
57
+ url += "#" + heads.join("|");
58
+ }
59
+ return url;
60
+ };
61
+ /** Helper to extract just the heads from a URL if they exist */
62
+ export const getHeadsFromUrl = (url) => {
63
+ const { heads } = parseAutomergeUrl(url);
64
+ return heads;
37
65
  };
66
+ export const anyDocumentIdToAutomergeUrl = (id) => isValidAutomergeUrl(id)
67
+ ? id
68
+ : isValidDocumentId(id)
69
+ ? stringifyAutomergeUrl({ documentId: id })
70
+ : isValidUuid(id)
71
+ ? parseLegacyUUID(id)
72
+ : undefined;
38
73
  /**
39
74
  * Given a string, returns true if it is a valid Automerge URL. This function also acts as a type
40
75
  * discriminator in Typescript.
41
76
  */
42
77
  export const isValidAutomergeUrl = (str) => {
43
- if (typeof str !== "string")
44
- return false;
45
- if (!str || !str.startsWith(urlPrefix))
78
+ if (typeof str !== "string" || !str || !str.startsWith(urlPrefix))
46
79
  return false;
47
- const automergeUrl = str;
48
80
  try {
49
- const { documentId } = parseAutomergeUrl(automergeUrl);
50
- return isValidDocumentId(documentId);
81
+ const { documentId, heads } = parseAutomergeUrl(str);
82
+ if (!isValidDocumentId(documentId))
83
+ return false;
84
+ if (heads &&
85
+ !heads.every(head => {
86
+ try {
87
+ bs58check.decode(head);
88
+ return true;
89
+ }
90
+ catch {
91
+ return false;
92
+ }
93
+ }))
94
+ return false;
95
+ return true;
51
96
  }
52
97
  catch {
53
98
  return false;
@@ -74,6 +119,8 @@ export const generateAutomergeUrl = () => {
74
119
  };
75
120
  export const documentIdToBinary = (docId) => bs58check.decodeUnsafe(docId);
76
121
  export const binaryToDocumentId = (docId) => bs58check.encode(docId);
122
+ export const encodeHeads = (heads) => heads.map(h => bs58check.encode(uint8ArrayFromHexString(h)));
123
+ export const decodeHeads = (heads) => heads.map(h => uint8ArrayToHexString(bs58check.decode(h)));
77
124
  export const parseLegacyUUID = (str) => {
78
125
  if (!Uuid.validate(str))
79
126
  return undefined;
@@ -1,5 +1,6 @@
1
1
  import * as A from "@automerge/automerge/slim/next";
2
2
  import { EventEmitter } from "eventemitter3";
3
+ import { UrlHeads } from "./AutomergeUrl.js";
3
4
  import type { AutomergeUrl, DocumentId, PeerId } from "./types.js";
4
5
  import { StorageId } from "./storage/types.js";
5
6
  /**
@@ -92,12 +93,10 @@ export declare class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
92
93
  * This precisely defines the state of a document.
93
94
  * @returns the current document's heads, or undefined if the document is not ready
94
95
  */
95
- heads(): A.Heads | undefined;
96
+ heads(): UrlHeads | undefined;
96
97
  begin(): void;
97
98
  /**
98
- * Creates a fixed "view" of an automerge document at the given point in time represented
99
- * by the `heads` passed in. The return value is the same type as docSync() and will return
100
- * undefined if the object hasn't finished loading.
99
+ * Returns an array of all past "heads" for the document in topological order.
101
100
  *
102
101
  * @remarks
103
102
  * A point-in-time in an automerge document is an *array* of heads since there may be
@@ -106,11 +105,11 @@ export declare class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
106
105
  * history views would be quite large under concurrency (every thing in each branch against each other).
107
106
  * There might be a clever way to think about this, but we haven't found it yet, so for now at least
108
107
  * we present a single traversable view which excludes concurrency.
109
- * @returns The individual heads for every change in the document.
108
+ * @returns UrlHeads[] - The individual heads for every change in the document. Each item is a tagged string[1].
110
109
  */
111
- history(): A.Heads[] | undefined;
110
+ history(): UrlHeads[] | undefined;
112
111
  /**
113
- * Creates a fixed "view" of an automerge document at the given point in time represented
112
+ * Creates a new DocHandle with a fixed "view" at the given point in time represented
114
113
  * by the `heads` passed in. The return value is the same type as docSync() and will return
115
114
  * undefined if the object hasn't finished loading.
116
115
  *
@@ -119,20 +118,24 @@ export declare class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
119
118
  * of Automerge doesn't check types at runtime, so if you go back to an old set of heads
120
119
  * that doesn't match the heads here, Typescript will not save you.
121
120
  *
122
- * @returns An Automerge.Doc<T> at the point in time.
121
+ * @argument heads - The heads to view the document at. See history().
122
+ * @returns DocHandle<T> at the time of `heads`
123
123
  */
124
- view(heads: A.Heads): A.Doc<T> | undefined;
124
+ view(heads: UrlHeads): DocHandle<T>;
125
125
  /**
126
126
  * Returns a set of Patch operations that will move a materialized document from one state to another
127
127
  * if applied.
128
128
  *
129
129
  * @remarks
130
- * We allow specifying both a from/to heads or just a single comparison point, in which case
131
- * the base will be the current document heads.
130
+ * We allow specifying either:
131
+ * - Two sets of heads to compare directly
132
+ * - A single set of heads to compare against our current heads
133
+ * - Another DocHandle to compare against (which must share history with this document)
132
134
  *
133
- * @returns Automerge patches that go from one document state to the other. Use view() to get the full state.
135
+ * @throws Error if the documents don't share history or if either document is not ready
136
+ * @returns Automerge patches that go from one document state to the other
134
137
  */
135
- diff(first: A.Heads, second?: A.Heads): A.Patch[] | undefined;
138
+ diff(first: UrlHeads | DocHandle<T>, second?: UrlHeads): A.Patch[];
136
139
  /**
137
140
  * `metadata(head?)` allows you to look at the metadata for a change
138
141
  * this can be used to build history graphs to find commit messages and edit times.
@@ -162,9 +165,9 @@ export declare class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
162
165
  * Called by the repo either when a doc handle changes or we receive new remote heads.
163
166
  * @hidden
164
167
  */
165
- setRemoteHeads(storageId: StorageId, heads: A.Heads): void;
168
+ setRemoteHeads(storageId: StorageId, heads: UrlHeads): void;
166
169
  /** Returns the heads of the storageId. */
167
- getRemoteHeads(storageId: StorageId): A.Heads | undefined;
170
+ getRemoteHeads(storageId: StorageId): UrlHeads | undefined;
168
171
  /**
169
172
  * All changes to an Automerge document should be made through this method.
170
173
  * Inside the callback, the document should be treated as mutable: all edits will be recorded
@@ -186,7 +189,7 @@ export declare class DocHandle<T> extends EventEmitter<DocHandleEvents<T>> {
186
189
  *
187
190
  * @returns A set of heads representing the concurrent change that was made.
188
191
  */
189
- changeAt(heads: A.Heads, callback: A.ChangeFn<T>, options?: A.ChangeOptions<T>): string[] | undefined;
192
+ changeAt(heads: UrlHeads, callback: A.ChangeFn<T>, options?: A.ChangeOptions<T>): UrlHeads[] | undefined;
190
193
  /**
191
194
  * Merges another document into this document. Any peers we are sharing changes with will be
192
195
  * notified of the changes resulting from the merge.
@@ -234,6 +237,7 @@ export type DocHandleOptions<T> = {
234
237
  initialValue?: T;
235
238
  } | {
236
239
  isNew?: false;
240
+ heads?: UrlHeads;
237
241
  /** The number of milliseconds before we mark this document as unavailable if we don't have it and nobody shares it with us. */
238
242
  timeoutDelay?: number;
239
243
  };
@@ -285,7 +289,7 @@ export interface DocHandleOutboundEphemeralMessagePayload<T> {
285
289
  /** Emitted when we have new remote heads for this document */
286
290
  export interface DocHandleRemoteHeadsPayload {
287
291
  storageId: StorageId;
288
- heads: A.Heads;
292
+ heads: UrlHeads;
289
293
  }
290
294
  /**
291
295
  * Possible internal states for a DocHandle
@@ -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
@@ -2,7 +2,7 @@ import * as A from "@automerge/automerge/slim/next";
2
2
  import debug from "debug";
3
3
  import { EventEmitter } from "eventemitter3";
4
4
  import { assertEvent, assign, createActor, setup, waitFor } from "xstate";
5
- import { stringifyAutomergeUrl } from "./AutomergeUrl.js";
5
+ import { decodeHeads, encodeHeads, stringifyAutomergeUrl, } from "./AutomergeUrl.js";
6
6
  import { encode } from "./helpers/cbor.js";
7
7
  import { headsAreSame } from "./helpers/headsAreSame.js";
8
8
  import { withTimeout } from "./helpers/withTimeout.js";
@@ -24,6 +24,8 @@ export class DocHandle extends EventEmitter {
24
24
  #log;
25
25
  /** The XState actor running our state machine. */
26
26
  #machine;
27
+ /** If set, this handle will only show the document at these heads */
28
+ #fixedHeads;
27
29
  /** The last known state of our document. */
28
30
  #prevDocState = A.init();
29
31
  /** How long to wait before giving up on a document. (Note that a document will be marked
@@ -38,6 +40,9 @@ export class DocHandle extends EventEmitter {
38
40
  if ("timeoutDelay" in options && options.timeoutDelay) {
39
41
  this.#timeoutDelay = options.timeoutDelay;
40
42
  }
43
+ if ("heads" in options) {
44
+ this.#fixedHeads = options.heads;
45
+ }
41
46
  const doc = A.init();
42
47
  this.#log = debug(`automerge-repo:dochandle:${this.documentId.slice(0, 5)}`);
43
48
  const delay = this.#timeoutDelay;
@@ -150,7 +155,7 @@ export class DocHandle extends EventEmitter {
150
155
  #checkForChanges(before, after) {
151
156
  const beforeHeads = A.getHeads(before);
152
157
  const afterHeads = A.getHeads(after);
153
- const docChanged = !headsAreSame(afterHeads, beforeHeads);
158
+ const docChanged = !headsAreSame(encodeHeads(afterHeads), encodeHeads(beforeHeads));
154
159
  if (docChanged) {
155
160
  this.emit("heads-changed", { handle: this, doc: after });
156
161
  const patches = A.diff(after, beforeHeads, afterHeads);
@@ -173,7 +178,10 @@ export class DocHandle extends EventEmitter {
173
178
  /** Our documentId in Automerge URL form.
174
179
  */
175
180
  get url() {
176
- return stringifyAutomergeUrl({ documentId: this.documentId });
181
+ return stringifyAutomergeUrl({
182
+ documentId: this.documentId,
183
+ heads: this.#fixedHeads,
184
+ });
177
185
  }
178
186
  /**
179
187
  * @returns true if the document is ready for accessing or changes.
@@ -237,6 +245,13 @@ export class DocHandle extends EventEmitter {
237
245
  // if we timed out, return undefined
238
246
  return undefined;
239
247
  }
248
+ // If we have fixed heads, return a view at those heads
249
+ if (this.#fixedHeads) {
250
+ const doc = this.#doc;
251
+ if (!doc || this.isUnavailable())
252
+ return undefined;
253
+ return A.view(doc, decodeHeads(this.#fixedHeads));
254
+ }
240
255
  // Return the document
241
256
  return !this.isUnavailable() ? this.#doc : undefined;
242
257
  }
@@ -256,8 +271,11 @@ export class DocHandle extends EventEmitter {
256
271
  docSync() {
257
272
  if (!this.isReady())
258
273
  return undefined;
259
- else
260
- return this.#doc;
274
+ if (this.#fixedHeads) {
275
+ const doc = this.#doc;
276
+ return doc ? A.view(doc, decodeHeads(this.#fixedHeads)) : undefined;
277
+ }
278
+ return this.#doc;
261
279
  }
262
280
  /**
263
281
  * Returns the current "heads" of the document, akin to a git commit.
@@ -265,18 +283,18 @@ export class DocHandle extends EventEmitter {
265
283
  * @returns the current document's heads, or undefined if the document is not ready
266
284
  */
267
285
  heads() {
268
- if (!this.isReady()) {
286
+ if (!this.isReady())
269
287
  return undefined;
288
+ if (this.#fixedHeads) {
289
+ return this.#fixedHeads;
270
290
  }
271
- return A.getHeads(this.#doc);
291
+ return encodeHeads(A.getHeads(this.#doc));
272
292
  }
273
293
  begin() {
274
294
  this.#machine.send({ type: BEGIN });
275
295
  }
276
296
  /**
277
- * Creates a fixed "view" of an automerge document at the given point in time represented
278
- * by the `heads` passed in. The return value is the same type as docSync() and will return
279
- * undefined if the object hasn't finished loading.
297
+ * Returns an array of all past "heads" for the document in topological order.
280
298
  *
281
299
  * @remarks
282
300
  * A point-in-time in an automerge document is an *array* of heads since there may be
@@ -285,17 +303,17 @@ export class DocHandle extends EventEmitter {
285
303
  * history views would be quite large under concurrency (every thing in each branch against each other).
286
304
  * There might be a clever way to think about this, but we haven't found it yet, so for now at least
287
305
  * we present a single traversable view which excludes concurrency.
288
- * @returns The individual heads for every change in the document.
306
+ * @returns UrlHeads[] - The individual heads for every change in the document. Each item is a tagged string[1].
289
307
  */
290
308
  history() {
291
309
  if (!this.isReady()) {
292
310
  return undefined;
293
311
  }
294
312
  // This just returns all the heads as individual strings.
295
- return A.topoHistoryTraversal(this.#doc).map(h => [h]);
313
+ return A.topoHistoryTraversal(this.#doc).map(h => encodeHeads([h]));
296
314
  }
297
315
  /**
298
- * Creates a fixed "view" of an automerge document at the given point in time represented
316
+ * Creates a new DocHandle with a fixed "view" at the given point in time represented
299
317
  * by the `heads` passed in. The return value is the same type as docSync() and will return
300
318
  * undefined if the object hasn't finished loading.
301
319
  *
@@ -304,32 +322,59 @@ export class DocHandle extends EventEmitter {
304
322
  * of Automerge doesn't check types at runtime, so if you go back to an old set of heads
305
323
  * that doesn't match the heads here, Typescript will not save you.
306
324
  *
307
- * @returns An Automerge.Doc<T> at the point in time.
325
+ * @argument heads - The heads to view the document at. See history().
326
+ * @returns DocHandle<T> at the time of `heads`
308
327
  */
309
328
  view(heads) {
310
329
  if (!this.isReady()) {
311
- return undefined;
330
+ throw new Error(`DocHandle#${this.documentId} is not ready. Check \`handle.isReady()\` before calling view().`);
312
331
  }
313
- return A.view(this.#doc, heads);
332
+ // Create a new handle with the same documentId but fixed heads
333
+ const handle = new DocHandle(this.documentId, {
334
+ heads,
335
+ timeoutDelay: this.#timeoutDelay,
336
+ });
337
+ handle.update(() => A.clone(this.#doc));
338
+ handle.doneLoading();
339
+ return handle;
314
340
  }
315
341
  /**
316
342
  * Returns a set of Patch operations that will move a materialized document from one state to another
317
343
  * if applied.
318
344
  *
319
345
  * @remarks
320
- * We allow specifying both a from/to heads or just a single comparison point, in which case
321
- * the base will be the current document heads.
346
+ * We allow specifying either:
347
+ * - Two sets of heads to compare directly
348
+ * - A single set of heads to compare against our current heads
349
+ * - Another DocHandle to compare against (which must share history with this document)
322
350
  *
323
- * @returns Automerge patches that go from one document state to the other. Use view() to get the full state.
351
+ * @throws Error if the documents don't share history or if either document is not ready
352
+ * @returns Automerge patches that go from one document state to the other
324
353
  */
325
354
  diff(first, second) {
326
355
  if (!this.isReady()) {
327
- return undefined;
356
+ throw new Error(`DocHandle#${this.documentId} is not ready. Check \`handle.isReady()\` before calling diff().`);
357
+ }
358
+ const doc = this.#doc;
359
+ if (!doc)
360
+ throw new Error("Document not available");
361
+ // If first argument is a DocHandle
362
+ if (first instanceof DocHandle) {
363
+ if (!first.isReady()) {
364
+ throw new Error("Cannot diff against a handle that isn't ready");
365
+ }
366
+ const otherHeads = first.heads();
367
+ if (!otherHeads)
368
+ throw new Error("Other document's heads not available");
369
+ // Create a temporary merged doc to verify shared history and compute diff
370
+ const mergedDoc = A.merge(A.clone(doc), first.docSync());
371
+ // Use the merged doc to compute the diff
372
+ return A.diff(mergedDoc, decodeHeads(this.heads()), decodeHeads(otherHeads));
328
373
  }
329
- // We allow only one set of heads to be specified, in which case we use the doc's heads
330
- const from = second ? first : this.heads() || []; // because we guard above this should always have useful data
374
+ // Otherwise treat as heads
375
+ const from = second ? first : (this.heads() || []);
331
376
  const to = second ? second : first;
332
- return A.diff(this.#doc, from, to);
377
+ return A.diff(doc, decodeHeads(from), decodeHeads(to));
333
378
  }
334
379
  /**
335
380
  * `metadata(head?)` allows you to look at the metadata for a change
@@ -350,7 +395,8 @@ export class DocHandle extends EventEmitter {
350
395
  change = this.heads()[0];
351
396
  }
352
397
  // we return undefined instead of null by convention in this API
353
- return A.inspectChange(this.#doc, change) || undefined;
398
+ return (A.inspectChange(this.#doc, decodeHeads([change])[0]) ||
399
+ undefined);
354
400
  }
355
401
  /**
356
402
  * `update` is called any time we have a new document state; could be
@@ -400,6 +446,9 @@ export class DocHandle extends EventEmitter {
400
446
  if (!this.isReady()) {
401
447
  throw new Error(`DocHandle#${this.documentId} is in ${this.state} and not ready. Check \`handle.isReady()\` before accessing the document.`);
402
448
  }
449
+ if (this.#fixedHeads) {
450
+ throw new Error(`DocHandle#${this.documentId} is in view-only mode at specific heads. Use clone() to create a new document from this state.`);
451
+ }
403
452
  this.#machine.send({
404
453
  type: UPDATE,
405
454
  payload: { callback: doc => A.change(doc, options, callback) },
@@ -414,13 +463,18 @@ export class DocHandle extends EventEmitter {
414
463
  if (!this.isReady()) {
415
464
  throw new Error(`DocHandle#${this.documentId} is not ready. Check \`handle.isReady()\` before accessing the document.`);
416
465
  }
466
+ if (this.#fixedHeads) {
467
+ throw new Error(`DocHandle#${this.documentId} is in view-only mode at specific heads. Use clone() to create a new document from this state.`);
468
+ }
417
469
  let resultHeads = undefined;
418
470
  this.#machine.send({
419
471
  type: UPDATE,
420
472
  payload: {
421
473
  callback: doc => {
422
- const result = A.changeAt(doc, heads, options, callback);
423
- resultHeads = result.newHeads || undefined;
474
+ const result = A.changeAt(doc, decodeHeads(heads), options, callback);
475
+ resultHeads = result.newHeads
476
+ ? encodeHeads(result.newHeads)
477
+ : undefined;
424
478
  return result.newDoc;
425
479
  },
426
480
  },
@@ -442,6 +496,9 @@ export class DocHandle extends EventEmitter {
442
496
  if (!this.isReady() || !otherHandle.isReady()) {
443
497
  throw new Error("Both handles must be ready to merge");
444
498
  }
499
+ if (this.#fixedHeads) {
500
+ throw new Error(`DocHandle#${this.documentId} is in view-only mode at specific heads. Use clone() to create a new document from this state.`);
501
+ }
445
502
  const mergingDoc = otherHandle.docSync();
446
503
  if (!mergingDoc) {
447
504
  throw new Error("The document to be merged in is falsy, aborting.");
@@ -1,19 +1,19 @@
1
- import { next as A } from "@automerge/automerge/slim";
2
1
  import { EventEmitter } from "eventemitter3";
3
2
  import { DocumentId, PeerId } from "./types.js";
4
3
  import { RemoteHeadsChanged, RemoteSubscriptionControlMessage } from "./network/messages.js";
5
4
  import { StorageId } from "./index.js";
5
+ import { UrlHeads } from "./AutomergeUrl.js";
6
6
  export type RemoteHeadsSubscriptionEventPayload = {
7
7
  documentId: DocumentId;
8
8
  storageId: StorageId;
9
- remoteHeads: A.Heads;
9
+ remoteHeads: UrlHeads;
10
10
  timestamp: number;
11
11
  };
12
12
  export type NotifyRemoteHeadsPayload = {
13
13
  targetId: PeerId;
14
14
  documentId: DocumentId;
15
15
  storageId: StorageId;
16
- heads: A.Heads;
16
+ heads: UrlHeads;
17
17
  timestamp: number;
18
18
  };
19
19
  type RemoteHeadsSubscriptionEvents = {
@@ -33,7 +33,7 @@ export declare class RemoteHeadsSubscriptions extends EventEmitter<RemoteHeadsSu
33
33
  /** A peer we are not directly connected to has changed their heads */
34
34
  handleRemoteHeads(msg: RemoteHeadsChanged): void;
35
35
  /** A peer we are directly connected to has updated their heads */
36
- handleImmediateRemoteHeadsChanged(documentId: DocumentId, storageId: StorageId, heads: A.Heads): void;
36
+ handleImmediateRemoteHeadsChanged(documentId: DocumentId, storageId: StorageId, heads: UrlHeads): void;
37
37
  addGenerousPeer(peerId: PeerId): void;
38
38
  removePeer(peerId: PeerId): void;
39
39
  subscribePeerToDoc(peerId: PeerId, documentId: DocumentId): void;
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteHeadsSubscriptions.d.ts","sourceRoot":"","sources":["../src/RemoteHeadsSubscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EACL,kBAAkB,EAClB,gCAAgC,EACjC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAItC,MAAM,MAAM,mCAAmC,GAAG;IAChD,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,CAAC,CAAC,KAAK,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAGD,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,KAAK,6BAA6B,GAAG;IACnC,sBAAsB,EAAE,CAAC,OAAO,EAAE,mCAAmC,KAAK,IAAI,CAAA;IAC9E,oBAAoB,EAAE,CAAC,OAAO,EAAE;QAC9B,KAAK,EAAE,MAAM,EAAE,CAAA;QACf,GAAG,CAAC,EAAE,SAAS,EAAE,CAAA;QACjB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;KACrB,KAAK,IAAI,CAAA;IACV,qBAAqB,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAA;CACnE,CAAA;AAED,qBAAa,wBAAyB,SAAQ,YAAY,CAAC,6BAA6B,CAAC;;IAcvF,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE;IAkBvC,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE;IAsB3C,oBAAoB,CAAC,OAAO,EAAE,gCAAgC;IA0E9D,sEAAsE;IACtE,iBAAiB,CAAC,GAAG,EAAE,kBAAkB;IAgDzC,kEAAkE;IAClE,iCAAiC,CAC/B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,CAAC,CAAC,KAAK;IAgChB,eAAe,CAAC,MAAM,EAAE,MAAM;IAwB9B,UAAU,CAAC,MAAM,EAAE,MAAM;IA2BzB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;CAoE1D"}
1
+ {"version":3,"file":"RemoteHeadsSubscriptions.d.ts","sourceRoot":"","sources":["../src/RemoteHeadsSubscriptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,EACL,kBAAkB,EAClB,gCAAgC,EACjC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEtC,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAG5C,MAAM,MAAM,mCAAmC,GAAG;IAChD,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,WAAW,EAAE,QAAQ,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAGD,MAAM,MAAM,wBAAwB,GAAG;IACrC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,KAAK,EAAE,QAAQ,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,KAAK,6BAA6B,GAAG;IACnC,sBAAsB,EAAE,CAAC,OAAO,EAAE,mCAAmC,KAAK,IAAI,CAAA;IAC9E,oBAAoB,EAAE,CAAC,OAAO,EAAE;QAC9B,KAAK,EAAE,MAAM,EAAE,CAAA;QACf,GAAG,CAAC,EAAE,SAAS,EAAE,CAAA;QACjB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;KACrB,KAAK,IAAI,CAAA;IACV,qBAAqB,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAA;CACnE,CAAA;AAED,qBAAa,wBAAyB,SAAQ,YAAY,CAAC,6BAA6B,CAAC;;IAcvF,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE;IAkBvC,sBAAsB,CAAC,OAAO,EAAE,SAAS,EAAE;IAsB3C,oBAAoB,CAAC,OAAO,EAAE,gCAAgC;IA0E9D,sEAAsE;IACtE,iBAAiB,CAAC,GAAG,EAAE,kBAAkB;IAgDzC,kEAAkE;IAClE,iCAAiC,CAC/B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,QAAQ;IAgCjB,eAAe,CAAC,MAAM,EAAE,MAAM;IAwB9B,UAAU,CAAC,MAAM,EAAE,MAAM;IA2BzB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU;CAuE1D"}
@@ -270,7 +270,10 @@ export class RemoteHeadsSubscriptions extends EventEmitter {
270
270
  continue;
271
271
  }
272
272
  else {
273
- remote.set(storageId, { timestamp, heads });
273
+ remote.set(storageId, {
274
+ timestamp,
275
+ heads: heads,
276
+ });
274
277
  changedHeads.push({
275
278
  documentId,
276
279
  storageId: storageId,
@@ -1 +1 @@
1
- {"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"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"}