• Stars
    star
    278
  • Rank 143,562 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 7 years ago
  • Updated over 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

a p2p document synchronization system for automerge

MPL

Build cloud apps without needing cloud infrastructure.

Magic Persistence Layer is a WebRTC peer-to-peer synchronization system for automerge documents.

Guide

This guide will demonstrate how to create a basic counter app using Electron, React, and MPL. First, start by creating a new Electron app using Electron Forge with the React template.

$ npm install -g electron-forge
$ electron-forge init demo --template=react
$ cd demo

Now, install MPL:

$ npm install --save mpl

In src/app.jsx, initialize the MPL store and add the counter to the view:

import React from 'react'
import MPL from 'mpl'

export default class App extends React.Component {
  constructor() {
    super()

    this.store = new MPL.Store((state, action) => {
      switch(action.type) {
        case "INCREMENT_COUNTER":
          return MPL.Automerge.change(state, "increment counter", (doc) => {
            doc.counter = (state.counter || 0) + 1
          })
        default:
          return state
      }
    })

    // Force App component to re-render when state changes
    this.store.subscribe(() => this.setState({}))
  }

  componentDidMount() {
    // Normally your app would get your document id via URL or from a file,
    // but here we will fix it to "1" so our clients join the same doc
    this.store.dispatch({ type: "OPEN_DOCUMENT", docId: "1" })
  }

  render() {
    return <div>
      <h2>Counter: { this.store.getState().counter }</h2>
      <button onClick={ () => this.store.dispatch({type: "INCREMENT_COUNTER"}) } >
        Increment
      </button>
    </div>
  }
}

Start two clients and try incrementing the counter by clicking the button, and you should see the counters synchronize on both clients:

$ npm start & npm start

API

Store

The Store class is modeled off of Redux and follows the same basic pattern.

new Store(reducer)

Constructor that accepts a reducer function. When an action is dispatched to the store, it first checks against MPL's provided reducer actions and then invokes your reducer if the action did not map to any of the provided ones.

getState()

Returns the current state object including all of your persisted data.

getHistory()

Returns the change history from the state.

Ex:

store.getHistory()
=> [
  {
    "change": {
      "actor": "61d8b814-463c-4092-b71d-7137873840e4",
      "seq": 1,
      "deps": {},
      "message": "new document",
      "ops": [...]
    },
    "snapshot": {
      "cards": [...],
      "lists": [...],
      "docId": "saffron-guangzhou-85"
    }
  }
]

dispatch(action)

Sends an action through your reducer. You should only modify the state through dispatch. Note: dispatch is a synchronous function.

subscribe(listener)

Allows to register a listener callback. All listeners are invoked whenver there is a state change in the store, including inbound changes that come in through other peers over the network.

save()

Returns a JSON serialization of your store's state. This is useful for persisting your state to a file, which can then be opened later by dispatching a "OPEN_DOCUMENT" action.

Provided Actions

MPL.Store provides several built-in actions to create, open, and merge documents. All document management should go through your MPL.Store instance so that aMPL can connect to the right peer group and broadcast state changes over the network.

"NEW_DOCUMENT"

Resets the store's state to a new document.

Ex:

this.store.dispatch({
  type: "NEW_DOCUMENT"
})

"OPEN_DOCUMENT"

Opens a new document. Accepts a docId or file blob as parameters (i.e. the serialized output from MPL.Store#save().

Ex:

this.store.dispatch({
  type: "OPEN_DOCUMENT", docId: "1234-5678-9"
})

"FORK_DOCUMENT"

Creates a fork of the current document, copying all of its current data but creating a new docId.

Ex:

this.store.dispatch({
  type: "FORK_DOCUMENT"
})

Development

Compiling

MPL is configured via Babel to use ES2016 syntax. The source code is located in src and compiled code in lib. Make sure to compile and commit before creating a new release:

$ npm run compile

Testing

To run tests:

$ npm run test

Versions

When it's time to cut a release do the following:

  1. Edit local package.json and set version number (eg. 0.0.5)
  2. Make sure all code is compiled:
$ npm run compile
  1. Create a commit, tag, and push:
$ git commit -a -m "v0.0.5"
$ git tag v0.0.5
$ git push --tags

More Repositories

1

automerge-classic

A JSON-like data structure (a CRDT) that can be modified concurrently by different users, and merged again automatically.
JavaScript
14,768
star
2

automerge

A JSON-like data structure (a CRDT) that can be modified concurrently by different users, and merged again automatically.
JavaScript
3,205
star
3

hypermerge

Build p2p collaborative applications without any server infrastructure in Node.js
TypeScript
1,277
star
4

pushpin

A collaborative corkboard app
TypeScript
619
star
5

trellis

Trello clone / sample app for Automerge persistence library
JavaScript
497
star
6

automerge-repo

TypeScript
401
star
7

autosurgeon

Rust
249
star
8

pixelpusher

pushin' pix
JavaScript
219
star
9

automerge-swift

Swift language bindings presenting Automerge
Swift
205
star
10

automerge-swift-archived

Wrapper around Swift types that can be modified concurrently by different users, and merged again automatically (a CRDT).
Swift
159
star
11

automerge-go

Go
79
star
12

MeetingNotes

An example application that uses Automerge-Swift to provide collaborative note taking for meetings.
Swift
50
star
13

automerge-py

Rust
35
star
14

automerge-perf

Performance tests for Automerge
JavaScript
35
star
15

automerge-repo-rs

Rust
31
star
16

pinecone

An example Electron + React + Hypermerge application designed to be a starting point for your own ideas.
TypeScript
29
star
17

automerge-net

Network examples for Automerge
JavaScript
25
star
18

automerge-codemirror

TypeScript
21
star
19

automerge-prosemirror

TypeScript
20
star
20

automerge-java

Java
15
star
21

automerge.github.io

JavaScript
14
star
22

automerge-connection

A generic network synchronisation protocol for Automerge
JavaScript
12
star
23

sync-server

Simple WebSocket server for syncing Automerge clients
JavaScript
12
star
24

automerge-repo-swift

Extends the Automerge-swift library, providing support for working with multiple Automerge documents at once, with pluggable network and storage providers.
Swift
11
star
25

automerge-repo-sync-server

JavaScript
9
star
26

contaaacts

An automerge-swifter demo app
Swift
5
star
27

pixelpusherd

An archiver daemon for pixelpusher
JavaScript
5
star
28

automerge-swift-backend

A XCFramework wrapper for the rs-backend
Shell
5
star
29

automerge-repo-quickstart

TypeScript
5
star
30

prosemirror-quickstart

An example of using Automerge + Prosemirror
TypeScript
3
star
31

automerge-repo-network-peerjs

Network adapter for automerge-repo using peerjs
TypeScript
1
star