diff --git a/packages/automerge-repo/README.md b/packages/automerge-repo/README.md index c1460f025..18b42cf8e 100644 --- a/packages/automerge-repo/README.md +++ b/packages/automerge-repo/README.md @@ -45,6 +45,8 @@ A `Repo` exposes these methods: networks. - `delete(docId: DocumentId)` Deletes the local copy of a document from the local cache and local storage. _This does not currently delete the document from any other peers_. +- `import(binary: Uint8Array)` + Imports a document binary (from `Automerge.save(doc)`) into the repo, returning a new handle - `.on("document", ({handle: DocHandle}) => void)` Registers a callback to be fired each time a new document is loaded or created. - `.on("delete-document", ({handle: DocHandle}) => void)` @@ -64,7 +66,7 @@ the document. A `DocHandle` also emits these events: -- `change({handle: DocHandle, patches: Patch[], patchInfo: PatchInfo})` +- `change({handle: DocHandle, patches: Patch[], patchInfo: PatchInfo})` Called whenever the document changes, the handle's .doc - `delete` Called when the document is deleted locally. @@ -85,11 +87,12 @@ network adapter: const repo = new Repo({ network: [new BroadcastChannelNetworkAdapter()], storage: new IndexedDBStorageAdapter(), - sharePolicy: async (peerId: PeerId, documentId: DocumentId) => true // this is the default + sharePolicy: async (peerId: PeerId, documentId: DocumentId) => true, // this is the default }) ``` ### Share Policy + The share policy is used to determine which document in your repo should be _automatically_ shared with other peers. **The default setting is to share all documents with all peers.** > **Warning** @@ -99,13 +102,13 @@ You can override this by providing a custom share policy. The function should re The share policy will not stop a document being _requested_ by another peer by its `DocumentId`. -```ts +````ts ## Starting the demo app ```bash yarn yarn dev -``` +```` ## Quickstart @@ -272,7 +275,8 @@ you'll need to manually copy the `rootDocId` value between the browsers.) Originally authored by Peter van Hardenberg. With gratitude for contributions by: - - Herb Caudill - - Jeremy Rose - - Alex Currie-Clark - - Dylan Mackenzie + +- Herb Caudill +- Jeremy Rose +- Alex Currie-Clark +- Dylan Mackenzie diff --git a/packages/automerge-repo/src/Repo.ts b/packages/automerge-repo/src/Repo.ts index 275ce3f17..6122af8f2 100644 --- a/packages/automerge-repo/src/Repo.ts +++ b/packages/automerge-repo/src/Repo.ts @@ -442,6 +442,22 @@ export class Repo extends EventEmitter { this.emit("delete-document", { documentId }) } + /** + * Imports document binary into the repo. + * @param binary - The binary to import + */ + import(binary: Uint8Array) { + const doc = Automerge.load(binary) + + const handle = this.create() + + handle.update(() => { + return Automerge.clone(doc) + }) + + return handle + } + subscribeToRemotes = (remotes: StorageId[]) => { this.#log("subscribeToRemotes", { remotes }) this.#remoteHeadsSubscriptions.subscribeToRemotes(remotes) diff --git a/packages/automerge-repo/test/Repo.test.ts b/packages/automerge-repo/test/Repo.test.ts index 129cb6eb4..f3aca4987 100644 --- a/packages/automerge-repo/test/Repo.test.ts +++ b/packages/automerge-repo/test/Repo.test.ts @@ -2,7 +2,7 @@ import { next as A } from "@automerge/automerge" import { MessageChannelNetworkAdapter } from "@automerge/automerge-repo-network-messagechannel" import assert from "assert" import * as Uuid from "uuid" -import { describe, it } from "vitest" +import { describe, expect, it } from "vitest" import { READY } from "../src/DocHandle.js" import { parseAutomergeUrl } from "../src/AutomergeUrl.js" import { @@ -396,6 +396,30 @@ describe("Repo", () => { const storageKeyTypes = storageAdapter.keys().map(k => k.split(".")[1]) assert(storageKeyTypes.filter(k => k === "snapshot").length === 1) }) + + it("can import an existing document", async () => { + const { repo } = setup() + const doc = A.init() + const updatedDoc = A.change(doc, d => { + d.foo = "bar" + }) + + const saved = A.save(updatedDoc) + + const handle = repo.import(saved) + assert.equal(handle.isReady(), true) + const v = await handle.doc() + assert.equal(v?.foo, "bar") + + expect(A.getHistory(v)).toEqual(A.getHistory(updatedDoc)) + }) + + it("throws an error if we try to import an invalid document", async () => { + const { repo } = setup() + expect(() => { + repo.import(A.init as unknown as Uint8Array) + }).toThrow() + }) }) describe("with peers (linear network)", async () => {