@automerge/automerge-repo 1.0.2 → 1.0.4

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.
@@ -1,4 +1,5 @@
1
1
  import { SessionId } from "../EphemeralData.js";
2
+ export { type SessionId } from "../EphemeralData.js";
2
3
  import { DocumentId, PeerId } from "../types.js";
3
4
  export declare function isValidMessage(message: NetworkAdapterMessage): message is SyncMessage | EphemeralMessage | RequestMessage | DocumentUnavailableMessage;
4
5
  export declare function isDocumentUnavailableMessage(message: NetworkAdapterMessage): message is DocumentUnavailableMessage;
@@ -14,7 +15,20 @@ export interface SyncMessageContents {
14
15
  targetId: PeerId;
15
16
  documentId: DocumentId;
16
17
  }
17
- export type SyncMessage = SyncMessageEnvelope & SyncMessageContents;
18
+ /**
19
+ * A sync message for a particular document
20
+ */
21
+ export type SyncMessage = {
22
+ /** The peer ID of the sender of this message */
23
+ senderId: PeerId;
24
+ type: "sync";
25
+ /** The automerge sync message */
26
+ data: Uint8Array;
27
+ /** The peer ID of the recipient of this message */
28
+ targetId: PeerId;
29
+ /** The document ID of the document this message is for */
30
+ documentId: DocumentId;
31
+ };
18
32
  export interface EphemeralMessageEnvelope {
19
33
  senderId: PeerId;
20
34
  count: number;
@@ -26,32 +40,93 @@ export interface EphemeralMessageContents {
26
40
  documentId: DocumentId;
27
41
  data: Uint8Array;
28
42
  }
29
- export type EphemeralMessage = EphemeralMessageEnvelope & EphemeralMessageContents;
43
+ /** An ephemeral message
44
+ *
45
+ * @remarks
46
+ * Ephemeral messages are not persisted anywhere and have no particular
47
+ * structure. `automerge-repo` will gossip them around, in order to avoid
48
+ * eternal loops of ephemeral messages every message has a session ID, which
49
+ * is a random number generated by the sender at startup time, and a sequence
50
+ * number. The combination of these two things allows us to discard messages
51
+ * we have already seen.
52
+ * */
53
+ export type EphemeralMessage = {
54
+ /** The ID of the peer who sent this message */
55
+ senderId: PeerId;
56
+ /** A sequence number which must be incremented for each message sent by this peer */
57
+ count: number;
58
+ /** The ID of the session this message is part of. The sequence number for a given session always increases */
59
+ sessionId: SessionId;
60
+ type: "ephemeral";
61
+ /** The peer this message is for */
62
+ targetId: PeerId;
63
+ /** The document ID this message pertains to */
64
+ documentId: DocumentId;
65
+ /** The actual data of the message */
66
+ data: Uint8Array;
67
+ };
30
68
  export interface DocumentUnavailableMessageContents {
31
69
  type: "doc-unavailable";
32
70
  documentId: DocumentId;
33
71
  targetId: PeerId;
34
72
  }
35
- export type DocumentUnavailableMessage = SyncMessageEnvelope & DocumentUnavailableMessageContents;
73
+ /** Sent by a {@link Repo} to indicate that it does not have the document and none of it's connected peers do either */
74
+ export type DocumentUnavailableMessage = {
75
+ /** The peer who sent this message */
76
+ senderId: PeerId;
77
+ type: "doc-unavailable";
78
+ /** The document which the peer claims it doesn't have */
79
+ documentId: DocumentId;
80
+ /** The peer this message is for */
81
+ targetId: PeerId;
82
+ };
36
83
  export interface RequestMessageContents {
37
84
  type: "request";
38
85
  data: Uint8Array;
39
86
  targetId: PeerId;
40
87
  documentId: DocumentId;
41
88
  }
42
- export type RequestMessage = SyncMessageEnvelope & RequestMessageContents;
89
+ /** Sent by a {@link Repo} to request a document from a peer
90
+ *
91
+ * @remarks
92
+ * This is identical to a {@link SyncMessage} except that it is sent by a {@link Repo}
93
+ * as the initial sync message when asking the other peer if it has the document.
94
+ * */
95
+ export type RequestMessage = {
96
+ /** The peer who sent this message */
97
+ senderId: PeerId;
98
+ type: "request";
99
+ /** The initial automerge sync message */
100
+ data: Uint8Array;
101
+ /** The peer this message is for */
102
+ targetId: PeerId;
103
+ /** The document ID this message requests */
104
+ documentId: DocumentId;
105
+ };
43
106
  export type MessageContents = SyncMessageContents | EphemeralMessageContents | RequestMessageContents | DocumentUnavailableMessageContents;
107
+ /** The type of messages that {@link Repo} sends and receive to {@link NetworkAdapter}s */
44
108
  export type Message = SyncMessage | EphemeralMessage | RequestMessage | DocumentUnavailableMessage;
45
109
  export type SynchronizerMessage = SyncMessage | RequestMessage | DocumentUnavailableMessage | EphemeralMessage;
46
- type ArriveMessage = {
110
+ /** Notify the network that we have arrived so everyone knows our peer ID */
111
+ export type ArriveMessage = {
112
+ /** Our peer ID */
47
113
  senderId: PeerId;
48
114
  type: "arrive";
49
115
  };
50
- type WelcomeMessage = {
116
+ /** Respond to an arriving peer with our peer ID */
117
+ export type WelcomeMessage = {
118
+ /** Our peer ID */
51
119
  senderId: PeerId;
120
+ /** The ID of the peer who sent the {@link ArriveMessage} we are responding to */
52
121
  targetId: PeerId;
53
122
  type: "welcome";
54
123
  };
124
+ /** The type of messages that {@link NetworkAdapter}s send and receive to each other
125
+ *
126
+ * @remarks
127
+ * It is not _required_ that a {@link NetworkAdapter} use this message type.
128
+ * NetworkAdapters are free to use whatever message type makes sense for their
129
+ * transport. However, this type is a useful default.
130
+ * */
55
131
  export type NetworkAdapterMessage = ArriveMessage | WelcomeMessage | Message;
56
- export {};
57
132
  //# sourceMappingURL=messages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/network/messages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEhD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,IACN,WAAW,GACX,gBAAgB,GAChB,cAAc,GACd,0BAA0B,CAU7B;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,qBAAqB,GAC7B,OAAO,IAAI,0BAA0B,CAEvC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,IAAI,cAAc,CAE3B;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,IAAI,WAAW,CAExB;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,qBAAqB,GAAG,eAAe,GAC/C,OAAO,IAAI,gBAAgB,GAAG,wBAAwB,CAExD;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,MAAM,WAAW,GAAG,mBAAmB,GAAG,mBAAmB,CAAA;AAEnE,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,SAAS,CAAA;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;IACtB,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,MAAM,MAAM,gBAAgB,GAAG,wBAAwB,GACrD,wBAAwB,CAAA;AAE1B,MAAM,WAAW,kCAAkC;IACjD,IAAI,EAAE,iBAAiB,CAAA;IACvB,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,0BAA0B,GAAG,mBAAmB,GAC1D,kCAAkC,CAAA;AAEpC,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,SAAS,CAAA;IACf,IAAI,EAAE,UAAU,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,UAAU,CAAA;CACvB;AAED,MAAM,MAAM,cAAc,GAAG,mBAAmB,GAAG,sBAAsB,CAAA;AAEzE,MAAM,MAAM,eAAe,GACvB,mBAAmB,GACnB,wBAAwB,GACxB,sBAAsB,GACtB,kCAAkC,CAAA;AAEtC,MAAM,MAAM,OAAO,GACf,WAAW,GACX,gBAAgB,GAChB,cAAc,GACd,0BAA0B,CAAA;AAE9B,MAAM,MAAM,mBAAmB,GAC3B,WAAW,GACX,cAAc,GACd,0BAA0B,GAC1B,gBAAgB,CAAA;AAEpB,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,QAAQ,CAAA;CACf,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,SAAS,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG,cAAc,GAAG,OAAO,CAAA"}
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../src/network/messages.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,33 @@
1
+ /** A storage adapter represents some way of storing binary data for a {@link Repo}
2
+ *
3
+ * @remarks
4
+ * `StorageAdapter`s are a little like a key/value store. The keys are arrays
5
+ * of strings ({@link StorageKey}) and the values are binary blobs.
6
+ */
1
7
  export declare abstract class StorageAdapter {
8
+ /** Load the single blob correspongind to `key` */
2
9
  abstract load(key: StorageKey): Promise<Uint8Array | undefined>;
10
+ /** save the blod `data` to the key `key` */
3
11
  abstract save(key: StorageKey, data: Uint8Array): Promise<void>;
12
+ /** remove the blob corresponding to `key` */
4
13
  abstract remove(key: StorageKey): Promise<void>;
14
+ /** Load all blobs with keys that start with `keyPrefix` */
5
15
  abstract loadRange(keyPrefix: StorageKey): Promise<{
6
16
  key: StorageKey;
7
17
  data: Uint8Array;
8
18
  }[]>;
19
+ /** Remove all blobs with keys that start with `keyPrefix` */
9
20
  abstract removeRange(keyPrefix: StorageKey): Promise<void>;
10
21
  }
22
+ /** The type of keys for a {@link StorageAdapter}
23
+ *
24
+ * @remarks
25
+ * Storage keys are arrays because they are hierarchical and the storage
26
+ * subsystem will need to be able to do range queries for all keys that
27
+ * have a particular prefix. For example, incremental changes for a given
28
+ * document might be stored under `[<documentId>, "incremental", <SHA256>]`.
29
+ * `StorageAdapter` implementations should not assume any particular structure
30
+ * though.
31
+ **/
11
32
  export type StorageKey = string[];
12
33
  //# sourceMappingURL=StorageAdapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"StorageAdapter.d.ts","sourceRoot":"","sources":["../../src/storage/StorageAdapter.ts"],"names":[],"mappings":"AAAA,8BAAsB,cAAc;IAMlC,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAC/D,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAC/D,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC;QAAC,GAAG,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAC,EAAE,CAAC;IACzF,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAC3D;AAED,MAAM,MAAO,UAAU,GAAG,MAAM,EAAE,CAAA"}
1
+ {"version":3,"file":"StorageAdapter.d.ts","sourceRoot":"","sources":["../../src/storage/StorageAdapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,8BAAsB,cAAc;IAMlC,kDAAkD;IAClD,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAC/D,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAC/D,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC;QAAC,GAAG,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,UAAU,CAAA;KAAC,EAAE,CAAC;IACzF,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAC3D;AAED;;;;;;;;;IASI;AACJ,MAAM,MAAO,UAAU,GAAG,MAAM,EAAE,CAAA"}
@@ -1,2 +1,8 @@
1
+ /** A storage adapter represents some way of storing binary data for a {@link Repo}
2
+ *
3
+ * @remarks
4
+ * `StorageAdapter`s are a little like a key/value store. The keys are arrays
5
+ * of strings ({@link StorageKey}) and the values are binary blobs.
6
+ */
1
7
  export class StorageAdapter {
2
8
  }
package/dist/types.d.ts CHANGED
@@ -1,14 +1,25 @@
1
+ /** The ID of a document. Typically you should use a {@link AutomergeUrl} instead.
2
+ */
1
3
  export type DocumentId = string & {
2
4
  __documentId: true;
3
5
  };
6
+ /** A branded string representing a URL for a document
7
+ *
8
+ * @remarks
9
+ * An automerge URL has the form `automerge:<base58 encoded string>`. This
10
+ * type is returned from various routines which validate a url.
11
+ *
12
+ */
4
13
  export type AutomergeUrl = string & {
5
14
  __documentUrl: true;
6
15
  };
16
+ /** A document ID as a Uint8Array instead of a bas58 encoded string. Typically you should use a {@link AutomergeUrl} instead.
17
+ */
7
18
  export type BinaryDocumentId = Uint8Array & {
8
19
  __binaryDocumentId: true;
9
20
  };
21
+ /** A branded type for peer IDs */
10
22
  export type PeerId = string & {
11
23
  __peerId: false;
12
24
  };
13
- export type DistributiveOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;
14
25
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG;IAAE,YAAY,EAAE,IAAI,CAAA;CAAE,CAAA;AACxD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,aAAa,EAAE,IAAI,CAAA;CAAE,CAAA;AAC3D,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG;IAAE,kBAAkB,EAAE,IAAI,CAAA;CAAE,CAAA;AAExE,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAA;CAAE,CAAA;AAEjD,MAAM,MAAM,gBAAgB,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,GAAG,IAAI,CAAC,SAAS,GAAG,GAChE,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GACV,KAAK,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;GACG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG;IAAE,YAAY,EAAE,IAAI,CAAA;CAAE,CAAA;AACxD;;;;;;GAMG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,aAAa,EAAE,IAAI,CAAA;CAAE,CAAA;AAC3D;GACG;AACH,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG;IAAE,kBAAkB,EAAE,IAAI,CAAA;CAAE,CAAA;AAExE,kCAAkC;AAClC,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG;IAAE,QAAQ,EAAE,KAAK,CAAA;CAAE,CAAA"}
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@automerge/automerge-repo",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "A repository object to manage a collection of automerge documents",
5
- "repository": "https://github.com/automerge/automerge-repo",
5
+ "repository": "https://github.com/automerge/automerge-repo/tree/master/packages/automerge-repo",
6
6
  "author": "Peter van Hardenberg <pvh@pvh.ca>",
7
7
  "license": "MIT",
8
- "private": false,
9
8
  "type": "module",
10
9
  "main": "dist/index.js",
11
10
  "scripts": {
@@ -21,6 +20,7 @@
21
20
  "crypto": false
22
21
  },
23
22
  "devDependencies": {
23
+ "@automerge/automerge": "^2.1.0",
24
24
  "@types/debug": "^4.1.7",
25
25
  "@types/node": "^20.4.8",
26
26
  "@types/uuid": "^8.3.4",
@@ -41,7 +41,7 @@
41
41
  "fast-sha256": "^1.3.0",
42
42
  "tiny-typed-emitter": "^2.1.0",
43
43
  "ts-node": "^10.9.1",
44
- "uuid": "^8.3.2",
44
+ "uuid": "^9.0.0",
45
45
  "xstate": "^4.37.0"
46
46
  },
47
47
  "watch": {
@@ -65,5 +65,5 @@
65
65
  "publishConfig": {
66
66
  "access": "public"
67
67
  },
68
- "gitHead": "c72b9ec33c3a1f7f39ad20cb4fa0d766afe42158"
68
+ "gitHead": "17fd5260f9af3e65da636fef084e8c04d6c4bed0"
69
69
  }
package/src/DocHandle.ts CHANGED
@@ -21,7 +21,18 @@ import type { DocumentId, PeerId, AutomergeUrl } from "./types.js"
21
21
  import { stringifyAutomergeUrl } from "./DocUrl.js"
22
22
  import { encode } from "./helpers/cbor.js"
23
23
 
24
- /** DocHandle is a wrapper around a single Automerge document that lets us listen for changes. */
24
+ /** DocHandle is a wrapper around a single Automerge document that lets us
25
+ * listen for changes and notify the network and storage of new changes.
26
+ *
27
+ * @remarks
28
+ * A `DocHandle` represents a document which is being managed by a {@link Repo}.
29
+ * To obtain `DocHandle` use {@link Repo.find} or {@link Repo.create}.
30
+ *
31
+ * To modify the underlying document use either {@link DocHandle.change} or
32
+ * {@link DocHandle.changeAt}. These methods will notify the `Repo` that some
33
+ * change has occured and the `Repo` will save any new changes to the
34
+ * attached {@link StorageAdapter} and send sync messages to connected peers.
35
+ * */
25
36
  export class DocHandle<T> //
26
37
  extends EventEmitter<DocHandleEvents<T>>
27
38
  {
@@ -30,10 +41,16 @@ export class DocHandle<T> //
30
41
  #machine: DocHandleXstateMachine<T>
31
42
  #timeoutDelay: number
32
43
 
44
+ /** The URL of this document
45
+ *
46
+ * @remarks
47
+ * This can be used to request the document from an instance of {@link Repo}
48
+ */
33
49
  get url(): AutomergeUrl {
34
50
  return stringifyAutomergeUrl({ documentId: this.documentId })
35
51
  }
36
52
 
53
+ /** @hidden */
37
54
  constructor(
38
55
  public documentId: DocumentId,
39
56
  { isNew = false, timeoutDelay = 60_000 }: DocHandleOptions = {}
@@ -248,6 +265,7 @@ export class DocHandle<T> //
248
265
  inState = (states: HandleState[]) =>
249
266
  states.some(this.#machine?.getSnapshot().matches)
250
267
 
268
+ /** @hidden */
251
269
  get state() {
252
270
  return this.#machine?.getSnapshot().value
253
271
  }
@@ -303,7 +321,9 @@ export class DocHandle<T> //
303
321
  return this.#doc
304
322
  }
305
323
 
306
- /** `update` is called by the repo when we receive changes from the network */
324
+ /** `update` is called by the repo when we receive changes from the network
325
+ * @hidden
326
+ * */
307
327
  update(callback: (doc: A.Doc<T>) => A.Doc<T>) {
308
328
  this.#machine.send(UPDATE, {
309
329
  payload: { callback },
@@ -357,15 +377,19 @@ export class DocHandle<T> //
357
377
  this.#machine.send(MARK_UNAVAILABLE)
358
378
  }
359
379
 
360
- /** `request` is called by the repo when the document is not found in storage */
380
+ /** `request` is called by the repo when the document is not found in storage
381
+ * @hidden
382
+ * */
361
383
  request() {
362
384
  if (this.#state === LOADING) this.#machine.send(REQUEST)
363
385
  }
364
386
 
387
+ /** @hidden */
365
388
  awaitNetwork() {
366
389
  if (this.#state === LOADING) this.#machine.send(AWAIT_NETWORK)
367
390
  }
368
391
 
392
+ /** @hidden */
369
393
  networkReady() {
370
394
  if (this.#state === AWAITING_NETWORK) this.#machine.send(NETWORK_READY)
371
395
  }
@@ -391,7 +415,8 @@ export class DocHandle<T> //
391
415
 
392
416
  // WRAPPER CLASS TYPES
393
417
 
394
- interface DocHandleOptions {
418
+ /** @hidden */
419
+ export interface DocHandleOptions {
395
420
  isNew?: boolean
396
421
  timeoutDelay?: number
397
422
  }
@@ -411,10 +436,15 @@ export interface DocHandleDeletePayload<T> {
411
436
  handle: DocHandle<T>
412
437
  }
413
438
 
439
+ /** Emitted when a document has changed */
414
440
  export interface DocHandleChangePayload<T> {
441
+ /** The hande which changed */
415
442
  handle: DocHandle<T>
443
+ /** The value of the document after the change */
416
444
  doc: A.Doc<T>
445
+ /** The patches representing the change that occurred */
417
446
  patches: A.Patch[]
447
+ /** Information about the change */
418
448
  patchInfo: A.PatchInfo<T>
419
449
  }
420
450
 
@@ -444,14 +474,27 @@ export interface DocHandleEvents<T> {
444
474
 
445
475
  // state
446
476
 
477
+ /**
478
+ * The state of a document handle
479
+ * @enum
480
+ *
481
+ */
447
482
  export const HandleState = {
483
+ /** The handle has been created but not yet loaded or requested */
448
484
  IDLE: "idle",
485
+ /** We are waiting for storage to finish loading */
449
486
  LOADING: "loading",
487
+ /** We are waiting for the network to be come ready */
450
488
  AWAITING_NETWORK: "awaitingNetwork",
489
+ /** We are waiting for someone in the network to respond to a sync request */
451
490
  REQUESTING: "requesting",
491
+ /** The document is available */
452
492
  READY: "ready",
493
+ /** We were unable to load or request the document for some reason */
453
494
  FAILED: "failed",
495
+ /** The document has been deleted from the repo */
454
496
  DELETED: "deleted",
497
+ /** The document was not available in storage or from any connected peers */
455
498
  UNAVAILABLE: "unavailable",
456
499
  } as const
457
500
  export type HandleState = (typeof HandleState)[keyof typeof HandleState]
package/src/DocUrl.ts CHANGED
@@ -20,10 +20,6 @@ export const parseAutomergeUrl = (url: AutomergeUrl) => {
20
20
  return { binaryDocumentId, documentId }
21
21
  }
22
22
 
23
- interface StringifyAutomergeUrlOptions {
24
- documentId: DocumentId | BinaryDocumentId
25
- }
26
-
27
23
  /**
28
24
  * Given a documentId in either canonical form, return an Automerge URL
29
25
  * Throws on invalid input.
@@ -33,7 +29,7 @@ interface StringifyAutomergeUrlOptions {
33
29
  */
34
30
  export const stringifyAutomergeUrl = ({
35
31
  documentId,
36
- }: StringifyAutomergeUrlOptions): AutomergeUrl => {
32
+ }: {documentId: DocumentId | BinaryDocumentId}): AutomergeUrl => {
37
33
  if (documentId instanceof Uint8Array)
38
34
  return (urlPrefix +
39
35
  binaryToDocumentId(documentId as BinaryDocumentId)) as AutomergeUrl
@@ -2,6 +2,7 @@ import { DocumentId, PeerId } from "./index.js"
2
2
  import { EphemeralMessageContents } from "./network/messages.js"
3
3
 
4
4
  // types
5
+ /** A randomly generated string created when the {@link Repo} starts up */
5
6
  export type SessionId = string & { __SessionId: false }
6
7
 
7
8
  export interface EphemeralDataPayload {
package/src/Repo.ts CHANGED
@@ -18,14 +18,24 @@ import { EventEmitter } from "eventemitter3"
18
18
  import bs58check from "bs58check"
19
19
 
20
20
  /** A Repo is a collection of documents with networking, syncing, and storage capabilities. */
21
- export class Repo extends EventEmitter<DocCollectionEvents> {
21
+ /** The `Repo` is the main entry point of this library
22
+ *
23
+ * @remarks
24
+ * To construct a `Repo` you will need an {@link StorageAdapter} and one or
25
+ * more {@link NetworkAdapter}s. Once you have a `Repo` you can use it to
26
+ * obtain {@link DocHandle}s.
27
+ */
28
+ export class Repo extends EventEmitter<RepoEvents> {
22
29
  #log: debug.Debugger
23
30
 
31
+ /** @hidden */
24
32
  networkSubsystem: NetworkSubsystem
33
+ /** @hidden */
25
34
  storageSubsystem?: StorageSubsystem
26
35
  #handleCache: Record<DocumentId, DocHandle<any>> = {}
27
36
 
28
37
  /** By default, we share generously with all peers. */
38
+ /** @hidden */
29
39
  sharePolicy: SharePolicy = async () => true
30
40
 
31
41
  constructor({ storage, network, peerId, sharePolicy }: RepoConfig) {
@@ -257,23 +267,34 @@ export interface RepoConfig {
257
267
  sharePolicy?: SharePolicy
258
268
  }
259
269
 
270
+ /** A function that determines whether we should share a document with a peer
271
+ *
272
+ * @remarks
273
+ * This function is called by the {@link Repo} every time a new document is created
274
+ * or discovered (such as when another peer starts syncing with us). If this
275
+ * function returns `true` then the {@link Repo} will begin sharing the new
276
+ * document with the peer given by `peerId`.
277
+ * */
260
278
  export type SharePolicy = (
261
279
  peerId: PeerId,
262
280
  documentId?: DocumentId
263
281
  ) => Promise<boolean>
264
282
 
265
283
  // events & payloads
266
- interface DocCollectionEvents {
284
+ export interface RepoEvents {
285
+ /** A new document was created or discovered */
267
286
  document: (arg: DocumentPayload) => void
287
+ /** A document was deleted */
268
288
  "delete-document": (arg: DeleteDocumentPayload) => void
289
+ /** A document was marked as unavailable (we don't have it and none of our peers have it) */
269
290
  "unavailable-document": (arg: DeleteDocumentPayload) => void
270
291
  }
271
292
 
272
- interface DocumentPayload {
293
+ export interface DocumentPayload {
273
294
  handle: DocHandle<any>
274
295
  isNew: boolean
275
296
  }
276
297
 
277
- interface DeleteDocumentPayload {
298
+ export interface DeleteDocumentPayload {
278
299
  documentId: DocumentId
279
300
  }
package/src/index.ts CHANGED
@@ -1,10 +1,45 @@
1
- export { DocHandle, HandleState } from "./DocHandle.js"
2
- export type { DocHandleChangePayload } from "./DocHandle.js"
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * The [`automerge`](https://www.npmjs.com/package/@automerge/automerge) CRDT
5
+ * provides a core CRDT data structure and an implementation of a storage
6
+ * format and sync protocol but doesn't provide the plumbing to use these tools
7
+ * in a JS application. `automerge-repo` provides the plumbing.
8
+ *
9
+ * The main entry point is the {@link Repo} class, which you instantiate with
10
+ * a {@link StorageAdapter} and zero or more {@link NetworkAdapter}s. Once you
11
+ * have a repo you can use it to create {@link DocHandle}s. {@link DocHandle}s
12
+ * are a reference to a document, identified by a {@link AutomergeUrl}, a place to
13
+ * listen for changes to the document, and to make new changes.
14
+ *
15
+ * A typical example of how to use this library then might look like this:
16
+ *
17
+ * ```typescript
18
+ * import { Repo } from "@automerge/automerge-repo";
19
+ *
20
+ * const repo = new Repo({
21
+ * storage: <storage adapter>,
22
+ * network: [<network adapter>, <network adapter>]
23
+ * })
24
+ *
25
+ * const handle = repo.create
26
+ * ```
27
+ */
28
+
29
+ export { DocHandle, type HandleState, type DocHandleOptions, type DocHandleEvents } from "./DocHandle.js"
30
+ export type {
31
+ DocHandleChangePayload,
32
+ DocHandleDeletePayload,
33
+ DocHandleEphemeralMessagePayload,
34
+ DocHandleOutboundEphemeralMessagePayload,
35
+ DocHandleEncodedChangePayload,
36
+ } from "./DocHandle.js"
3
37
  export { NetworkAdapter } from "./network/NetworkAdapter.js"
4
38
  export type {
5
39
  OpenPayload,
6
40
  PeerCandidatePayload,
7
41
  PeerDisconnectedPayload,
42
+ NetworkAdapterEvents,
8
43
  } from "./network/NetworkAdapter.js"
9
44
 
10
45
  // This is a bit confusing right now, but:
@@ -13,17 +48,19 @@ export type {
13
48
  // and Message is (as of this writing) a union type for EphmeralMessage and SyncMessage
14
49
  export type {
15
50
  Message,
51
+ ArriveMessage,
52
+ WelcomeMessage,
16
53
  NetworkAdapterMessage,
17
54
  EphemeralMessage,
55
+ RequestMessage,
56
+ DocumentUnavailableMessage,
18
57
  SyncMessage,
58
+ SessionId,
19
59
  } from "./network/messages.js"
20
60
  export { isValidMessage } from "./network/messages.js"
21
61
 
22
- export { NetworkSubsystem } from "./network/NetworkSubsystem.js"
23
- export { Repo, type SharePolicy } from "./Repo.js"
62
+ export { Repo, type SharePolicy, type RepoConfig, type RepoEvents, type DeleteDocumentPayload, type DocumentPayload } from "./Repo.js"
24
63
  export { StorageAdapter, type StorageKey } from "./storage/StorageAdapter.js"
25
- export { StorageSubsystem } from "./storage/StorageSubsystem.js"
26
- export { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js"
27
64
  export {
28
65
  parseAutomergeUrl,
29
66
  isValidAutomergeUrl,
@@ -31,4 +68,5 @@ export {
31
68
  } from "./DocUrl.js"
32
69
  export * from "./types.js"
33
70
 
71
+ /** @hidden **/
34
72
  export * as cbor from "./helpers/cbor.js"
@@ -2,23 +2,44 @@ import { EventEmitter } from "eventemitter3"
2
2
  import { PeerId } from "../types.js"
3
3
  import { Message } from "./messages.js"
4
4
 
5
+ /** An interface representing some way to connect to other peers
6
+ *
7
+ * @remarks
8
+ * The {@link Repo} uses one or more `NetworkAdapter`s to connect to other peers.
9
+ * Because the network may take some time to be ready the {@link Repo} will wait
10
+ * until the adapter emits a `ready` event before it starts trying to use it
11
+ */
5
12
  export abstract class NetworkAdapter extends EventEmitter<NetworkAdapterEvents> {
6
13
  peerId?: PeerId // hmmm, maybe not
7
14
 
15
+ /** Called by the {@link Repo} to start the connection process
16
+ *
17
+ * @argument peerId - the peerId of this repo
18
+ */
8
19
  abstract connect(peerId: PeerId): void
9
20
 
21
+ /** Called by the {@link Repo} to send a message to a peer
22
+ *
23
+ * @argument message - the message to send
24
+ */
10
25
  abstract send(message: Message): void
11
26
 
27
+ /** Called by the {@link Repo} to disconnect from the network */
12
28
  abstract disconnect(): void
13
29
  }
14
30
 
15
31
  // events & payloads
16
32
 
17
33
  export interface NetworkAdapterEvents {
34
+ /** Emitted when the network is ready to be used */
18
35
  ready: (payload: OpenPayload) => void
36
+ /** Emitted when the network is closed */
19
37
  close: () => void
38
+ /** Emitted when the network adapter learns about a new peer */
20
39
  "peer-candidate": (payload: PeerCandidatePayload) => void
40
+ /** Emitted when the network adapter learns that a peer has disconnected */
21
41
  "peer-disconnected": (payload: PeerDisconnectedPayload) => void
42
+ /** Emitted when the network adapter receives a message from a peer */
22
43
  message: (payload: Message) => void
23
44
  }
24
45