Comparing version 0.1.1 to 1.0.3
{ | ||
"name": "demux", | ||
"version": "0.1.1", | ||
"keywords": [ "stream", "streams", "multiplex", "mux", "demux", "demultiplex" ], | ||
"description": "Combine a bunch of streams into one", | ||
"author": "Drew Young", | ||
"main": "./index", | ||
"repository": { "type": "git", "url": "http://github.com/drewyoung1/demux.git" }, | ||
"dependencies": { | ||
"through": "~2.1.0" | ||
} | ||
} | ||
"name": "demux", | ||
"version": "1.0.3", | ||
"author": { | ||
"name": "Julien Heller", | ||
"url": "https://block.one/" | ||
}, | ||
"license": "MIT", | ||
"description": "Deterministic event-sourced state and side effect handling for blockchain applications", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"repository": "https://github.com/EOSIO/demux-js", | ||
"devDependencies": { | ||
"@types/jest": "^23.1.4", | ||
"@types/node": "^10.5.1", | ||
"@types/request-promise-native": "^1.0.15", | ||
"eslint": "^4.9.0", | ||
"eslint-config-airbnb-base": "12.1.0", | ||
"eslint-plugin-import": "^2.7.0", | ||
"jest": "^22.4.3", | ||
"release-it": "^7.5.0", | ||
"ts-jest": "^23.0.0", | ||
"tslint": "^5.10.0", | ||
"tslint-eslint-rules": "^5.3.1", | ||
"typedoc": "^0.11.1", | ||
"typescript": "^2.9.2" | ||
}, | ||
"scripts": { | ||
"compile": "tsc", | ||
"watch": "tsc -w", | ||
"example": "./run-example.sh", | ||
"lint": "tslint -c tslint.json src/**/*.ts", | ||
"test": "jest", | ||
"build-docs": "./build-docs.sh" | ||
}, | ||
"jest": { | ||
"moduleFileExtensions": [ | ||
"ts", | ||
"tsx", | ||
"js" | ||
], | ||
"transform": { | ||
"^.+\\.(tsx?)$": "ts-jest" | ||
}, | ||
"globals": { | ||
"ts-jest": { | ||
"tsConfigFile": "tsconfig.json" | ||
} | ||
}, | ||
"testRegex": "(/src/.*(\\.|/)(test|spec))\\.(jsx?|tsx?)$", | ||
"testEnvironment": "node" | ||
} | ||
} |
125
README.md
@@ -1,21 +0,120 @@ | ||
# Demux | ||
# demux-js [![Build Status](https://travis-ci.org/EOSIO/demux-js.svg?branch=develop)](https://travis-ci.org/EOSIO/demux-js) | ||
Combine a bunch of streams into one. | ||
Demux is a backend infrastructure pattern for sourcing blockchain events to deterministically update queryable datastores and trigger side effects. This library serves as a reference implementation of that pattern for use with Node applications. | ||
```javascript | ||
var crdt = require('crdt'); | ||
var demux = require('demux'); | ||
## Installation | ||
var doc1 = new crdt.Doc; | ||
var doc2 = new crdt.Doc; | ||
var doc3 = new crdt.Doc; | ||
demux(doc1.createReadStream(), doc2.createReadStream()).pipe(doc3.createWriteStream()); | ||
```bash | ||
# Using yarn | ||
yarn add demux | ||
// Now doc1 and doc2 replicate to doc3, basiclly a master, master, slave scenario | ||
# Using npm | ||
npm install demux --save | ||
``` | ||
## Overview | ||
## Demux | ||
Taking inspiration from the [Flux Architecture](https://facebook.github.io/flux/docs/in-depth-overview.html#content) pattern and [Redux](https://github.com/reduxjs/redux/), Demux was born out of the following qualifications: | ||
### demux(stream...) | ||
Create one stream that all the other streams go into. | ||
1. A separation of concerns between how state exists on the blockchain and how it is queried by the client front-end | ||
1. Client front-end not solely responsible for determining derived, reduced, and/or accumulated state | ||
1. Ability for blockchain events to trigger new transactions, as well as other side effects outside of the blockchain | ||
1. The blockchain as the single source of truth for all application state | ||
### Separated Persistence Layer | ||
Storing data in indexed state on blockchains can be useful for three reasons: decentralized consensus of computation results, usage of state from within other blockchain computations, and for retrieval of state for use in client front-ends. When building more complicated front-ends, you run into a few problems when retrieving directly from indexed blockchain state: | ||
* The query interface used to retrieve the indexed data is limited. Complex data requirements can mean you either have to make an excess number of queries and process the data on the client, or you must store additional derivative data on the blockchain itself. | ||
* Scaling your query load means creating more blockchain endpoint nodes, which can be very expensive. | ||
Demux solves these problems by off-loading queries to any persistence layer that you want. As blockchain events happen, your chosen persistence layer is updated by `updater` functions, which deterministically process an array of `Action` objects. The persistence layer can then be queried by your front-end through a suitable API (for example, REST or GraphQL). | ||
This means that we can separate our concerns: for data that needs decentralized consensus of computation or access from other blockchain events, we can still store the data in indexed blockchain state, without having to worry about tailoring to front-end queries. For data required by our front-end, we can pre-process and index data in a way that makes it easy for it to be queried, in a horizontally scalable persistence layer of our choice. The end result is that both systems can serve their purpose more effectively. | ||
### Side Effects | ||
Since we have a system for acting upon specific blockchain events deterministically, we can utilize this system to manage non-deterministic events as well. These `effect` functions work almost exactly the same as `updater` functions, except they run asynchronously, are not run during replays, and modifying the deterministic datastore is off-limits. Examples include: signing and broadcasting a transaction, sending an email, and initiating a traditional fiat payment. | ||
### Single Source of Truth | ||
There are other solutions to the above problems that involve legacy persistence layers that are their own sources of truth. By deriving all state from the blockchain, however, we gain the following benefits: | ||
* If the accumulated datastore is lost or deleted, it may be regenerated by replaying blockchain actions | ||
* As long as application code is open source, and the blockchain is public, all application state can be audited | ||
* No need to maintain multiple ways of updating state (submitting transactions is the sole way) | ||
## Data Flow | ||
<img src='https://i.imgur.com/MFfGOe3.png' height='492' alt='Demux Logo' /> | ||
1. Client sends transaction to blockchain | ||
1. Action Watcher invokes Action Reader to check for new blocks | ||
1. Action Reader sees transaction in new block, parses actions | ||
1. Action Watcher sends actions to Action Handler | ||
1. Action Handler processes actions through Updaters and Effects | ||
1. Actions run their corresponding Updaters, updating the state of the Datastore | ||
1. Actions run their corresponding Effects, triggering external events | ||
1. Client queries API for updated data | ||
## Usage | ||
This library provides the following classes: | ||
* [**`AbstractActionReader`**](https://eosio.github.io/demux-js/classes/abstractactionreader.html): Abstract class used for implementing your own Action Readers | ||
* [**`AbstractActionHandler`**](https://eosio.github.io/demux-js/classes/abstractactionhandler.html): Abstract class used for implementing your own Action Handlers | ||
* [**`BaseActionWatcher`**](https://eosio.github.io/demux-js/classes/baseactionwatcher.html): Base class that implements a ready-to-use Action Watcher | ||
#### [**View full API documentation here.**](https://eosio.github.io/demux-js/) | ||
## Class Implementations | ||
Repository | Description | ||
---|--- | ||
[EOSIO / demux-js-eos](https://github.com/EOSIO/demux-js-eos) * | Action Reader implementations for EOSIO blockchains | ||
[EOSIO / demux-js-postgres](https://github.com/EOSIO/demux-js-postgres) * | Action Handler implementation for Postgres databases | ||
*\* Officially supported by Block.one* | ||
To get your project listed, add it here and submit a PR! | ||
## Example | ||
```js | ||
// Let's read from an EOS node | ||
const { NodeosActionReader } = require("demux-eos") | ||
// Assuming you've created your own subclass of AbstractActionHandler | ||
const MyActionHandler = require("./MyActionHandler") | ||
// Ties everything together in a polling loop | ||
const { BaseActionWatcher } = require("demux") | ||
// Import Updaters and Effects, which are arrays of objects: | ||
// [ { actionType: string, (updater|effect): function }, ... ] | ||
const updaters = require("./updaters") | ||
const effects = require("./effects") | ||
const actionReader = new NodeosActionReader( | ||
"http://some-nodeos-endpoint:8888", // Locally hosted node needed for reasonable indexing speed | ||
12345678, // First actions relevant to this dapp happen at this block | ||
) | ||
const actionHandler = new MyActionHandler( | ||
updaters, | ||
effects, | ||
) | ||
const actionWatcher = new BaseActionWatcher( | ||
actionReader, | ||
actionHandler, | ||
250, // Poll at twice the block interval for less latency | ||
) | ||
actionWatcher.watch() // Start watch loop | ||
``` | ||
For more complete examples, [see the examples directory](examples/). |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Trivial Package
Supply chain riskPackages less than 10 lines of code are easily copied into your own project and may not warrant the additional supply chain risk of an external dependency.
Found 1 instance in 1 package
No License Found
License(Experimental) License information could not be found.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
461110
0
32
0
563
1
121
13
1
2
- Removedthrough@~2.1.0
- Removedthrough@2.1.0(transitive)