mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-05-21 14:26:38 +00:00
Merge pull request #103 from haadcode/feat/ipfs-pubsub
Feature: IPFS Pubsub
This commit is contained in:
commit
ffb40dd50e
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,3 +7,6 @@ dump.rdb
|
||||
Vagrantfile
|
||||
orbit-db-cache.json
|
||||
examples/browser/bundle.js
|
||||
examples/browser/*.map
|
||||
dist/*.map
|
||||
dist/orbitdb.js
|
||||
|
4
CHANGELOG.md
Normal file
4
CHANGELOG.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Changelog
|
||||
|
||||
## v0.12.0
|
||||
- IPFS pubsub
|
263
README.md
263
README.md
@ -16,22 +16,15 @@ This is the Javascript implementation and it works both in **Node.js** and **Bro
|
||||
- Aggregation happens on client side and data is eventually consistent
|
||||
- Designed to work offline first
|
||||
|
||||
Check out a visualization of the data flow at https://github.com/haadcode/proto2
|
||||
**Node.js**
|
||||
|
||||
Live demo: http://celebdil.benet.ai:8080/ipfs/Qmezm7g8mBpWyuPk6D84CNcfLKJwU6mpXuEN5GJZNkX3XK/
|
||||
<img src="https://raw.githubusercontent.com/haadcode/orbit-db/feat/ipfs-pubsub/screenshots/orbit-db-demo3.gif" width="60%">
|
||||
|
||||

|
||||
**Browser**
|
||||
|
||||
**NOTE: the README can be out of date, I'm working to get up to date. If you find a problem, please open an issue or a PR.**
|
||||
<img src="https://raw.githubusercontent.com/haadcode/orbit-db/feat/ipfs-pubsub/screenshots/orbit-db-demo1.gif" height="60%">
|
||||
|
||||
_Currently requires [orbit-server](https://github.com/haadcode/orbit-server) for pubsub communication. This will change in the future as soon as IPFS provides pubsub._
|
||||
|
||||
## Install
|
||||
```
|
||||
npm install orbit-db
|
||||
```
|
||||
|
||||
## Data stores
|
||||
### Data stores
|
||||
|
||||
Currently available data stores:
|
||||
|
||||
@ -40,177 +33,145 @@ Currently available data stores:
|
||||
- [orbit-db-feedstore](https://github.com/haadcode/orbit-db-feedstore)
|
||||
- [orbit-db-counterstore](https://github.com/haadcode/orbit-db-counterstore)
|
||||
|
||||
## Install
|
||||
|
||||
From npm:
|
||||
```
|
||||
npm install orbit-db
|
||||
```
|
||||
|
||||
From git:
|
||||
```
|
||||
git clone https://github.com/haadcode/orbit-db.git
|
||||
cd orbit-db
|
||||
npm install
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
'use strict'
|
||||
|
||||
const IpfsApi = require('ipfs-api')
|
||||
const OrbitDB = require('orbit-db')
|
||||
const IPFS = require('ipfs')
|
||||
|
||||
OrbitDB.connect('178.62.241.75:3333', 'tester', null, new IPFS(), { allowOffline: true })
|
||||
.then((orbitdb) => {
|
||||
const kvstore = orbitdb.kvstore('db name')
|
||||
const events = orbitdb.eventlog('db name')
|
||||
const feed = orbitdb.feed('db name')
|
||||
const counters = orbitdb.counter('db name')
|
||||
const ipfs = IpfsApi('localhost', '5001')
|
||||
const orbitdb = new OrbitDB(ipfs)
|
||||
|
||||
kvstore.put('key1', 'hello1')
|
||||
.then(() => kvstore.get('key1'))
|
||||
.then((value) => console.log(value)) // 'hello!'
|
||||
const db = orbitdb.eventlog("feed name")
|
||||
|
||||
db.add("hello world")
|
||||
.then(() => {
|
||||
const latest = db.iterator({ limit: 5 }).collect()
|
||||
console.log(latest.join("\n"))
|
||||
})
|
||||
```
|
||||
|
||||
Documentation for individual stores are WIP, please see each store's source code for available public methods.
|
||||
|
||||
## Examples
|
||||
|
||||
*To run the examples below, make sure to run a local [orbit-server](https://github.com/haadcode/orbit-server)*
|
||||
### Browser example
|
||||
|
||||
### Browser examples
|
||||
Build the examples:
|
||||
```bash
|
||||
npm install
|
||||
npm run build:examples
|
||||
npm run examples:browser
|
||||
```
|
||||
|
||||
Then open `examples/browser.html` or `examples/index.html`. See the full example [here](https://github.com/haadcode/orbit-db/blob/master/examples/browser/browser.html).
|
||||
### Node.js example
|
||||
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript" src="../dist/orbitdb.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="../node_modules/logplease/dist/logplease.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="../node_modules/ipfs/dist/index.min.js" charset="utf-8"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
const ipfs = window.Ipfs();
|
||||
OrbitDB.connect('localhost:3333', 'user1', '', ipfs)
|
||||
.then((orbit) => orbit.kvstore('test'))
|
||||
.then((db) => db.put('hello', 'world'))
|
||||
.then((res) => {
|
||||
const result = db.get(key)
|
||||
console.log(result)
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### Node.js examples
|
||||
|
||||
Before running the examples, install dependencies with:
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
Key-Value store [example](https://github.com/haadcode/orbit-db/blob/master/examples/keyvalue.js):
|
||||
```
|
||||
node examples/keyvalue.js <host:port> <username> <channel> <key> <value>
|
||||
```
|
||||
|
||||
Event log [example](https://github.com/haadcode/orbit-db/blob/master/examples/eventlog.js) (run several in separate shells):
|
||||
```
|
||||
node examples/eventlog.js <host:port> <username> <channel> <data> <interval in ms>
|
||||
```
|
||||
|
||||
Benchmark writes:
|
||||
```bash
|
||||
node examples/benchmark.js <host:port> <username> <channel>;
|
||||
npm install
|
||||
npm run examples:node
|
||||
```
|
||||
|
||||
See detailed [example](https://github.com/haadcode/orbit-db/blob/master/examples/eventlog.js) and run it with:
|
||||
```bash
|
||||
node examples/eventlog.js
|
||||
```
|
||||
|
||||
```javascript
|
||||
'use strict'
|
||||
|
||||
const IpfsDaemon = require('ipfs-daemon')
|
||||
const OrbitDB = require('orbit-db')
|
||||
|
||||
IpfsDaemon()
|
||||
.then((res) => {
|
||||
const orbitdb = new OrbitDB(res.ipfs)
|
||||
const db = orbitdb.eventlog("|orbit-db|examples|eventlog-example")
|
||||
|
||||
const creatures = ['🐙', '🐷', '🐬', '🐞', '🐈', '🙉', '🐸', '🐓']
|
||||
|
||||
const query = () => {
|
||||
const index = Math.floor(Math.random() * creatures.length)
|
||||
db.add(creatures[index])
|
||||
.then(() => {
|
||||
const latest = db.iterator({ limit: 5 }).collect()
|
||||
let output = ``
|
||||
output += `---------------------------------------------------\n`
|
||||
output += `Latest Visitors\n`
|
||||
output += `---------------------------------------------------\n`
|
||||
output += latest.reverse().map((e) => e.payload.value).join('\n') + `\n`
|
||||
console.log(output)
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e.stack)
|
||||
})
|
||||
}
|
||||
|
||||
setInterval(query, 1000)
|
||||
})
|
||||
.catch((err) => console.error(err))
|
||||
```
|
||||
|
||||
## API
|
||||
**NOTE: the API documentation is currently out of date. It will be updated soon!**
|
||||
|
||||
_See usage example below_
|
||||
**TODO**
|
||||
|
||||
_OrbitDB calls its namespaces channels. A channel is similar to "table", "keyspace", "topic", "feed" or "collection" in other db systems._
|
||||
- [orbit-db-kvstore](https://github.com/haadcode/orbit-db-kvstore)
|
||||
- put(key, value)
|
||||
- set(key, value)
|
||||
- get(key)
|
||||
- [orbit-db-eventstore](https://github.com/haadcode/orbit-db-eventstore)
|
||||
- add(value)
|
||||
- get(hash)
|
||||
- iterator(options)
|
||||
- [orbit-db-feedstore](https://github.com/haadcode/orbit-db-feedstore)
|
||||
- add(value)
|
||||
- del(hash)
|
||||
- get(hash)
|
||||
- iterator(options)
|
||||
- [orbit-db-counterstore](https://github.com/haadcode/orbit-db-counterstore)
|
||||
- inc([value])
|
||||
|
||||
connect(<host:port>, username, password)
|
||||
|
||||
channel(name, password)
|
||||
|
||||
.add(data: String) // Insert an event to a channel, returns <ipfs-hash> of the event
|
||||
|
||||
.iterator([options]) // Returns an iterator of events
|
||||
|
||||
// options : {
|
||||
// gt: <ipfs-hash>, // Return events newer than <ipfs-hash>
|
||||
// gte: <ipfs-hash>, // Return events newer then <ipfs-hash> (inclusive)
|
||||
// lt: <ipfs-hash>, // Return events older than <ipfs-hash>
|
||||
// lte: <ipfs-hash>, // Return events older than <ipfs-hash> (inclusive)
|
||||
// limit: -1, // Number of events to return, -1 returns all, default 1
|
||||
// reverse: true // Return items oldest first, default latest first
|
||||
// }
|
||||
|
||||
.put(key, data: String) // Insert (key,value) to a channel
|
||||
|
||||
.get(key) // Retrieve value
|
||||
|
||||
.del({ key: <key or hash> }) // Remove entry
|
||||
|
||||
.delete() // Deletes the channel, all data will be "removed" (unassociated with the channel, actual data is not deleted from ipfs)
|
||||
|
||||
## Usage
|
||||
```javascript
|
||||
const async = require('asyncawait/async');
|
||||
const ipfsAPI = require('ipfs-api');
|
||||
const OrbitDB = require('orbit-db');
|
||||
|
||||
// local ipfs daemon
|
||||
const ipfs = ipfsAPI();
|
||||
|
||||
async(() => {
|
||||
// Connect
|
||||
const orbit = await(OrbitClient.connect('localhost:3333', 'usernamne', '', ipfs));
|
||||
|
||||
/* Event Log */
|
||||
const eventlog = orbit.eventlog('eventlog test');
|
||||
const hash = await(eventlog.add('hello')); // <ipfs-hash>
|
||||
|
||||
// Remove event
|
||||
await(eventlog.remove(hash));
|
||||
|
||||
// Iterator options
|
||||
const options = { limit: -1 }; // fetch all messages
|
||||
|
||||
// Get events
|
||||
const iter = eventlog.iterator(options); // Symbol.iterator
|
||||
const next = iter.next(); // { value: <item>, done: false|true}
|
||||
|
||||
// OR:
|
||||
// var all = iter.collect(); // returns all elements as an array
|
||||
|
||||
// OR:
|
||||
// for(let i of iter)
|
||||
// console.log(i.hash, i.item);
|
||||
|
||||
/* Delete database locally */
|
||||
eventlog.delete();
|
||||
|
||||
/* KV Store */
|
||||
const kvstore = orbit.kvstore('kv test');
|
||||
await(kvstore.put('key1', 'hello world'));
|
||||
kvstore.get('key1'); // returns "hello world"
|
||||
await(kvstore.del('key1'));
|
||||
})();
|
||||
```
|
||||
|
||||
### Development
|
||||
## Development
|
||||
|
||||
#### Run Tests
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
Keep tests running while development:
|
||||
```bash
|
||||
mocha -w
|
||||
```
|
||||
|
||||
#### Build distributables
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Background
|
||||
|
||||
**TODO**
|
||||
|
||||
Check out a visualization of the data flow at https://github.com/haadcode/proto2
|
||||
|
||||
Live demo: http://celebdil.benet.ai:8080/ipfs/Qmezm7g8mBpWyuPk6D84CNcfLKJwU6mpXuEN5GJZNkX3XK/
|
||||
|
||||

|
||||
|
||||
**TODO: list of modules used, orbit-db-pubsub, etc.**
|
||||
|
||||
## Contributing
|
||||
|
||||
**TODO**
|
||||
|
||||
## License
|
||||
|
||||
MIT ©️ 2016, Haadcode
|
||||
|
@ -1,8 +1,3 @@
|
||||
machine:
|
||||
node:
|
||||
version: 4.3.1
|
||||
services:
|
||||
- redis
|
||||
dependencies:
|
||||
pre:
|
||||
- npm install -g npm@3.x.x
|
||||
version: 6.1.0
|
||||
|
42646
dist/orbitdb.js
vendored
42646
dist/orbitdb.js
vendored
File diff suppressed because it is too large
Load Diff
68
dist/orbitdb.min.js
vendored
68
dist/orbitdb.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,107 +0,0 @@
|
||||
***WIP***
|
||||
|
||||
### Structure
|
||||
The database has one log (OrbitList) for each *channel*. *Channel* is comparable to a *"topic"* or *"table"*.
|
||||
|
||||
```
|
||||
DB
|
||||
|-- channel 1
|
||||
| |-- list 1
|
||||
| | |-- node 1
|
||||
| | |-- operation
|
||||
| | |-- value
|
||||
| |-- list 2
|
||||
|-- channel 2
|
||||
|-- list 3
|
||||
...
|
||||
```
|
||||
|
||||
### Operation Logs
|
||||
- Each *channel* is saved as a log of operations: add, put, del
|
||||
- Operations are stored in an append-only log linked list
|
||||
- Each node in the linked list points to the previous node
|
||||
- Event log: take latest add or del operation for <hash>
|
||||
- JV-store: take last put or del operation for <key>
|
||||
|
||||
### CRDTs
|
||||
- orbit-db is a CmRDT and implements an LWW-element-set
|
||||
- Operation-based CRDT
|
||||
- Uses Merkle Trees for partial ordering
|
||||
|
||||
### add/put IO:
|
||||
==> Not expensive
|
||||
|
||||
1. Create POST for the content
|
||||
`ipfs object get QmZzic86oN7B5GMMYnTFvZMyDMjkKEBXe5SYsryXPeoGdb?`
|
||||
```json
|
||||
{
|
||||
"content": "hello 1",
|
||||
"ts": 1457703735759,
|
||||
"meta": {
|
||||
"type": "text",
|
||||
"size": 7,
|
||||
"ts": 1457703735759
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. Create POST for the DB operation
|
||||
`ipfs object get QmZzBNrUiYATJ4aicPTbupnEUWH3AHDmfBbDTQK3fhhYDE`
|
||||
```json
|
||||
{
|
||||
"op": "ADD",
|
||||
"key": "QmZzic86oN7B5GMMYnTFvZMyDMjkKEBXe5SYsryXPeoGdb",
|
||||
"value": "QmZzic86oN7B5GMMYnTFvZMyDMjkKEBXe5SYsryXPeoGdb",
|
||||
"meta": {
|
||||
"type": "orbit-db-op",
|
||||
"size": 15,
|
||||
"ts": 1457703735779
|
||||
},
|
||||
"by": "userA"
|
||||
}
|
||||
```
|
||||
|
||||
3. Create ipfs object for the nodet
|
||||
`ipfs object get QmX2Jq1JHmgjgM3YVuHyGSRpUWMDbv4PuRhqBhsZqDmagD`
|
||||
```json
|
||||
{
|
||||
"id": "userA",
|
||||
"seq": 0,
|
||||
"ver": 1,
|
||||
"data": "QmZzBNrUiYATJ4aicPTbupnEUWH3AHDmfBbDTQK3fhhYDE",
|
||||
"next": {
|
||||
"userA.0.0": "QmXUTgYPG4cSaHW8dKggJRfLvPWjaDktWyRAgn5NPwTqtz"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. Create ipfs object for the current list
|
||||
`ipfs object get Qmb2rpex9TdmoXvwLKLL24atWa2HfPbArobN7XiBAFvmZ9`
|
||||
```json
|
||||
{
|
||||
"id": "userA",
|
||||
"seq": 1,
|
||||
"ver": 0,
|
||||
"items": {
|
||||
"userA.0.0": "QmXUTgYPG4cSaHW8dKggJRfLvPWjaDktWyRAgn5NPwTqtz",
|
||||
"userA.0.1": "QmX2Jq1JHmgjgM3YVuHyGSRpUWMDbv4PuRhqBhsZqDmagD"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
5. Pubsub.publish (send to socket, network IO)
|
||||
```json
|
||||
{
|
||||
channel: '<channel name>',
|
||||
hash: 'Qmb2rpex9TdmoXvwLKLL24atWa2HfPbArobN7XiBAFvmZ9'
|
||||
}
|
||||
```
|
||||
|
||||
### get IO:
|
||||
==> A little expensive
|
||||
|
||||
1. Payload (get from ipfs-hash, network IO)
|
||||
|
||||
### sync/merge IO:
|
||||
==> Expensive!
|
||||
TODO
|
141
docs/ordering.md
141
docs/ordering.md
@ -1,141 +0,0 @@
|
||||
# Odering in OrbitList
|
||||
|
||||
Ordering in OrbitList is done with Interval Tree Clocks (https://github.com/ricardobcl/Interval-Tree-Clocks). Each node tracks a global sequence *seq* and a local version *ver*. When an item is added to a list, local version *ver* is increased by 1. Whenever a list is *joined* with another list (eg. upon sync), the global sequence *seq* is set to *Max(global.seq, local.seq)*. When adding an item to the list, the item has a reference to all *heads* where *head* is an item that is not referenced by any other item in the list.
|
||||
|
||||
### Graph
|
||||
```
|
||||
A B C
|
||||
|
||||
0.0
|
||||
|
|
||||
0.0 0.1
|
||||
| |
|
||||
0.1 0.2
|
||||
\ / <--- Sync B with A and C
|
||||
1.0
|
||||
|
|
||||
1.1
|
||||
/ <--- Sync A with B
|
||||
2.0
|
||||
\
|
||||
\ <--- Sync C with A
|
||||
\
|
||||
3.0
|
||||
<--- Sync ALL
|
||||
```
|
||||
|
||||
### Evolution of the state
|
||||
Initial state:
|
||||
```
|
||||
A = []
|
||||
B = []
|
||||
C = []
|
||||
```
|
||||
|
||||
***Two nodes add events concurrently***
|
||||
|
||||
Add items to A:
|
||||
```
|
||||
listA.add("mango")
|
||||
listA.add("banana")
|
||||
|
||||
// "A": [
|
||||
// { "id": "A", "seq": 0, "ver": 0, "prev": null}
|
||||
// { "id": "A", "seq": 0, "ver": 1, "prev": ["A.0.0"]}
|
||||
// ]
|
||||
```
|
||||
|
||||
Add items to C:
|
||||
```
|
||||
listC.add("apple")
|
||||
listC.add("strawberry")
|
||||
listC.add("orange")
|
||||
|
||||
// "C": [
|
||||
// { "id": "C", "seq": 0, "ver": 0, "prev": null}
|
||||
// { "id": "C", "seq": 0, "ver": 1, "prev": ["C.0.0"]}
|
||||
// { "id": "C", "seq": 0, "ver": 2, "prev": ["C.0.1"]}
|
||||
// ]
|
||||
```
|
||||
|
||||
B receives a 'sync' from A and C:
|
||||
```
|
||||
B.join(A)
|
||||
B.join(C)
|
||||
```
|
||||
|
||||
Add items to B:
|
||||
```
|
||||
listB.add("pineapple")
|
||||
listB.add("papaya")
|
||||
|
||||
// "B": [
|
||||
// { "id": "A", "seq": 0, "ver": 0, "prev": null}
|
||||
// { "id": "A", "seq": 0, "ver": 1, "prev": ["A.0.0"]}
|
||||
// { "id": "C", "seq": 0, "ver": 0, "prev": null}
|
||||
// { "id": "C", "seq": 0, "ver": 1, "prev": ["C.0.0"]}
|
||||
// { "id": "C", "seq": 0, "ver": 2, "prev": ["C.0.1"]}
|
||||
// { "id": "B", "seq": 1, "ver": 0, "prev": ["A.0.1", "C.0.2"]}
|
||||
// { "id": "B", "seq": 1, "ver": 1, "prev": ["B.1.0"]}
|
||||
// ]
|
||||
```
|
||||
|
||||
A receives a 'sync' from B:
|
||||
```
|
||||
A.join(B)
|
||||
```
|
||||
|
||||
```
|
||||
listA.add("kiwi")
|
||||
|
||||
// "A": [
|
||||
// { "id": "A", "seq": 0, "ver": 0, "prev": null}
|
||||
// { "id": "A", "seq": 0, "ver": 1, "prev": ["A.0.0"]}
|
||||
// { "id": "C", "seq": 0, "ver": 0, "prev": null}
|
||||
// { "id": "C", "seq": 0, "ver": 1, "prev": ["C.0.0"]}
|
||||
// { "id": "C", "seq": 0, "ver": 2, "prev": ["C.0.1"]}
|
||||
// { "id": "B", "seq": 1, "ver": 0, "prev": ["A.0.1", "C.0.2"]}
|
||||
// { "id": "B", "seq": 1, "ver": 1, "prev": ["B.1.0"]}
|
||||
// { "id": "A", "seq": 2, "ver": 0, "prev": ["B.1.1"]}
|
||||
// ]
|
||||
```
|
||||
|
||||
C receives a 'sync' from A:
|
||||
```
|
||||
C.join(A)
|
||||
```
|
||||
|
||||
```
|
||||
listC.add("blueberry")
|
||||
|
||||
// "C": [
|
||||
// { "id": "A", "seq": 0, "ver": 0, "prev": null}
|
||||
// { "id": "A", "seq": 0, "ver": 1, "prev": ["A.0.0"]}
|
||||
// { "id": "C", "seq": 0, "ver": 0, "prev": null}
|
||||
// { "id": "C", "seq": 0, "ver": 1, "prev": ["C.0.0"]}
|
||||
// { "id": "C", "seq": 0, "ver": 2, "prev": ["C.0.1"]}
|
||||
// { "id": "B", "seq": 1, "ver": 0, "prev": ["A.0.1", "C.0.2"]}
|
||||
// { "id": "B", "seq": 1, "ver": 1, "prev": ["B.1.0"]}
|
||||
// { "id": "A", "seq": 2, "ver": 0, "prev": ["B.1.1"]}
|
||||
// { "id": "C", "seq": 3, "ver": 0, "prev": ["A.2.0"]}
|
||||
// ]
|
||||
```
|
||||
|
||||
A receives a 'sync' from C, B receives a 'sync' from C:
|
||||
```
|
||||
A.join(C)
|
||||
B.join(C)
|
||||
```
|
||||
|
||||
Converged data set:
|
||||
```json
|
||||
{ "id": "A", "seq": 0, "ver": 0, "prev": null},
|
||||
{ "id": "A", "seq": 0, "ver": 1, "prev": ["A.0.0"]},
|
||||
{ "id": "C", "seq": 0, "ver": 0, "prev": null},
|
||||
{ "id": "C", "seq": 0, "ver": 1, "prev": ["C.0.0"]},
|
||||
{ "id": "C", "seq": 0, "ver": 2, "prev": ["C.0.1"]},
|
||||
{ "id": "B", "seq": 1, "ver": 0, "prev": ["A.0.1", "C.0.2"]},
|
||||
{ "id": "B", "seq": 1, "ver": 1, "prev": ["B.1.0"]}
|
||||
{ "id": "A", "seq": 2, "ver": 0, "prev": ["B.1.1"]}
|
||||
{ "id": "C", "seq": 3, "ver": 0, "prev": ["A.2.0]"]}
|
||||
```
|
@ -1,19 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
class Timer {
|
||||
constructor(startImmediately) {
|
||||
this.startTime = startImmediately ? new Date().getTime() : null;
|
||||
this.endTime = null;
|
||||
}
|
||||
|
||||
start() {
|
||||
this.startTime = new Date().getTime();
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.endTime = new Date().getTime();
|
||||
return (this.endTime - this.startTime);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Timer;
|
@ -1,89 +1,49 @@
|
||||
'use strict';
|
||||
'use strict'
|
||||
|
||||
// const ipfsd = require('ipfsd-ctl');
|
||||
const IPFS = require('ipfs')
|
||||
const ipfsd = require('ipfsd-ctl');
|
||||
const OrbitDB = require('../src/OrbitDB');
|
||||
const Timer = require('./Timer');
|
||||
const IpfsApi = require('ipfs-api')
|
||||
const OrbitDB = require('../src/OrbitDB')
|
||||
|
||||
// usage: benchmark.js <network hash> <username> <channel>;
|
||||
|
||||
// orbit-server
|
||||
const network = 'localhost:3333';
|
||||
const username = process.argv[2] ? process.argv[2] : 'testrunner';
|
||||
const password = '';
|
||||
const channelName = process.argv[3] ? process.argv[3] : 'c1';
|
||||
|
||||
const startIpfs = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ipfsd.disposableApi((err, ipfs) => {
|
||||
if(err) console.error(err);
|
||||
resolve(ipfs);
|
||||
});
|
||||
// ipfsd.local((err, node) => {
|
||||
// if(err) reject(err);
|
||||
// node.startDaemon((err, ipfs) => {
|
||||
// if(err) reject(err);
|
||||
// resolve(ipfs);
|
||||
// });
|
||||
// });
|
||||
// const ipfs = new IPFS('/tmp/benchmark')
|
||||
// ipfs.goOnline(() => {
|
||||
// resolve(ipfs)
|
||||
// })
|
||||
});
|
||||
};
|
||||
|
||||
const util = require('util');
|
||||
const username = process.argv[2] ? process.argv[2] : 'testrunner'
|
||||
const channelName = process.argv[3] ? process.argv[3] : 'c1'
|
||||
|
||||
// Metrics
|
||||
let totalQueries = 0;
|
||||
let seconds = 0;
|
||||
let queriesPerSecond = 0;
|
||||
let lastTenSeconds = 0;
|
||||
let store;
|
||||
let totalQueries = 0
|
||||
let seconds = 0
|
||||
let queriesPerSecond = 0
|
||||
let lastTenSeconds = 0
|
||||
|
||||
// Main loop
|
||||
const queryLoop = (db) => {
|
||||
// let timer = new Timer();
|
||||
// timer.start();
|
||||
db.add(username + totalQueries).then(() => {
|
||||
// console.log(`${timer.stop(true)} ms - ${process._getActiveRequests().length} ${process._getActiveHandles().length}`);
|
||||
// console.log(util.inspect(process.memoryUsage()));
|
||||
totalQueries ++;
|
||||
lastTenSeconds ++;
|
||||
queriesPerSecond ++;
|
||||
process.nextTick(() => queryLoop(db));
|
||||
});
|
||||
};
|
||||
totalQueries ++
|
||||
lastTenSeconds ++
|
||||
queriesPerSecond ++
|
||||
process.nextTick(() => queryLoop(db))
|
||||
})
|
||||
}
|
||||
|
||||
let run = (() => {
|
||||
// Connect
|
||||
console.log(`Connecting...`)
|
||||
startIpfs()
|
||||
.then((ipfs) => OrbitDB.connect(network, username, password, ipfs))
|
||||
.then((orbit) => orbit.eventlog(channelName))
|
||||
.then((db) => {
|
||||
|
||||
queryLoop(db);
|
||||
const ipfs = IpfsApi('localhost', '5001')
|
||||
const orbit = new OrbitDB(ipfs, 'benchmark')
|
||||
const db = orbit.eventlog(channelName)
|
||||
|
||||
// Metrics output
|
||||
setInterval(() => {
|
||||
seconds ++;
|
||||
seconds ++
|
||||
if(seconds % 10 === 0) {
|
||||
console.log(`--> Average of ${lastTenSeconds/10} q/s in the last 10 seconds`);
|
||||
console.log(`--> Average of ${lastTenSeconds/10} q/s in the last 10 seconds`)
|
||||
if(lastTenSeconds === 0)
|
||||
throw new Error("Problems!");
|
||||
lastTenSeconds = 0;
|
||||
throw new Error("Problems!")
|
||||
lastTenSeconds = 0
|
||||
}
|
||||
console.log(`${queriesPerSecond} queries per second, ${totalQueries} queries in ${seconds} seconds`);
|
||||
queriesPerSecond = 0;
|
||||
}, 1000);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("error:", e);
|
||||
console.error(e.stack);
|
||||
process.exit(1);
|
||||
})
|
||||
})();
|
||||
console.log(`${queriesPerSecond} queries per second, ${totalQueries} queries in ${seconds} seconds`)
|
||||
queriesPerSecond = 0
|
||||
}, 1000)
|
||||
|
||||
module.exports = run;
|
||||
// Start
|
||||
queryLoop(db)
|
||||
})()
|
||||
|
||||
module.exports = run
|
||||
|
@ -6,10 +6,8 @@
|
||||
<div id="result">Loading...</div>
|
||||
|
||||
<script type="text/javascript" src="../../dist/orbitdb.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="../../node_modules/logplease/dist/logplease.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="../../node_modules/ipfs/dist/index.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript">
|
||||
const logger = Logger.create("orbit-db example", { color: Logger.Colors.Green, showTimestamp: false, showLevel: false })
|
||||
const network = '178.62.241.75:3333'
|
||||
const username = 'user1'
|
||||
const password = ''
|
||||
@ -26,7 +24,7 @@
|
||||
const startTime = new Date().getTime()
|
||||
db.put(key, value + " " + count).then((res) => {
|
||||
const endTime = new Date().getTime()
|
||||
logger.debug(`db.put (#${count}) took ${(endTime - startTime)} ms\n`)
|
||||
console.log(`db.put (#${count}) took ${(endTime - startTime)} ms\n`)
|
||||
count ++
|
||||
|
||||
const result = db.get(key)
|
||||
@ -38,12 +36,12 @@
|
||||
---------------------------------------------------`
|
||||
|
||||
elm.innerHTML = output.split("\n").join("<br>")
|
||||
logger.debug(output)
|
||||
}).catch((e) => logger.error(e))
|
||||
console.log(output)
|
||||
}).catch((e) => console.error(e))
|
||||
};
|
||||
setInterval(query, 1000)
|
||||
}).catch((e) => logger.error(e))
|
||||
}).catch((e) => logger.error(e))
|
||||
}).catch((e) => console.error(e))
|
||||
}).catch((e) => console.error(e))
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,45 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const IPFS = require('exports?Ipfs!ipfs/dist/index.js')
|
||||
const Logger = require('logplease')
|
||||
const logger = Logger.create("orbit-db example", { color: Logger.Colors.Green, showTimestamp: false, showLevel: false })
|
||||
const OrbitDB = require('../../src/OrbitDB')
|
||||
|
||||
const network = '178.62.241.75:3333'
|
||||
const username = 'user1'
|
||||
const password = ''
|
||||
const channel = 'browsertest1'
|
||||
const key = 'greeting'
|
||||
const value = 'Hello world'
|
||||
|
||||
try {
|
||||
const elm = document.getElementById("result")
|
||||
const ipfs = new IPFS()
|
||||
OrbitDB.connect(network, username, password, ipfs).then((orbit) => {
|
||||
orbit.kvstore(channel).then((db) => {
|
||||
let count = 1
|
||||
const query = () => {
|
||||
const startTime = new Date().getTime()
|
||||
db.put(key, value + " " + count).then((res) => {
|
||||
const endTime = new Date().getTime()
|
||||
logger.debug(`db.put (#${count}) took ${(endTime - startTime)} ms\n`)
|
||||
count ++
|
||||
|
||||
const result = db.get(key)
|
||||
const output = `
|
||||
---------------------------------------------------
|
||||
Key | Value
|
||||
---------------------------------------------------
|
||||
${key} | ${result}
|
||||
---------------------------------------------------`
|
||||
|
||||
elm.innerHTML = output.split("\n").join("<br>")
|
||||
logger.debug(output)
|
||||
}).catch((e) => logger.error(e.stack))
|
||||
}
|
||||
setInterval(query, 1000)
|
||||
})
|
||||
})
|
||||
} catch(e) {
|
||||
logger.error(e.stack)
|
||||
}
|
71
examples/browser/index.js
Normal file
71
examples/browser/index.js
Normal file
@ -0,0 +1,71 @@
|
||||
'use strict'
|
||||
|
||||
const IpfsApi = require('exports?IpfsApi!ipfs-api/dist/index.js')
|
||||
const OrbitDB = require('../../src/OrbitDB')
|
||||
|
||||
const username = new Date().getTime()
|
||||
const channel = 'browser-example'
|
||||
const key = 'greeting'
|
||||
|
||||
try {
|
||||
const elm = document.getElementById("result")
|
||||
const ipfs = IpfsApi('localhost', '5001')
|
||||
const orbit = new OrbitDB(ipfs, username)
|
||||
|
||||
const db = orbit.kvstore(channel)
|
||||
const log = orbit.eventlog(channel + ".log")
|
||||
const counter = orbit.counter(channel + ".count")
|
||||
|
||||
const creatures = ['👻', '🐙', '🐷', '🐬', '🐞', '🐈', '🙉', '🐸', '🐓']
|
||||
|
||||
let count = 1
|
||||
const query = () => {
|
||||
const startTime = new Date().getTime()
|
||||
const idx = Math.floor(Math.random() * creatures.length)
|
||||
|
||||
// Set a key-value pair
|
||||
db.put(key, "db.put #" + count + " - GrEEtinGs to " + creatures[idx])
|
||||
.then((res) => {
|
||||
const endTime = new Date().getTime()
|
||||
console.log(`db.put (#${count}) took ${(endTime - startTime)} ms\n`)
|
||||
count ++
|
||||
})
|
||||
.then(() => counter.inc()) // Increase the counter by one
|
||||
.then(() => log.add(creatures[idx])) // Add an event to 'latest visitors' log
|
||||
.then(() => {
|
||||
const result = db.get(key)
|
||||
const latest = log.iterator({ limit: 5 }).collect()
|
||||
const count = counter.value()
|
||||
|
||||
const output =
|
||||
`<b>Key-Value Store</b>
|
||||
---------------------------------------------------
|
||||
Key | Value
|
||||
---------------------------------------------------
|
||||
${key} | ${result}
|
||||
---------------------------------------------------
|
||||
|
||||
<b>Eventlog</b>
|
||||
---------------------------------------------------
|
||||
Latest Visitors
|
||||
---------------------------------------------------
|
||||
${latest.reverse().map((e) => e.payload.value + " (" + e.payload.from + ") at" + new Date(e.payload.meta.ts).toISOString()).join('\n')}
|
||||
|
||||
<b>Counter</b>
|
||||
---------------------------------------------------
|
||||
Visitor Count: ${count}
|
||||
---------------------------------------------------
|
||||
`
|
||||
elm.innerHTML = output.split("\n").join("<br>")
|
||||
})
|
||||
.catch((e) => {
|
||||
elm.innerHTML = "<i>" + e.message + "</i><br><br>" + "Make sure you have an IPFS daemon running at localhost:5001"
|
||||
console.error(e.stack)
|
||||
})
|
||||
}
|
||||
setInterval(query, 1000)
|
||||
|
||||
} catch(e) {
|
||||
console.error(e.stack)
|
||||
elm.innerHTML = e.message
|
||||
}
|
@ -9,7 +9,7 @@ const Timer = require('./Timer');
|
||||
// usage: reader.js <network hash> <username> <channel> <interval in ms>
|
||||
|
||||
// orbit-server
|
||||
const network = 'QmYPobvobKsyoCKTw476yTui611XABf927KxUPCf4gRLRr'; // 'localhost:3333'
|
||||
const network = '178.62.241.75:3333'; // 'localhost:3333'
|
||||
const username = process.argv[2] ? process.argv[2] : 'testrunner';
|
||||
const password = '';
|
||||
const channelName = process.argv[3] ? process.argv[3] : 'c2';
|
||||
@ -28,7 +28,7 @@ let run = (async(() => {
|
||||
try {
|
||||
const ipfs = await(startIpfs());
|
||||
const orbit = await(OrbitDB.connect(network, username, password, ipfs));
|
||||
const db = await(orbit.eventlog(channelName));
|
||||
const db = orbit.eventlog(channelName);
|
||||
|
||||
let count = 1;
|
||||
let running = false;
|
||||
@ -42,7 +42,7 @@ let run = (async(() => {
|
||||
console.log("---------------------------------------------------")
|
||||
console.log("Timestamp | Value")
|
||||
console.log("---------------------------------------------------")
|
||||
console.log(items.map((e) => `${e.meta.ts} | ${e.value}`).join("\n"));
|
||||
console.log(items.map((e) => `${e.payload.meta.ts} | ${e.payload.value}`).join("\n"));
|
||||
console.log("---------------------------------------------------")
|
||||
console.log(`Query #${count} took ${timer2.stop(true)} ms\n`);
|
||||
|
||||
|
@ -1,65 +1,42 @@
|
||||
'use strict';
|
||||
'use strict'
|
||||
|
||||
const async = require('asyncawait/async');
|
||||
const await = require('asyncawait/await');
|
||||
const ipfsd = require('ipfsd-ctl');
|
||||
const OrbitDB = require('../src/OrbitDB');
|
||||
const Timer = require('./Timer');
|
||||
const IpfsDaemon = require('ipfs-daemon')
|
||||
const OrbitDB = require('../src/OrbitDB')
|
||||
|
||||
// usage: reader.js <network hash> <username> <channel> <data> <interval in ms>
|
||||
const userId = Math.floor(Math.random() * 100)
|
||||
const conf = {
|
||||
IpfsDataDir: '/tmp/' + userId,
|
||||
Addresses: {
|
||||
API: '/ip4/127.0.0.1/tcp/0',
|
||||
Swarm: ['/ip4/0.0.0.0/tcp/0'],
|
||||
Gateway: '/ip4/0.0.0.0/tcp/0'
|
||||
},
|
||||
}
|
||||
|
||||
// orbit-server
|
||||
const network = 'QmYPobvobKsyoCKTw476yTui611XABf927KxUPCf4gRLRr'; // 'localhost:3333'
|
||||
const username = process.argv[2] ? process.argv[2] : 'testrunner';
|
||||
const password = '';
|
||||
const channelName = process.argv[3] ? process.argv[3] : 'c2';
|
||||
const prefix = process.argv[4] ? process.argv[4] : 'Hello';
|
||||
IpfsDaemon(conf)
|
||||
.then((res) => {
|
||||
const orbitdb = new OrbitDB(res.ipfs)
|
||||
const db = orbitdb.eventlog("|orbit-db|examples|eventlog-example")
|
||||
|
||||
const startIpfs = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ipfsd.disposableApi((err, ipfs) => {
|
||||
if(err) console.error(err);
|
||||
resolve(ipfs);
|
||||
});
|
||||
});
|
||||
};
|
||||
const creatures = ['🐙', '🐷', '🐬', '🐞', '🐈', '🙉', '🐸', '🐓']
|
||||
|
||||
let run = (async(() => {
|
||||
try {
|
||||
const ipfs = await(startIpfs());
|
||||
const orbit = await(OrbitDB.connect(network, username, password, ipfs));
|
||||
const db = await(orbit.eventlog(channelName));
|
||||
|
||||
let count = 1;
|
||||
let running = false;
|
||||
|
||||
setInterval(async(() => {
|
||||
if(!running) {
|
||||
running = true;
|
||||
|
||||
let timer = new Timer(true);
|
||||
await(db.add(prefix + count));
|
||||
console.log(`Query #${count} took ${timer.stop(true)} ms\n`);
|
||||
|
||||
let timer2 = new Timer(true);
|
||||
let items = db.iterator({ limit: -1 }).collect();
|
||||
console.log("----------------------------------------------------------------------------------------")
|
||||
console.log("Hash | Timestamp | Value")
|
||||
console.log("----------------------------------------------------------------------------------------")
|
||||
console.log(items.map((e) => `${e.hash} | ${e.meta.ts} | ${e.value}`).join("\n"));
|
||||
console.log("----------------------------------------------------------------------------------------")
|
||||
console.log(`Query 2 #${count} took ${timer2.stop(true)} ms\n`);
|
||||
|
||||
running = false;
|
||||
count ++;
|
||||
const query = () => {
|
||||
const index = Math.floor(Math.random() * creatures.length)
|
||||
db.add({ avatar: creatures[index], userId: userId })
|
||||
.then(() => {
|
||||
const latest = db.iterator({ limit: 5 }).collect()
|
||||
let output = ``
|
||||
output += `--------------------\n`
|
||||
output += `Latest Visitors\n`
|
||||
output += `--------------------\n`
|
||||
output += latest.reverse().map((e) => e.payload.value.avatar + " (userId: " + e.payload.value.userId + ")").join('\n') + `\n`
|
||||
console.log(output)
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e.stack)
|
||||
})
|
||||
}
|
||||
}), process.argv[6] ? process.argv[6] : 1000);
|
||||
|
||||
} catch(e) {
|
||||
console.error(e.stack);
|
||||
console.log("Exiting...")
|
||||
process.exit(1);
|
||||
}
|
||||
}))();
|
||||
|
||||
module.exports = run;
|
||||
setInterval(query, 1000)
|
||||
})
|
||||
.catch((err) => console.error(err))
|
||||
|
13
examples/start-daemon.js
Normal file
13
examples/start-daemon.js
Normal file
@ -0,0 +1,13 @@
|
||||
const IpfsDaemon = require('ipfs-daemon')
|
||||
module.exports = IpfsDaemon({
|
||||
IpfsDataDir: './tmp',
|
||||
API: {
|
||||
HTTPHeaders: {
|
||||
"Access-Control-Allow-Origin": ['*'],
|
||||
"Access-Control-Allow-Methods": ["PUT", "GET", "POST"],
|
||||
"Access-Control-Allow-Credentials": ["true"]
|
||||
}
|
||||
}
|
||||
})
|
||||
.then((res) => console.log("started"))
|
||||
.catch((err) => console.error(err))
|
28
package.json
28
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "orbit-db",
|
||||
"version": "0.11.1",
|
||||
"version": "0.11.2",
|
||||
"description": "Distributed p2p database on IPFS",
|
||||
"author": "Haad",
|
||||
"license": "MIT",
|
||||
@ -9,35 +9,41 @@
|
||||
"url": "https://github.com/haadcode/orbit-db"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^4.x.x"
|
||||
"node": "^6.x.x"
|
||||
},
|
||||
"main": "src/OrbitDB.js",
|
||||
"dependencies": {
|
||||
"logplease": "^1.2.7",
|
||||
"orbit-db-counterstore": "0.1.1",
|
||||
"orbit-db-eventstore": "0.1.1",
|
||||
"orbit-db-feedstore": "0.1.1",
|
||||
"orbit-db-kvstore": "0.1.1",
|
||||
"socket.io-client": "^1.4.5"
|
||||
"orbit-db-counterstore": "0.1.2",
|
||||
"orbit-db-eventstore": "0.1.4",
|
||||
"orbit-db-feedstore": "0.1.3",
|
||||
"orbit-db-kvstore": "0.1.2",
|
||||
"orbit-db-pubsub": "0.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"asyncawait": "^1.0.6",
|
||||
"babel-core": "^6.11.4",
|
||||
"babel-loader": "^6.2.4",
|
||||
"babel-plugin-transform-runtime": "^6.8.0",
|
||||
"babel-polyfill": "^6.16.0",
|
||||
"babel-preset-es2015": "^6.6.0",
|
||||
"bluebird": "^3.4.6",
|
||||
"exports-loader": "^0.6.3",
|
||||
"ipfs": "^0.13.0",
|
||||
"ipfs-api": "^6.0.3",
|
||||
"ipfsd-ctl": "^0.14.0",
|
||||
"fs-pull-blob-store": "^0.3.0",
|
||||
"html5-fs": "https://github.com/haadcode/html5-fs.git",
|
||||
"ipfs-daemon": "0.0.3",
|
||||
"ipfs-test-apis": "0.0.1",
|
||||
"json-loader": "^0.5.4",
|
||||
"lodash": "^4.3.0",
|
||||
"mocha": "^2.4.5",
|
||||
"orbit-server": "^0.2.3",
|
||||
"stream-http": "^2.2.1",
|
||||
"webpack": "^2.1.0-beta.7"
|
||||
},
|
||||
"scripts": {
|
||||
"examples": "npm run example:node",
|
||||
"examples:node": "LOG=debug node examples/eventlog.js",
|
||||
"examples:browser": "open examples/browser/index.html && LOG=debug node examples/start-daemon.js",
|
||||
"postinstall": "./scripts/post_install.sh",
|
||||
"test": "mocha",
|
||||
"build": "npm run build:dist && npm run build:minified && npm run build:examples",
|
||||
"build:dist": "./node_modules/.bin/webpack --config webpack.config.js",
|
||||
|
BIN
screenshots/orbit-db-demo1.gif
Normal file
BIN
screenshots/orbit-db-demo1.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 136 KiB |
BIN
screenshots/orbit-db-demo3.gif
Normal file
BIN
screenshots/orbit-db-demo3.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
4
scripts/post_install.sh
Executable file
4
scripts/post_install.sh
Executable file
@ -0,0 +1,4 @@
|
||||
# !/bin/sh
|
||||
rm -rf ./node_modules/ipfs/node_modules/ipfs-api
|
||||
rm -rf ./node_modules/ipfsd-ctl/node_modules/go-ipfs-dep
|
||||
rm -rf ./node_modules/ipfsd-ctl/node_modules/ipfs-api
|
152
src/OrbitDB.js
152
src/OrbitDB.js
@ -1,66 +1,63 @@
|
||||
'use strict';
|
||||
'use strict'
|
||||
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const Logger = require('logplease');
|
||||
const logger = Logger.create("orbit-db", { color: Logger.Colors.Magenta });
|
||||
const EventStore = require('orbit-db-eventstore');
|
||||
const FeedStore = require('orbit-db-feedstore');
|
||||
const KeyValueStore = require('orbit-db-kvstore');
|
||||
const CounterStore = require('orbit-db-counterstore');
|
||||
const PubSub = require('./PubSub');
|
||||
const Cache = require('./Cache');
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const EventStore = require('orbit-db-eventstore')
|
||||
const FeedStore = require('orbit-db-feedstore')
|
||||
const KeyValueStore = require('orbit-db-kvstore')
|
||||
const CounterStore = require('orbit-db-counterstore')
|
||||
const Pubsub = require('orbit-db-pubsub')
|
||||
const Cache = require('./Cache')
|
||||
|
||||
const defaultNetworkName = 'Orbit DEV Network'
|
||||
|
||||
class OrbitDB {
|
||||
constructor(ipfs) {
|
||||
this._ipfs = ipfs;
|
||||
this._pubsub = null;
|
||||
this.user = null;
|
||||
this.network = null;
|
||||
this.events = new EventEmitter();
|
||||
this.stores = {};
|
||||
constructor(ipfs, id = 'default', options = {}) {
|
||||
this._ipfs = ipfs
|
||||
this._pubsub = options && options.broker ? new options.broker(ipfs) : new Pubsub(ipfs)
|
||||
this.user = { id: id }
|
||||
this.network = { name: defaultNetworkName }
|
||||
this.events = new EventEmitter()
|
||||
this.stores = {}
|
||||
}
|
||||
|
||||
/* Databases */
|
||||
feed(dbname, options) {
|
||||
return this._createStore(FeedStore, dbname, options);
|
||||
return this._createStore(FeedStore, dbname, options)
|
||||
}
|
||||
|
||||
eventlog(dbname, options) {
|
||||
return this._createStore(EventStore, dbname, options);
|
||||
return this._createStore(EventStore, dbname, options)
|
||||
}
|
||||
|
||||
kvstore(dbname, options) {
|
||||
return this._createStore(KeyValueStore, dbname, options);
|
||||
return this._createStore(KeyValueStore, dbname, options)
|
||||
}
|
||||
|
||||
counter(dbname, options) {
|
||||
return this._createStore(CounterStore, dbname, options);
|
||||
return this._createStore(CounterStore, dbname, options)
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if(this._pubsub) this._pubsub.disconnect();
|
||||
this.events.removeAllListeners('data');
|
||||
if (this._pubsub) this._pubsub.disconnect()
|
||||
this.events.removeAllListeners('data')
|
||||
Object.keys(this.stores).map((e) => this.stores[e]).forEach((store) => {
|
||||
store.events.removeAllListeners('data');
|
||||
store.events.removeAllListeners('write');
|
||||
store.events.removeAllListeners('close');
|
||||
});
|
||||
this.stores = {};
|
||||
this.user = null;
|
||||
this.network = null;
|
||||
store.events.removeAllListeners('data')
|
||||
store.events.removeAllListeners('write')
|
||||
store.events.removeAllListeners('close')
|
||||
})
|
||||
this.stores = {}
|
||||
this.user = null
|
||||
this.network = null
|
||||
}
|
||||
|
||||
_createStore(Store, dbname, options) {
|
||||
if(!options) options = {};
|
||||
const replicate = options.subscribe !== undefined ? options.subscribe : true;
|
||||
const store = new Store(this._ipfs, this.user.username, dbname, options);
|
||||
this.stores[dbname] = store;
|
||||
return this._subscribe(store, dbname, replicate, options);
|
||||
/* Private methods */
|
||||
_createStore(Store, dbname, options = { subscribe: true }) {
|
||||
const store = new Store(this._ipfs, this.user.id, dbname, options)
|
||||
this.stores[dbname] = store
|
||||
return this._subscribe(store, dbname, options.subscribe, options)
|
||||
}
|
||||
|
||||
_subscribe(store, dbname, subscribe, options) {
|
||||
if(subscribe === undefined) subscribe = true
|
||||
|
||||
_subscribe(store, dbname, subscribe = true, options) {
|
||||
store.events.on('data', this._onData.bind(this))
|
||||
store.events.on('write', this._onWrite.bind(this))
|
||||
store.events.on('close', this._onClose.bind(this))
|
||||
@ -68,37 +65,33 @@ class OrbitDB {
|
||||
if(subscribe && this._pubsub)
|
||||
this._pubsub.subscribe(dbname, this._onMessage.bind(this), this._onConnected.bind(this), store.options.maxHistory > 0)
|
||||
else
|
||||
store.loadHistory().catch((e) => logger.error(e.stack));
|
||||
store.loadHistory().catch((e) => console.error(e.stack))
|
||||
|
||||
Cache.loadCache(options.cacheFile).then(() => {
|
||||
const hash = Cache.get(dbname)
|
||||
store.loadHistory(hash).catch((e) => logger.error(e.stack))
|
||||
store.loadHistory(hash).catch((e) => console.error(e.stack))
|
||||
})
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
|
||||
/* Connected to the message broker */
|
||||
|
||||
_onConnected(dbname, hash) {
|
||||
// console.log(".CONNECTED", dbname, hash, this.user.username);
|
||||
// console.log(".CONNECTED", dbname, hash)
|
||||
const store = this.stores[dbname]
|
||||
store.loadHistory(hash).catch((e) => logger.error(e.stack))
|
||||
store.loadHistory(hash).catch((e) => console.error(e.stack))
|
||||
}
|
||||
|
||||
/* Replication request from the message broker */
|
||||
|
||||
_onMessage(dbname, hash) {
|
||||
// console.log(".MESSAGE", dbname, hash, this.user.username)
|
||||
// console.log(".MESSAGE", dbname, hash)
|
||||
const store = this.stores[dbname]
|
||||
store.sync(hash)
|
||||
.then((res) => Cache.set(dbname, hash))
|
||||
.catch((e) => logger.error(e.stack))
|
||||
.catch((e) => console.error(e.stack))
|
||||
}
|
||||
|
||||
/* Data events */
|
||||
|
||||
_onWrite(dbname, hash) {
|
||||
// 'New entry written to database...', after adding a new db entry locally
|
||||
// console.log(".WRITE", dbname, hash, this.user.username)
|
||||
@ -109,7 +102,7 @@ class OrbitDB {
|
||||
|
||||
_onData(dbname, item) {
|
||||
// 'New database entry...', after a new entry was added to the database
|
||||
// console.log(".SYNCED", dbname, items.length);
|
||||
// console.log(".SYNCED", dbname, items.length)
|
||||
this.events.emit('data', dbname, item)
|
||||
}
|
||||
|
||||
@ -117,63 +110,6 @@ class OrbitDB {
|
||||
if(this._pubsub) this._pubsub.unsubscribe(dbname)
|
||||
delete this.stores[dbname]
|
||||
}
|
||||
|
||||
_connect(hash, username, password, allowOffline) {
|
||||
if(allowOffline === undefined) allowOffline = false
|
||||
|
||||
const readNetworkInfo = (hash) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(JSON.stringify({
|
||||
name: 'Orbit DEV Network',
|
||||
publishers: [hash]
|
||||
}));
|
||||
});
|
||||
};
|
||||
|
||||
let host, port, name;
|
||||
return readNetworkInfo(hash)
|
||||
.then((object) => {
|
||||
this.network = JSON.parse(object);
|
||||
name = this.network.name;
|
||||
host = this.network.publishers[0].split(":")[0];
|
||||
port = this.network.publishers[0].split(":")[1];
|
||||
})
|
||||
.then(() => {
|
||||
this._pubsub = new PubSub();
|
||||
logger.debug(`Connecting to network ${hash} (${host}:${port})`);
|
||||
return this._pubsub.connect(host, port, username, password)
|
||||
})
|
||||
.then(() => {
|
||||
logger.debug(`Connected to network ${hash} (${host}:${port})`);
|
||||
this.user = { username: username, id: username } // TODO: user id from ipfs hash
|
||||
return;
|
||||
})
|
||||
.catch((e) => {
|
||||
logger.warn(`Couldn't connect to ${hash} network: ${e.message}`);
|
||||
if(!allowOffline) {
|
||||
logger.debug(`'allowOffline' set to false, terminating`);
|
||||
if(this._pubsub) this._pubsub.disconnect();
|
||||
throw e;
|
||||
}
|
||||
this.user = { username: username, id: username } // TODO: user id from ipfs hash
|
||||
return;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class OrbitClientFactory {
|
||||
static connect(network, username, password, ipfs, options) {
|
||||
if(!options) options = { allowOffline: false };
|
||||
|
||||
if(!ipfs) {
|
||||
logger.error("IPFS instance not provided");
|
||||
throw new Error("IPFS instance not provided");
|
||||
}
|
||||
|
||||
const client = new OrbitDB(ipfs);
|
||||
return client._connect(network, username, password, options.allowOffline)
|
||||
.then(() => client)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = OrbitClientFactory;
|
||||
module.exports = OrbitDB
|
||||
|
@ -1,63 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const io = require('socket.io-client');
|
||||
const logger = require('logplease').create("orbit-db.Pubsub");
|
||||
|
||||
class Pubsub {
|
||||
constructor() {
|
||||
this._socket = null;
|
||||
this._subscriptions = {};
|
||||
}
|
||||
|
||||
connect(host, port, username, password) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if(!this._socket)
|
||||
this._socket = io.connect(`http://${host}:${port}`, { 'forceNew': true });
|
||||
|
||||
this._socket.on('connect', resolve);
|
||||
this._socket.on('connect_error', (err) => reject(new Error(`Connection refused to Pubsub at '${host}:${port}'`)));
|
||||
this._socket.on('disconnect', (socket) => logger.warn(`Disconnected from Pubsub at 'http://${host}:${port}'`));
|
||||
this._socket.on('error', (e) => logger.error('Pubsub socket error:', e));
|
||||
this._socket.on('message', this._handleMessage.bind(this));
|
||||
this._socket.on('subscribed', this._handleSubscribed.bind(this));
|
||||
});
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
if(this._socket)
|
||||
this._socket.disconnect();
|
||||
}
|
||||
|
||||
subscribe(hash, callback, onSubscribed, fetchHistory) {
|
||||
if(!this._subscriptions[hash]) {
|
||||
this._subscriptions[hash] = { callback: callback, history: fetchHistory, onSubscribed: onSubscribed };
|
||||
this._socket.emit('subscribe', { channel: hash }); // calls back with 'subscribed' event
|
||||
}
|
||||
}
|
||||
|
||||
unsubscribe(hash) {
|
||||
if(this._subscriptions[hash]) {
|
||||
this._socket.emit('unsubscribe', { channel: hash });
|
||||
delete this._subscriptions[hash];
|
||||
}
|
||||
}
|
||||
|
||||
publish(hash, message) {
|
||||
if(this._subscriptions[hash])
|
||||
this._socket.send(JSON.stringify({ channel: hash, message: message }));
|
||||
}
|
||||
|
||||
_handleMessage(hash, message) {
|
||||
const subscription = this._subscriptions[hash];
|
||||
if(subscription && subscription.callback)
|
||||
subscription.callback(hash, message);
|
||||
}
|
||||
|
||||
_handleSubscribed(hash, message) {
|
||||
const subscription = this._subscriptions[hash];
|
||||
if(subscription && subscription.history && subscription.onSubscribed)
|
||||
subscription.onSubscribed(hash, message)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Pubsub;
|
File diff suppressed because it is too large
Load Diff
@ -1,165 +1,104 @@
|
||||
'use strict';
|
||||
// 'use strict'
|
||||
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const Promise = require('bluebird');
|
||||
const rimraf = require('rimraf')
|
||||
const OrbitDB = require('../src/OrbitDB');
|
||||
const OrbitServer = require('orbit-server/src/server');
|
||||
const ipfsd = require('ipfsd-ctl');
|
||||
const IPFS = require('ipfs')
|
||||
// const assert = require('assert')
|
||||
// const path = require('path')
|
||||
// const fs = require('fs')
|
||||
// const Promise = require('bluebird')
|
||||
// const rimraf = require('rimraf')
|
||||
// const IpfsApis = require('ipfs-test-apis')
|
||||
// const IpfsDaemon = require('ipfs-daemon')
|
||||
// const OrbitDB = require('../src/OrbitDB')
|
||||
|
||||
// Mute logging
|
||||
require('logplease').setLogLevel('ERROR');
|
||||
// const username = 'testrunner'
|
||||
// const username2 = 'rennurtset'
|
||||
// const cacheFile = path.join(process.cwd(), '/tmp/orbit-db-tests/cache.json')
|
||||
|
||||
const network = 'localhost:3333';
|
||||
const username = 'testrunner';
|
||||
const username2 = 'rennurtset';
|
||||
const ipfsPath = '/tmp/orbittests';
|
||||
const cacheFile = path.join(process.cwd(), '/test/orbit-db-cache.json')
|
||||
// IpfsApis.forEach(function(ipfsApi) {
|
||||
// let ipfs, ipfsDaemon
|
||||
|
||||
let ipfs, ipfsDaemon;
|
||||
const IpfsApis = [
|
||||
{
|
||||
// js-ipfs
|
||||
name: 'js-ipfs',
|
||||
start: () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const IPFS = require('ipfs')
|
||||
const ipfs = new IPFS('/tmp/orbit-db-test');
|
||||
const init = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ipfs.init({}, (err) => {
|
||||
if (err) {
|
||||
if (err.message === 'repo already exists') {
|
||||
return resolve();
|
||||
}
|
||||
return reject(err);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
};
|
||||
// describe('CounterStore with ' + ipfsApi.name, function() {
|
||||
// this.timeout(40000)
|
||||
// let client1, client2
|
||||
// let daemon1, daemon2
|
||||
|
||||
// resolve(ipfs);
|
||||
return init().then(() => {
|
||||
// resolve(ipfs);
|
||||
ipfs.goOnline((err) => {
|
||||
if(err) reject(err)
|
||||
return resolve(ipfs)
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
// stop: () => Promise.resolve()
|
||||
stop: () => new Promise((resolve, reject) => ipfs.goOffline(resolve))
|
||||
},
|
||||
{
|
||||
// js-ipfs-api via local daemon
|
||||
name: 'js-ipfs-api',
|
||||
start: () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
ipfsd.disposableApi((err, ipfs) => {
|
||||
if(err) reject(err);
|
||||
resolve(ipfs);
|
||||
});
|
||||
// ipfsd.local((err, node) => {
|
||||
// if(err) reject(err);
|
||||
// ipfsDaemon = node;
|
||||
// ipfsDaemon.startDaemon((err, ipfs) => {
|
||||
// if(err) reject(err);
|
||||
// resolve(ipfs);
|
||||
// });
|
||||
// });
|
||||
});
|
||||
},
|
||||
stop: () => Promise.resolve()
|
||||
// stop: () => new Promise((resolve, reject) => ipfsDaemon.stopDaemon(resolve))
|
||||
}
|
||||
];
|
||||
// before((done) => {
|
||||
// // rimraf.sync('./orbit-db-cache.json')
|
||||
// daemon1
|
||||
// Promise.all([
|
||||
// IpfsDaemon({ IpfsDataDir: '/tmp/daemon1' }),
|
||||
// IpfsDaemon({ IpfsDataDir: '/tmp/daemon2' })
|
||||
// ])
|
||||
// .then((res) => {
|
||||
// ipfs = [res[0].ipfs, res[1].ipfs]
|
||||
// daemon1 = res[0].daemon
|
||||
// daemon2 = res[1].daemon
|
||||
// done()
|
||||
// })
|
||||
// })
|
||||
|
||||
// OrbitServer.start(); // uncomment if running this test suite stand-alone
|
||||
IpfsApis.forEach(function(ipfsApi) {
|
||||
// after((done) => {
|
||||
// daemon1.stopDaemon()
|
||||
// daemon2.stopDaemon()
|
||||
// done()
|
||||
// })
|
||||
|
||||
describe('CounterStore with ' + ipfsApi.name, function() {
|
||||
this.timeout(40000);
|
||||
let client1, client2;
|
||||
// beforeEach(() => {
|
||||
// client1 = new OrbitDB(ipfs[0], username, { cacheFile: cacheFile })
|
||||
// client2 = new OrbitDB(ipfs[1], username2, { cacheFile: cacheFile })
|
||||
// })
|
||||
|
||||
before((done) => {
|
||||
rimraf.sync('./orbit-db-cache.json')
|
||||
ipfsApi.start()
|
||||
// .then((ipfs) => {
|
||||
// return ipfs.add(path.resolve(process.cwd(), './test/network.json')).then(() => ipfs)
|
||||
// })
|
||||
.then((res) => {
|
||||
ipfs = res;
|
||||
return Promise.map([username, username2], (login) => {
|
||||
return OrbitDB.connect(network, login, '', ipfs, { allowOffline: false, cacheFile: cacheFile });
|
||||
}).then((clients) => {
|
||||
client1 = clients[0];
|
||||
client2 = clients[1];
|
||||
return;
|
||||
}).catch((e) => {
|
||||
console.log(e.stack);
|
||||
assert.equal(e, null);
|
||||
});
|
||||
})
|
||||
.then(done)
|
||||
});
|
||||
// afterEach(() => {
|
||||
// if(client1) client1.disconnect()
|
||||
// if(client2) client2.disconnect()
|
||||
// })
|
||||
|
||||
after((done) => {
|
||||
if(client1) client1.disconnect();
|
||||
if(client2) client2.disconnect();
|
||||
ipfsApi.stop().then(() => {
|
||||
rimraf(cacheFile, done)
|
||||
});
|
||||
});
|
||||
// describe('counters', function() {
|
||||
// it('increases a counter value', function(done) {
|
||||
// const timeout = setTimeout(() => done(new Error('event was not fired')), 2000)
|
||||
// const counter = client1.counter('counter test', { subscribe: false, cacheFile: cacheFile })
|
||||
// counter.events.on('ready', () => {
|
||||
// Promise.map([13, 1], (f) => counter.inc(f), { concurrency: 1 })
|
||||
// .then(() => {
|
||||
// assert.equal(counter.value(), 14)
|
||||
// clearTimeout(timeout)
|
||||
// client1.disconnect()
|
||||
// done()
|
||||
// })
|
||||
// .catch(done)
|
||||
// })
|
||||
// })
|
||||
|
||||
describe('counters', function() {
|
||||
it('increases a counter value', function(done) {
|
||||
const timeout = setTimeout(() => done(new Error('event was not fired')), 2000)
|
||||
const counter = client1.counter('counter test', { subscribe: false, cacheFile: cacheFile })
|
||||
counter.events.on('ready', () => {
|
||||
Promise.map([13, 1], (f) => counter.inc(f), { concurrency: 1 })
|
||||
.then(() => {
|
||||
assert.equal(counter.value(), 14)
|
||||
clearTimeout(timeout)
|
||||
done()
|
||||
})
|
||||
.catch(done)
|
||||
})
|
||||
});
|
||||
// it('creates a new counter from cached data', function(done) {
|
||||
// const timeout = setTimeout(() => done(new Error('event was not fired')), 2000)
|
||||
// const counter = client1.counter('counter test', { subscribe: false, cacheFile: cacheFile })
|
||||
// counter.events.on('ready', () => {
|
||||
// assert.equal(counter.value(), 14)
|
||||
// clearTimeout(timeout)
|
||||
// client1.disconnect()
|
||||
// done()
|
||||
// })
|
||||
// })
|
||||
|
||||
it('creates a new counter from cached data', function(done) {
|
||||
const timeout = setTimeout(() => done(new Error('event was not fired')), 2000)
|
||||
const counter = client1.counter('counter test', { subscribe: false, cacheFile: cacheFile })
|
||||
counter.events.on('ready', () => {
|
||||
assert.equal(counter.value(), 14)
|
||||
clearTimeout(timeout)
|
||||
done()
|
||||
})
|
||||
})
|
||||
// it.only('syncs counters', (done) => {
|
||||
// const name = new Date().getTime()
|
||||
// const counter1 = client1.counter(name)
|
||||
// const counter2 = client2.counter(name)
|
||||
// const numbers = [[13, 10], [2, 5]]
|
||||
// // const res1 = ([13, 10]).map((f) => counter1.inc(f))//, { concurrency: 1 })
|
||||
// // const res2 = ([2, 5]).map((f) => counter2.inc(f))//, { concurrency: 1 })
|
||||
// Promise.map([counter1, counter2], (counter, i) => numbers[i].map((e) => counter.inc(e)) , { concurrency: 1 })
|
||||
// .then((res) => {
|
||||
// // wait for a while to make sure db's have been synced
|
||||
// setTimeout(() => {
|
||||
// assert.equal(counter2.value(), 30)
|
||||
// assert.equal(counter1.value(), 30)
|
||||
// done()
|
||||
// }, 10000)
|
||||
// })
|
||||
// .catch(done)
|
||||
// })
|
||||
|
||||
it('syncs counters', (done) => {
|
||||
const name = new Date().getTime();
|
||||
const counter1 = client1.counter(name)
|
||||
const counter2 = client2.counter(name)
|
||||
const res1 = Promise.map([13, 10], (f) => counter1.inc(f), { concurrency: 1 })
|
||||
const res2 = Promise.map([2, 5], (f) => counter2.inc(f), { concurrency: 1 })
|
||||
Promise.all([res1, res2])
|
||||
.then((res) => {
|
||||
// wait for a while to make sure db's have been synced
|
||||
setTimeout(() => {
|
||||
assert.equal(counter1.value(), 30)
|
||||
assert.equal(counter2.value(), 30)
|
||||
done()
|
||||
}, 4000)
|
||||
})
|
||||
.catch(done)
|
||||
})
|
||||
// })
|
||||
// })
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
// })
|
||||
|
@ -1,5 +1,5 @@
|
||||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack')
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
entry: './src/OrbitDB.js',
|
||||
@ -8,21 +8,18 @@ module.exports = {
|
||||
library: 'OrbitDB',
|
||||
filename: './dist/orbitdb.js'
|
||||
},
|
||||
devtool: 'sourcemap',
|
||||
node: {
|
||||
console: false,
|
||||
process: 'mock',
|
||||
Buffer: 'buffer'
|
||||
},
|
||||
resolveLoader: {
|
||||
root: path.join(__dirname, 'node_modules')
|
||||
Buffer: true
|
||||
},
|
||||
resolve: {
|
||||
modulesDirectories: [
|
||||
modules: [
|
||||
path.join(__dirname, 'node_modules')
|
||||
],
|
||||
alias: {
|
||||
'orbit-db-stre': require.resolve('./node_modules/orbit-db-store'),
|
||||
fs: require.resolve('./node_modules/logplease/src/fs-mock'),
|
||||
'fs': path.join(__dirname + '/node_modules', 'html5-fs'),
|
||||
http: 'stream-http',
|
||||
https: 'https-browserify',
|
||||
Buffer: 'buffer'
|
||||
@ -41,7 +38,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: /node_modules\/(hoek|qs|wreck|boom)/,
|
||||
include: /node_modules\/(hoek|qs|wreck|boom|ipfs-.+|orbit-db.+|logplease|crdts|promisify-es6)/,
|
||||
loader: 'babel',
|
||||
query: {
|
||||
presets: require.resolve('babel-preset-es2015'),
|
||||
@ -51,11 +48,12 @@ module.exports = {
|
||||
{
|
||||
test: /\.json$/,
|
||||
loader: 'json'
|
||||
}]
|
||||
}
|
||||
]
|
||||
},
|
||||
externals: {
|
||||
net: '{}',
|
||||
tls: '{}',
|
||||
'require-dir': '{}'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack')
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
entry: './src/OrbitDB.js',
|
||||
@ -8,10 +8,11 @@ module.exports = {
|
||||
library: 'OrbitDB',
|
||||
filename: './dist/orbitdb.min.js'
|
||||
},
|
||||
devtool: 'sourcemap',
|
||||
node: {
|
||||
console: false,
|
||||
process: 'mock',
|
||||
Buffer: 'buffer'
|
||||
Buffer: true
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
@ -20,17 +21,15 @@ module.exports = {
|
||||
})
|
||||
],
|
||||
resolveLoader: {
|
||||
root: path.join(__dirname, 'node_modules')
|
||||
modules: [path.join(__dirname, 'node_modules')]
|
||||
},
|
||||
resolve: {
|
||||
modulesDirectories: [
|
||||
modules: [
|
||||
path.join(__dirname, 'node_modules')
|
||||
],
|
||||
alias: {
|
||||
fs: require.resolve('./node_modules/logplease/src/fs-mock'),
|
||||
http: 'stream-http',
|
||||
https: 'https-browserify',
|
||||
Buffer: 'buffer'
|
||||
'node_modules': path.join(__dirname + '/node_modules'),
|
||||
'fs': path.join(__dirname + '/node_modules', 'html5-fs'),
|
||||
}
|
||||
},
|
||||
module: {
|
||||
@ -46,7 +45,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: /node_modules\/(hoek|qs|wreck|boom|ipfs-.+|orbit-db-.+|logplease|crdts)/,
|
||||
include: /node_modules\/(hoek|qs|wreck|boom|ipfs-.+|orbit-db.+|logplease|crdts|promisify-es6)/,
|
||||
loader: 'babel',
|
||||
query: {
|
||||
presets: require.resolve('babel-preset-es2015'),
|
||||
@ -64,4 +63,4 @@ module.exports = {
|
||||
tls: '{}',
|
||||
'require-dir': '{}'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
const webpack = require('webpack');
|
||||
const path = require('path');
|
||||
const webpack = require('webpack')
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
entry: './examples/browser/browser.js',
|
||||
entry: [
|
||||
'./examples/browser/index.js',
|
||||
],
|
||||
output: {
|
||||
filename: './examples/browser/bundle.js'
|
||||
},
|
||||
devtool: 'sourcemap',
|
||||
node: {
|
||||
console: false,
|
||||
process: 'mock',
|
||||
Buffer: 'buffer'
|
||||
Buffer: true
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
@ -17,18 +20,12 @@ module.exports = {
|
||||
compress: { warnings: false }
|
||||
})
|
||||
],
|
||||
resolveLoader: {
|
||||
root: path.join(__dirname, 'node_modules')
|
||||
},
|
||||
resolve: {
|
||||
modulesDirectories: [
|
||||
modules: [
|
||||
path.join(__dirname, 'node_modules')
|
||||
],
|
||||
alias: {
|
||||
fs: require.resolve('./node_modules/logplease/src/fs-mock'),
|
||||
http: 'stream-http',
|
||||
https: 'https-browserify',
|
||||
Buffer: 'buffer'
|
||||
'fs': path.join(__dirname + '/node_modules', 'html5-fs'),
|
||||
}
|
||||
},
|
||||
module: {
|
||||
@ -44,7 +41,7 @@ module.exports = {
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
include: /node_modules\/(hoek|qs|wreck|boom|ipfs-.+|orbit-db-.+|logplease|crdts)/,
|
||||
include: /node_modules\/(hoek|qs|wreck|boom|ipfs.+|orbit.+|logplease|crdts|promisify-es|whatwg-fetch|node-fetch|isomorphic-fetch|db\.js)/,
|
||||
loader: 'babel',
|
||||
query: {
|
||||
presets: require.resolve('babel-preset-es2015'),
|
||||
@ -62,4 +59,4 @@ module.exports = {
|
||||
tls: '{}',
|
||||
'require-dir': '{}'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user