Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sammccord/perge
Perge is a p2p synchronization system for Automerge documents using PeerJS
https://github.com/sammccord/perge
Last synced: 21 days ago
JSON representation
Perge is a p2p synchronization system for Automerge documents using PeerJS
- Host: GitHub
- URL: https://github.com/sammccord/perge
- Owner: sammccord
- License: mit
- Created: 2019-11-03T05:12:33.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T02:15:13.000Z (almost 2 years ago)
- Last Synced: 2024-04-20T13:30:19.340Z (8 months ago)
- Language: TypeScript
- Homepage:
- Size: 5.39 MB
- Stars: 56
- Watchers: 2
- Forks: 3
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Perge
Perge is a minimal p2p synchronization system for [Automerge](https://github.com/automerge/automerge) documents using [PeerJS](https://github.com/peers/peerjs).
![](screenshot.gif)
- [Perge](#perge)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [API](#api)
- [`Perge`](#perge-1)
- [`constructor (actorId: string, config: PergeConfig = {})`](#constructor-actorid-string-config-pergeconfig--)
- [`readonly docSet: Automerge.DocSet;`](#readonly-docset-automergedocsetany)
- [`readonly peer: Peer`](#readonly-peer-peer)
- [`connect(id: string, conn?: Peer.DataConnection, options?: Peer.PeerConnectOption): Peer.DataConnection`](#connectid-string-conn-peerdataconnection-options-peerpeerconnectoption-peerdataconnection)
- [`get(id: string): Doc`](#gettid-string-doct)
- [`select(id: string): (fn: Function, ...args: any[]) => Automerge.Doc`](#selecttid-string-fn-function-args-any--automergedoct)
- [`subscribe(idOrSetHandler: string | Automerge.DocSetHandler, callback?: Automerge.ChangeFn): () => void`](#subscribetidorsethandler-string--automergedocsethandlert-callback-automergechangefnt---void)## Installation
`Perge` has the following dependencies:
```json
{
"automerge": "^0.14.1",
"peerjs": "^1.2.0"
}
```Install `Perge` via npm:
```sh
npm install perge
```
or via yarn:
```sh
yarn add perge
```## Quick Start
For a more complete example, see [the example page](./example/index.html).
You can run the example with `yarn dev:example` which uses [Parcel](https://parceljs.org/getting_started.html)
```js
import { change } from 'automerge'
import Perge from 'perge'// instantiate library
const perge = new Perge('my-unique-id')// connect to a peer
perge.connect('someone-elses-unique-id')// subscribe to all docset changes
perge.subscribe((docId, doc) => {
// logs 'some-document-id', { message: 'Hey!' }
console.log(docId, doc)
})// subscribe to a single doc's changes
const unsubscribe = perge.subscribe('some-document-id', doc => {
// { message: 'Hey!' }
console.log(doc)
// unsubscribe this callback
unsubscribe()
})// select and change documents
perge.select('some-document-id')(
change,
doc => {
doc.message = 'Hey!'
}
)```
## API
### `Perge`
`Perge` is a class containing references to `Automerge.Connections`, and encodes and decodes passed messages using `PeerJS` and the `Automerge.Connection` protocol.
#### `constructor (actorId: string, config: PergeConfig = {})`
| `actorId` | `string` | Required. A unique ID used to initialize the PeerJS connection. Automerge should also be initialized with with this value.
You can further configure `Perge` with the following config shape. All properties are optional.
| Key | Type | Description |
| -------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `decode` | `(msg: string) => any` | A function called on a WebRTC string message before it is passed to an `Automerge.Connection` with `receiveMsg`, defaults to `JSON.parse` |
| `encode` | `(msg: any) => string` | A function called on `Automerge.DocSet` change objects before it is sent to a peer, defaults to `JSON.stringify` |
| `peer` | `PeerJS.Peer` | A preconfigured `PeerJS.Peer` instance. |
| `docSet` | `Automerge.DocSet` | An instantiated `Automerge.DocSet` to sync between clients. |#### `readonly docSet: Automerge.DocSet;`
A reference to the synchronized `Automerge.DocSet`, handy to subscribe to state changes with if you don't want to use `Perge.subscribe`:
```js
docSet.registerHandler((docId, doc) => {
// REACT TO STATE UPDATES
})
```#### `readonly peer: Peer`
A reference to the underlying PeerJS instance, useful for registering lifecycle handlers.
```js
perge.peer.on('error', (err) => {
// handle
})
```#### `connect(id: string, conn?: Peer.DataConnection, options?: Peer.PeerConnectOption): Peer.DataConnection`
Connects to a `PeerJS` peer with the given ID and sends outgoing `Automerge.DocSet` syncronization messages using the `Automerge.Connection` protocol.
Returns the DataConnection so you can register your own lifecycle callbacks.
Optionally, you can pass an existing `PeerJS` connection.
If you don't pass an existing `PeerJS` connection, it will connect using the given options, if any.
#### `get(id: string): Doc`
Gets an existing doc with given ID, or initializes a new doc with the client's actor ID.
#### `select(id: string): (fn: Function, ...args: any[]) => Automerge.Doc`
- [Updating Automerge Documents](https://github.com/automerge/automerge#updating-a-document)
Returns a function that applies a given `Automerge` document change method, then sets the returned document on the internal `DocSet` to broadcast changes to connected peers, for example:
```js
// Selects the document with the ID 'foo'
const exec = perge.select('foo')// Apply and broadcast changes on 'foo'
const newDoc = exec(
Automerge.change, // apply changes
'increase counter', // commit message
doc => { // mutate proxy document and apply changes
if(!doc.counter) doc.counter = new Automerge.Counter()
else doc.counter.increment()
}
)// which is roughly the same as:
const oldDoc = docSet.getDoc('foo') || Automerge.init(actorId)
const newDoc = Automerge.change(oldDoc, 'increase counter', doc => {
if(!doc.counter) doc.counter = new Automerge.Counter()
else doc.counter.increment()
})
perge.set.setDoc(id, newDoc)
```#### `subscribe(idOrSetHandler: string | Automerge.DocSetHandler, callback?: Automerge.ChangeFn): () => void`
Subscribe to doc updates for either the entire docSet or a specific document ID. Returns a function that, when called, unsubscribes.
```js
const unsubscribeFromAll = instance.subscribe((id, doc) => {
// do something with the updated doc
})// subscribe returns an unsubscribe function
const unsubscribeFromFoo = instance.subscribe('foo', (doc) => {
console.log('foo', doc)
if (doc.counter.value === 10) {
unsubscribeFromFoo()
console.log('unsubscribed from foo!')
}
})
```