Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds import method to add an existing document to the repo #251

Merged
merged 2 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -442,6 +442,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