Skip to content

Commit

Permalink
Merge pull request #251 from automerge/add-import-method
Browse files Browse the repository at this point in the history
Adds `import` method to add an existing document to the repo
  • Loading branch information
pvh authored Dec 14, 2023
2 parents 7ebf1dd + 72eec7f commit 5226d19
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 9 deletions.
20 changes: 12 additions & 8 deletions packages/automerge-repo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)`
Expand All @@ -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.
Expand All @@ -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**
Expand All @@ -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
Expand Down Expand Up @@ -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
16 changes: 16 additions & 0 deletions packages/automerge-repo/src/Repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,22 @@ export class Repo extends EventEmitter<RepoEvents> {
this.emit("delete-document", { documentId })
}

/**
* Imports document binary into the repo.
* @param binary - The binary to import
*/
import<T>(binary: Uint8Array) {
const doc = Automerge.load<T>(binary)

const handle = this.create<T>()

handle.update(() => {
return Automerge.clone(doc)
})

return handle
}

subscribeToRemotes = (remotes: StorageId[]) => {
this.#log("subscribeToRemotes", { remotes })
this.#remoteHeadsSubscriptions.subscribeToRemotes(remotes)
Expand Down
26 changes: 25 additions & 1 deletion packages/automerge-repo/test/Repo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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<TestDoc>()
const updatedDoc = A.change(doc, d => {
d.foo = "bar"
})

const saved = A.save(updatedDoc)

const handle = repo.import<TestDoc>(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<TestDoc>(A.init<TestDoc> as unknown as Uint8Array)
}).toThrow()
})
})

describe("with peers (linear network)", async () => {
Expand Down

0 comments on commit 5226d19

Please sign in to comment.