Merge branch 'master' into develop
This commit is contained in:
commit
7899ce3856
3
.gitignore
vendored
3
.gitignore
vendored
@ -21,3 +21,6 @@ examples/browser/lib
|
||||
# Don't track builds in git
|
||||
# Distribution builds are available via npm
|
||||
dist/
|
||||
|
||||
# Don't track Visual Studio Code settings
|
||||
.vscode
|
11
API.md
11
API.md
@ -49,7 +49,7 @@ Read the **[GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUI
|
||||
* [OrbitDB.isValidAddress(address)](#orbitdbisvalidaddressaddress)
|
||||
* [OrbitDB.parseAddress(address)](#orbitdbparseaddressaddress)
|
||||
- [Store API](#store-api)
|
||||
* [store.load([amount])](#storeloadamount)
|
||||
* [store.load([amount], { fetchEntryTimeout })](#storeloadamount--fetchentrytimeout-)
|
||||
* [store.close()](#storeclose)
|
||||
* [store.drop()](#storedrop)
|
||||
* [store.identity](#storeidentity)
|
||||
@ -95,6 +95,15 @@ const db = await orbitdb.keyvalue('profile')
|
||||
|
||||
## Public Instance Methods
|
||||
|
||||
Before starting, you should know that OrbitDB has different types of databases. Each one satisfies a different purpose. The databases that you can create are:
|
||||
|
||||
* [log](https://github.com/orbitdb/orbit-db/blob/master/API.md#orbitdblognameaddress): an imutable (write only) log database. Useful for transactions lists.
|
||||
* [feed](https://github.com/orbitdb/orbit-db/blob/master/API.md#orbitdbfeednameaddress): a mutable log database. Useful for blog comments.
|
||||
* [keyvalue](https://github.com/orbitdb/orbit-db/blob/master/API.md#orbitdbkeyvaluenameaddress): Useful for loading data from keywords or an id.
|
||||
* [docs](https://github.com/orbitdb/orbit-db/blob/master/API.md#orbitdbdocsnameaddress-options): a JSON documents database. Useful for user data or other structured data.
|
||||
* [counter](https://github.com/orbitdb/orbit-db/blob/master/API.md#orbitdbcounternameaddress): Useful for ordered data (like an ordered list or a playlist.)
|
||||
|
||||
|
||||
### orbitdb.create(name, type, [options])
|
||||
> Creates and opens an OrbitDB database.
|
||||
|
||||
|
37
CHANGELOG.md
37
CHANGELOG.md
@ -1,5 +1,42 @@
|
||||
# Changelog
|
||||
|
||||
## v0.22.1
|
||||
|
||||
- Thanks to [#712](https://github.com/orbitdb/orbit-db/pull/712) from @kolessios, as well as the efforts of @BartKnucle and @durac :heart:, OrbitDB now works on Windows :tada: We invite our Windows friends to try it out!
|
||||
- Several submodules are now exposed in the OrbitDB class ([#717](https://github.com/orbitdb/orbit-db/pull/717), thanks @hazae41)
|
||||
|
||||
## v0.22.0
|
||||
|
||||
Up to 10x Performance Increase in Appends :tada:
|
||||
|
||||
- `sortFn` now at the top level
|
||||
- `orbit-db-storage-adapter` now provides cache and keystore interop for mongo, redis, and any `abstract-leveldown`
|
||||
|
||||
### (semi-)Breaking Changes
|
||||
|
||||
To improve performance, this release changes the way caches are managed.
|
||||
|
||||
#### Cache Directory Locations
|
||||
|
||||
_Your cache directory structure will change_. There is a migration script that will run upon creating the database.
|
||||
|
||||
Old Structure (node.js default):
|
||||
```
|
||||
orbitdb/[OrbitDB ID]/keystore
|
||||
orbitdb/[DB ID]/db-name/
|
||||
orbitdb/[DB ID]/db-name1/
|
||||
orbitdb/[DB ID]/db-name2/
|
||||
```
|
||||
|
||||
New Structure (node.js default):
|
||||
```
|
||||
orbitdb/[OrbitDB ID]/keystore
|
||||
orbitdb/[OrbitDB ID]/cache
|
||||
```
|
||||
##### `identityKeysPath` is optional, but important!
|
||||
|
||||
Read more about what this release includes [here](https://orbitdb.org/orbitdb-release-v0.22).
|
||||
|
||||
## v0.20.0
|
||||
***This release contains API breaking changes!*** The release **IS** backwards compatible with respect to old OrbitDB addresses and will be able to process and read old data-structures. The shape of the `Entry` object has also changed to include an [`identity`](https://github.com/orbitdb/orbit-db-identity-provider) field as well as increment the version `v` to 1. The `hash` property now holds a [CIDv1](https://github.com/multiformats/cid#cidv1) multihash string.
|
||||
|
||||
|
48
FAQ.md
48
FAQ.md
@ -8,18 +8,20 @@ This document is seeded by questions from people opening issues in this reposito
|
||||
|
||||
**Questions**
|
||||
|
||||
<!-- toc -->
|
||||
<!-- TOC -->
|
||||
|
||||
- [Database replication is not working. Why?](#database-replication-is-not-working-why)
|
||||
- [Can I recreate the entire database on another machine based on the address?](#can-i-recreate-the-entire-database-on-another-machine-based-on-the-address)
|
||||
- [Is every `put` to OrbitDB immediately sent to the network and persisted?](#is-every-put-to-orbitdb-immediately-sent-to-the-network-and-persisted)
|
||||
- [Does OrbitDB already support pinning when using js-ipfs ?](#does-orbitdb-already-support-pinning-when-using-js-ipfs-)
|
||||
- [Does orbit have a shared feed between peers where multiple peers can append to the same feed?](#does-orbit-have-a-shared-feed-between-peers-where-multiple-peers-can-append-to-the-same-feed)
|
||||
- [I'm getting a lot of 429 (Too Many Requests) errors when I run OrbitDB](#im-getting-a-lot-of-429-too-many-requests-errors-when-i-run-orbitdb)
|
||||
- [Where can I learn more about security, encryption, and account recovery?](#where-can-i-learn-more-about-security-encryption-and-account-recovery)
|
||||
- [How can I contribute to this FAQ?](#how-can-i-contribute-to-this-faq)
|
||||
- [Frequently Asked Questions](#frequently-asked-questions)
|
||||
- [Database replication is not working. Why?](#database-replication-is-not-working-why)
|
||||
- [Can I recreate the entire database on another machine based on the address?](#can-i-recreate-the-entire-database-on-another-machine-based-on-the-address)
|
||||
- [Is every `put` to OrbitDB immediately sent to the network and persisted?](#is-every-put-to-orbitdb-immediately-sent-to-the-network-and-persisted)
|
||||
- [Does OrbitDB already support pinning when using js-ipfs ?](#does-orbitdb-already-support-pinning-when-using-js-ipfs-)
|
||||
- [Does orbit have a shared feed between peers where multiple peers can append to the same feed?](#does-orbit-have-a-shared-feed-between-peers-where-multiple-peers-can-append-to-the-same-feed)
|
||||
- [I'm getting a lot of 429 (Too Many Requests) errors when I run OrbitDB](#im-getting-a-lot-of-429-too-many-requests-errors-when-i-run-orbitdb)
|
||||
- [Where can I learn more about security, encryption, and account recovery?](#where-can-i-learn-more-about-security-encryption-and-account-recovery)
|
||||
- [Does OrbitDB natively allow for a multi-writer capability permission model?](#does-orbitdb-natively-allow-for-a-multi-writer-capability-permission-model)
|
||||
- [How can I contribute to this FAQ?](#how-can-i-contribute-to-this-faq)
|
||||
|
||||
<!-- tocstop -->
|
||||
<!-- /TOC -->
|
||||
|
||||
---
|
||||
|
||||
@ -55,7 +57,7 @@ All databases (feeds) are shared between peers, so nobody "owns them" like users
|
||||
|
||||
This happens when there's only one node with data available, and the system isn't able to effectively get all of the data it needs from it. In order to get around this, IPFS instantiates nodes with preload enabled, so that one node isn't effectively DDoSed. However, sometimes these nodes go down, as well, causing 429 errors. To get around this in example cases (certainly not in production), disable preload:
|
||||
|
||||
```js
|
||||
```
|
||||
this.ipfs = new Ipfs({
|
||||
preload: { enabled: false },
|
||||
// ...
|
||||
@ -66,6 +68,30 @@ this.ipfs = new Ipfs({
|
||||
|
||||
The very short answer is that OrbitDB is agnostic in terms of encryption and account recovery with the aim of providing maximum flexibility with your apps. We don't do any encryption on our side; however, nothing is stopping you from encrypting data before storing it in the OrbitDB network. OrbitDB (just like IPFS) will treat encrypted the data exactly the same. Any node can replicate the data, but only nodes which have access to the encryption key from some other means will be able to decrypt it.
|
||||
|
||||
|
||||
### Does OrbitDB natively allow for a multi-writer capability permission model?
|
||||
|
||||
BY default, if you allow `*` access to the access controller, like so:
|
||||
|
||||
`orbitdb.feed('name', { accessController: { write ['*'] }})`
|
||||
|
||||
To allow specific keys to write to the database, pass the keys as strings like so:
|
||||
|
||||
`orbitdb.feed('name', { accessController: { write ['key1', 'key2'] }}) // keys cannot be revoked`
|
||||
|
||||
Allows anyone to write to the db. If you specify keys, the process involves granting and revoking keys. Granting is doable, but revokation is a harder and is being worked on by multiple parties, without a solution.
|
||||
|
||||
If you want to encrypt the keys or content, it's easier with a single user. If you want to use encryption with multiwriters, that's another bag which also hasn't been solved.
|
||||
|
||||
The concept of identity in OrbitDB currently centers on a single user associated with a public key. To do more than this, you may need a different access controller. [@3box](https://github.com/3box) has a modified access controller plugin, [3box-orbitdb-plugins](https://github.com/3box/3box-orbitdb-plugins), which is worth looking at for how to do this.
|
||||
|
||||
| | Non-Encrypted | Encrypted |
|
||||
| ----- | ----- | ---- |
|
||||
| Single Writer | Default | Requires encryption key management |
|
||||
| Multi Writer | Difficulty w/ granting + revocation | Difficulty w/ granting + revocation AND sharing encryption keys |
|
||||
|
||||
We'd love to add multi-writer support to OrbitDB! The maintainers at Haja are currently not working on anything related to it though but would be happy to help. Your best bet is to jump on [Gitter](https://gitter.im/orbitdb/Lobby) and ask us where the current efforts are.
|
||||
|
||||
### How can I contribute to this FAQ?
|
||||
|
||||
See the introduction at the top! Please open any issues and pull requests you can to improve this FAQ.md. It is here for you. If you're confused, ask another question publicly; it's possible that other people are, too. If you don't want to open an issue, feel free to jump onto [the Gitter](https://gitter.im/orbitdb/Lobby) and ask us there, too.
|
11
GUIDE.md
11
GUIDE.md
@ -22,6 +22,7 @@ This guide is still being worked on and we would love to get [feedback and sugge
|
||||
+ [Custom Access Controller](#custom-access-controller)
|
||||
- [Add an entry](#add-an-entry)
|
||||
- [Get an entry](#get-an-entry)
|
||||
- [Entry sorting and conflict resolution](#entry-sorting-and-conflict-resolution)
|
||||
- [Persistency](#persistency)
|
||||
- [Replicating a database](#replicating-a-database)
|
||||
- [Custom Stores](#custom-stores)
|
||||
@ -55,16 +56,6 @@ Require OrbitDB and IPFS in your program and create the instances:
|
||||
const IPFS = require('ipfs')
|
||||
const OrbitDB = require('orbit-db')
|
||||
|
||||
// OrbitDB uses Pubsub which is an experimental feature
|
||||
// and need to be turned on manually.
|
||||
// Note that these options need to be passed to IPFS in
|
||||
// all examples in this document even if not specified so.
|
||||
const ipfsOptions = {
|
||||
EXPERIMENTAL: {
|
||||
pubsub: true
|
||||
}
|
||||
}
|
||||
|
||||
// Create IPFS instance
|
||||
const ipfs = new IPFS(ipfsOptions)
|
||||
|
||||
|
19
README.md
19
README.md
@ -63,7 +63,9 @@ We also have regular community calls, which we announce in the issues in [the @o
|
||||
|
||||
## Usage
|
||||
|
||||
Read the **[GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUIDE.md)** guide for a more in-depth tutorial and to understand how OrbitDB works.
|
||||
Read the **[GETTING STARTED](https://github.com/orbitdb/orbit-db/blob/master/GUIDE.md)** guide for a quick tutorial on how to use OrbitDB.
|
||||
|
||||
For a more in-depth tutorial and exploration of OrbitDB's architecture, please check out the **[OrbitDB Field Manual](https://github.com/orbitdb/field-manual)**.
|
||||
|
||||
### CLI
|
||||
|
||||
@ -88,17 +90,18 @@ npm install orbit-db ipfs
|
||||
```javascript
|
||||
const IPFS = require('ipfs')
|
||||
const OrbitDB = require('orbit-db')
|
||||
// OrbitDB uses Pubsub which is an experimental feature
|
||||
// and need to be turned on manually.
|
||||
// Note that these options need to be passed to IPFS in
|
||||
// all examples even if not specified so.
|
||||
|
||||
// Create IPFS instance
|
||||
|
||||
// For js-ipfs >= 0.38
|
||||
const ipfs = new IPFS()
|
||||
|
||||
// For js-ipfs < 0.38
|
||||
const ipfsOptions = {
|
||||
EXPERIMENTAL: {
|
||||
pubsub: true
|
||||
}
|
||||
}
|
||||
|
||||
// Create IPFS instance
|
||||
const ipfs = new IPFS(ipfsOptions)
|
||||
|
||||
ipfs.on('error', (e) => console.error(e))
|
||||
@ -289,4 +292,4 @@ If you want to sponsor developers to work on OrbitDB, please reach out to @haadc
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE) © 2015-2018 Protocol Labs Inc., Haja Networks Oy
|
||||
[MIT](LICENSE) © 2015-2019 Protocol Labs Inc., Haja Networks Oy
|
||||
|
2218
package-lock.json
generated
2218
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
46
package.json
46
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "orbit-db",
|
||||
"version": "0.22.0-rc5",
|
||||
"version": "0.22.1",
|
||||
"description": "Distributed p2p database on IPFS",
|
||||
"author": "Haad",
|
||||
"license": "MIT",
|
||||
@ -20,18 +20,18 @@
|
||||
"logplease": "^1.2.14",
|
||||
"multihashes": "^0.4.12",
|
||||
"orbit-db-access-controllers": "~0.2.2",
|
||||
"orbit-db-cache": "next",
|
||||
"orbit-db-counterstore": "next",
|
||||
"orbit-db-docstore": "next",
|
||||
"orbit-db-eventstore": "next",
|
||||
"orbit-db-feedstore": "next",
|
||||
"orbit-db-identity-provider": "next",
|
||||
"orbit-db-cache": "~0.3.0",
|
||||
"orbit-db-counterstore": "~1.6.0",
|
||||
"orbit-db-docstore": "~1.6.0",
|
||||
"orbit-db-eventstore": "~1.6.0",
|
||||
"orbit-db-feedstore": "~1.6.0",
|
||||
"orbit-db-identity-provider": "~0.2.0",
|
||||
"orbit-db-io": "^0.1.1",
|
||||
"orbit-db-keystore": "next",
|
||||
"orbit-db-kvstore": "next",
|
||||
"orbit-db-keystore": "~0.3.0",
|
||||
"orbit-db-kvstore": "~1.6.0",
|
||||
"orbit-db-pubsub": "~0.5.5",
|
||||
"orbit-db-storage-adapter": "^0.5.3",
|
||||
"orbit-db-store": "next"
|
||||
"orbit-db-store": "~2.7.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-cli": "^6.26.0",
|
||||
@ -40,6 +40,8 @@
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"cpy-cli": "^2.0.0",
|
||||
"cross-env": "^6.0.3",
|
||||
"datastore-level": "0.10.0",
|
||||
"fs-extra": "^7.0.1",
|
||||
"go-ipfs-dep": "aphelionz/npm-go-ipfs-dep",
|
||||
@ -47,8 +49,9 @@
|
||||
"ipfs-http-client": "^37.0.1",
|
||||
"ipfs-repo": "~0.26.6",
|
||||
"ipfsd-ctl": "~0.42.3",
|
||||
"localstorage-level-migration": "next",
|
||||
"localstorage-level-migration": "~0.1.0",
|
||||
"markdown-toc": "^1.2.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^5.2.0",
|
||||
"p-each-series": "^1.0.0",
|
||||
"p-map": "^1.2.0",
|
||||
@ -69,14 +72,15 @@
|
||||
"examples:node": "node examples/eventlog.js",
|
||||
"examples:browser-macos": "open examples/browser/browser.html",
|
||||
"examples:browser-linux": "xdg-open examples/browser/browser.html",
|
||||
"examples:browser-windows": "start examples/browser/browser.html",
|
||||
"lint:docs": "remark -qf -u validate-links .",
|
||||
"test:all": "npm run test:browser-multiple-tabs && npm run test",
|
||||
"test": "TEST=all mocha",
|
||||
"test:browser-multiple-tabs": "npm run build:dist && cp dist/orbitdb.min.js ./test/browser/orbitdb.js && cp node_modules/ipfs/dist/index.js ./test/browser/ipfs.js && cp node_modules/orbit-db-identity-provider/dist/index-browser.min.js ./test/browser/identities.js && cp node_modules/ipfs-log/dist/ipfslog.min.js ./test/browser/ipfslog.min.js && mocha ./test/browser/concurrent.spec.js",
|
||||
"test": "cross-env TEST=all mocha",
|
||||
"test:browser-multiple-tabs": "npm run build:dist && cpy dist/orbitdb.min.js ./test/browser/orbitdb.js && cpy node_modules/ipfs/dist/index.js ./test/browser/ipfs.js && cpy node_modules/orbit-db-identity-provider/dist/index-browser.min.js ./test/browser/identities.js && cpy node_modules/ipfs-log/dist/ipfslog.min.js ./test/browser/ipfslog.min.js && mocha ./test/browser/concurrent.spec.js",
|
||||
"build": "npm run build:es5 && npm run build:debug && npm run build:dist && npm run build:examples && npm run build:docs/toc",
|
||||
"build:examples": "webpack --config conf/webpack.example.config.js --sort-modules-by size && mkdir -p examples/browser/lib && cp node_modules/ipfs/dist/index.js examples/browser/lib/ipfs.js",
|
||||
"build:dist": "webpack --config conf/webpack.config.js --sort-modules-by size && mkdir -p examples/browser/lib && cp dist/orbitdb.min.js examples/browser/lib/orbitdb.min.js",
|
||||
"build:debug": "webpack --config conf/webpack.debug.config.js --sort-modules-by size && mkdir -p examples/browser/lib && cp dist/orbitdb.js examples/browser/lib/orbitdb.js && cp dist/orbitdb.js.map examples/browser/lib/orbitdb.js.map",
|
||||
"build:examples": "webpack --config conf/webpack.example.config.js --sort-modules-by size && mkdirp examples/browser/lib && cpy node_modules/ipfs/dist/index.js examples/browser/lib/ipfs.js",
|
||||
"build:dist": "webpack --config conf/webpack.config.js --sort-modules-by size && mkdirp examples/browser/lib && cpy dist/orbitdb.min.js examples/browser/lib/orbitdb.min.js",
|
||||
"build:debug": "webpack --config conf/webpack.debug.config.js --sort-modules-by size && mkdirp examples/browser/lib && cpy dist/orbitdb.js examples/browser/lib/orbitdb.js && cpy dist/orbitdb.js.map examples/browser/lib/orbitdb.js.map",
|
||||
"build:docs/toc": "markdown-toc --no-first1 -i README.md && markdown-toc --no-first1 -i API.md && markdown-toc --no-first1 -i GUIDE.md && markdown-toc --no-first1 -i CHANGELOG.md && markdown-toc --no-first1 -i FAQ.md ",
|
||||
"build:es5": "babel src --out-dir ./dist/es5/ --presets babel-preset-env --plugins babel-plugin-transform-runtime"
|
||||
},
|
||||
@ -92,5 +96,15 @@
|
||||
"haad <haad@haja.io>",
|
||||
"shamb0t <shams@haja.io>",
|
||||
"hajamark <mark@haja.io>"
|
||||
],
|
||||
"keywords": [
|
||||
"crdt",
|
||||
"database",
|
||||
"decentralized",
|
||||
"decentralised",
|
||||
"distributed",
|
||||
"ipfs",
|
||||
"p2p",
|
||||
"peer-to-peer"
|
||||
]
|
||||
}
|
||||
|
@ -23,12 +23,12 @@ const logger = Logger.create('orbit-db')
|
||||
Logger.setLogLevel('ERROR')
|
||||
|
||||
// Mapping for 'database type' -> Class
|
||||
let databaseTypes = {
|
||||
'counter': CounterStore,
|
||||
'eventlog': EventStore,
|
||||
'feed': FeedStore,
|
||||
'docstore': DocumentStore,
|
||||
'keyvalue': KeyValueStore
|
||||
const databaseTypes = {
|
||||
counter: CounterStore,
|
||||
eventlog: EventStore,
|
||||
feed: FeedStore,
|
||||
docstore: DocumentStore,
|
||||
keyvalue: KeyValueStore
|
||||
}
|
||||
|
||||
class OrbitDB {
|
||||
@ -57,6 +57,20 @@ class OrbitDB {
|
||||
AccessControllers = options.AccessControllers || AccessControllers
|
||||
}
|
||||
|
||||
static get Pubsub () { return Pubsub }
|
||||
static get Cache () { return Cache }
|
||||
static get Keystore () { return Keystore }
|
||||
static get Identities () { return Identities }
|
||||
static get AccessControllers () { return AccessControllers }
|
||||
static get Storage () { return Storage }
|
||||
static get OrbitDBAddress () { return OrbitDBAddress }
|
||||
|
||||
static get EventStore () { return EventStore }
|
||||
static get FeedStore () { return FeedStore }
|
||||
static get KeyValueStore () { return KeyValueStore }
|
||||
static get CounterStore () { return CounterStore }
|
||||
static get DocumentStore () { return DocumentStore }
|
||||
|
||||
get cache () { return this.caches[this.directory].cache }
|
||||
|
||||
static async createInstance (ipfs, options = {}) {
|
||||
@ -67,7 +81,7 @@ class OrbitDB {
|
||||
if (!options.directory) { options.directory = './orbitdb' }
|
||||
|
||||
if (!options.storage) {
|
||||
let storageOptions = {}
|
||||
const storageOptions = {}
|
||||
|
||||
// Create default `level` store
|
||||
options.storage = Storage(null, storageOptions)
|
||||
@ -79,7 +93,7 @@ class OrbitDB {
|
||||
|
||||
if (!options.keystore) {
|
||||
const keystorePath = path.join(options.directory, id, '/keystore')
|
||||
let keyStorage = await options.storage.createStore(keystorePath)
|
||||
const keyStorage = await options.storage.createStore(keystorePath)
|
||||
options.keystore = new Keystore(keyStorage)
|
||||
}
|
||||
|
||||
@ -92,7 +106,7 @@ class OrbitDB {
|
||||
|
||||
if (!options.cache) {
|
||||
const cachePath = path.join(options.directory, id, '/cache')
|
||||
let cacheStorage = await options.storage.createStore(cachePath)
|
||||
const cacheStorage = await options.storage.createStore(cachePath)
|
||||
options.cache = new Cache(cacheStorage)
|
||||
}
|
||||
|
||||
@ -144,13 +158,13 @@ class OrbitDB {
|
||||
|
||||
// Close all open databases
|
||||
const databases = Object.values(this.stores)
|
||||
for (let db of databases) {
|
||||
for (const db of databases) {
|
||||
await db.close()
|
||||
delete this.stores[db.address.toString()]
|
||||
}
|
||||
|
||||
const caches = Object.keys(this.caches)
|
||||
for (let directory of caches) {
|
||||
for (const directory of caches) {
|
||||
await this.caches[directory].cache.close()
|
||||
delete this.caches[directory]
|
||||
}
|
||||
@ -179,7 +193,7 @@ class OrbitDB {
|
||||
}
|
||||
|
||||
async _createCache (path) {
|
||||
let cacheStorage = await this.storage.createStore(path)
|
||||
const cacheStorage = await this.storage.createStore(path)
|
||||
return new Cache(cacheStorage)
|
||||
}
|
||||
|
||||
@ -300,7 +314,7 @@ class OrbitDB {
|
||||
async _determineAddress (name, type, options = {}) {
|
||||
if (!OrbitDB.isValidType(type)) { throw new Error(`Invalid database type '${type}'`) }
|
||||
|
||||
if (OrbitDBAddress.isValid(name)) { throw new Error(`Given database name is an address. Please give only the name of the database!`) }
|
||||
if (OrbitDBAddress.isValid(name)) { throw new Error('Given database name is an address. Please give only the name of the database!') }
|
||||
|
||||
// Create an AccessController, use IPFS AC as the default
|
||||
options.accessController = Object.assign({}, { name: name, type: 'ipfs' }, options.accessController)
|
||||
@ -310,7 +324,7 @@ class OrbitDB {
|
||||
const manifestHash = await createDBManifest(this._ipfs, name, type, accessControllerAddress, options)
|
||||
|
||||
// Create the database address
|
||||
return OrbitDBAddress.parse(path.join('/orbitdb', manifestHash, name))
|
||||
return OrbitDBAddress.parse(OrbitDBAddress.join(manifestHash, name))
|
||||
}
|
||||
|
||||
/* Create and Open databases */
|
||||
@ -322,7 +336,7 @@ class OrbitDB {
|
||||
}
|
||||
*/
|
||||
async create (name, type, options = {}) {
|
||||
logger.debug(`create()`)
|
||||
logger.debug('create()')
|
||||
|
||||
logger.debug(`Creating database '${name}' as ${type}`)
|
||||
|
||||
@ -377,7 +391,7 @@ class OrbitDB {
|
||||
}
|
||||
*/
|
||||
async open (address, options = {}) {
|
||||
logger.debug(`open()`)
|
||||
logger.debug('open()')
|
||||
|
||||
options = Object.assign({ localOnly: false, create: false }, options)
|
||||
logger.debug(`Open database '${address}'`)
|
||||
@ -385,7 +399,7 @@ class OrbitDB {
|
||||
// If address is just the name of database, check the options to crate the database
|
||||
if (!OrbitDBAddress.isValid(address)) {
|
||||
if (!options.create) {
|
||||
throw new Error(`'options.create' set to 'false'. If you want to create a database, set 'options.create' to 'true'.`)
|
||||
throw new Error('\'options.create\' set to \'false\'. If you want to create a database, set \'options.create\' to \'true\'.')
|
||||
} else if (options.create && !options.type) {
|
||||
throw new Error(`Database type not provided! Provide a type with 'options.type' (${OrbitDB.databaseTypes.join('|')})`)
|
||||
} else {
|
||||
@ -419,8 +433,9 @@ class OrbitDB {
|
||||
logger.debug(`Manifest for '${dbAddress}':\n${JSON.stringify(manifest, null, 2)}`)
|
||||
|
||||
// Make sure the type from the manifest matches the type that was given as an option
|
||||
if (manifest.name !== dbAddress.path) { throw new Error(`Manifest '${manifest.name}' cannot be opened as '${dbAddress.path}'`) }
|
||||
if (options.type && manifest.type !== options.type) { throw new Error(`Database '${dbAddress}' is type '${manifest.type}' but was opened as '${options.type}'`) }
|
||||
|
||||
|
||||
// Save the database locally
|
||||
await this._addManifestToCache(options.cache, dbAddress)
|
||||
|
||||
|
@ -6,7 +6,7 @@ const createDBManifest = async (ipfs, name, type, accessControllerAddress, optio
|
||||
const manifest = Object.assign({
|
||||
name: name,
|
||||
type: type,
|
||||
accessController: path.join('/ipfs', accessControllerAddress)
|
||||
accessController: (path.posix || path).join('/ipfs', accessControllerAddress)
|
||||
},
|
||||
// meta field is only added to manifest if options.meta is defined
|
||||
options.meta !== undefined ? { meta: options.meta } : {}
|
||||
|
@ -12,7 +12,7 @@ async function migrate (OrbitDB, options, dbAddress) {
|
||||
let oldStore
|
||||
|
||||
if (!oldCache) {
|
||||
const addr = path.join(OrbitDB.directory, dbAddress.root, dbAddress.path)
|
||||
const addr = (path.posix || path).join(OrbitDB.directory, dbAddress.root, dbAddress.path)
|
||||
if (fs && fs.existsSync && !fs.existsSync(addr)) return
|
||||
oldStore = await OrbitDB.storage.createStore(addr)
|
||||
oldCache = new Cache(oldStore)
|
||||
@ -29,7 +29,7 @@ async function migrate (OrbitDB, options, dbAddress) {
|
||||
'queue'
|
||||
]
|
||||
|
||||
for (let i in migrationKeys) {
|
||||
for (const i in migrationKeys) {
|
||||
try {
|
||||
const key = path.join(keyRoot, migrationKeys[i])
|
||||
const val = await oldCache.get(migrationKeys[i])
|
||||
|
@ -11,10 +11,12 @@ class OrbitDBAddress {
|
||||
}
|
||||
|
||||
toString () {
|
||||
return path.join('/orbitdb', this.root, this.path)
|
||||
return OrbitDBAddress.join(this.root, this.path)
|
||||
}
|
||||
|
||||
static isValid (address) {
|
||||
address = address.toString().replace(/\\/g, '/')
|
||||
|
||||
const containsProtocolPrefix = (e, i) => !((i === 0 || i === 1) && address.toString().indexOf('/orbit') === 0 && e === 'orbitdb')
|
||||
|
||||
const parts = address.toString()
|
||||
@ -40,6 +42,8 @@ class OrbitDBAddress {
|
||||
|
||||
if (!OrbitDBAddress.isValid(address)) { throw new Error(`Not a valid OrbitDB address: ${address}`) }
|
||||
|
||||
address = address.toString().replace(/\\/g, '/')
|
||||
|
||||
const parts = address.toString()
|
||||
.split('/')
|
||||
.filter((e, i) => !((i === 0 || i === 1) && address.toString().indexOf('/orbit') === 0 && e === 'orbitdb'))
|
||||
@ -47,6 +51,10 @@ class OrbitDBAddress {
|
||||
|
||||
return new OrbitDBAddress(parts[0], parts.slice(1, parts.length).join('/'))
|
||||
}
|
||||
|
||||
static join (...paths) {
|
||||
return (path.posix || path).join('/orbitdb', ...paths)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = OrbitDBAddress
|
||||
|
@ -3,10 +3,10 @@
|
||||
<title>Break OrbitDB</title>
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||
<meta content="utf-8" http-equiv="encoding">
|
||||
<script type="text/javascript" src="orbitdb.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="ipfs.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="identities.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="ipfslog.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="orbitdb.js/orbitdb.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="ipfs.js/index.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="identities.js/index-browser.min.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="ipfslog.min.js/ipfslog.min.js" charset="utf-8"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div style="padding: 0px 0px 25px 0px;">
|
||||
|
@ -20,39 +20,47 @@ const {
|
||||
testAPIs,
|
||||
} = require('./utils')
|
||||
|
||||
const dbPath = './orbitdb/tests/create-open'
|
||||
const ipfsPath = './orbitdb/tests/create-open/ipfs'
|
||||
const migrationFixturePath = './test/fixtures/migration/cache-schema-test'
|
||||
const ipfsFixturesDir = './test/fixtures/ipfs'
|
||||
const dbPath = path.join(__dirname, 'orbitdb', 'tests', 'create-open')
|
||||
const ipfsPath = path.join(__dirname, 'orbitdb', 'tests', 'create-open', 'ipfs')
|
||||
const migrationFixturePath = path.join(__dirname, 'fixtures', 'migration', 'cache-schema-test')
|
||||
const ipfsFixturesDir = path.join(__dirname, 'fixtures', 'ipfs')
|
||||
|
||||
Object.keys(testAPIs).forEach(API => {
|
||||
describe(`orbit-db - Create & Open (${API})`, function() {
|
||||
describe(`orbit-db - Create & Open (${API})`, function () {
|
||||
this.retries(1) // windows...
|
||||
this.timeout(config.timeout)
|
||||
|
||||
let ipfsd, ipfs, orbitdb, db, address
|
||||
let localDataPath
|
||||
|
||||
const filterFunc = (src, dest) => {
|
||||
// windows has problems copying these files...
|
||||
return !(src.includes('LOG') || src.includes('LOCK'))
|
||||
}
|
||||
|
||||
|
||||
before(async () => {
|
||||
config.daemon1.repo = ipfsPath
|
||||
rmrf.sync(config.daemon1.repo)
|
||||
rmrf.sync(dbPath)
|
||||
ipfsd = await startIpfs(API, config.daemon1)
|
||||
ipfs = ipfsd.api
|
||||
|
||||
await fs.copy(path.join(ipfsFixturesDir, 'blocks'), path.join(ipfsd.path, 'blocks'))
|
||||
await fs.copy(path.join(ipfsFixturesDir, 'datastore'), path.join(ipfsd.path, 'datastore'))
|
||||
await fs.copy(path.join(ipfsFixturesDir, 'datastore'), path.join(ipfsd.path, 'datastore'), { filter: filterFunc })
|
||||
orbitdb = await OrbitDB.createInstance(ipfs, { directory: dbPath })
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
if(orbitdb)
|
||||
if (orbitdb)
|
||||
await orbitdb.stop()
|
||||
|
||||
if (ipfsd)
|
||||
await stopIpfs(ipfsd)
|
||||
})
|
||||
|
||||
describe('Create', function() {
|
||||
describe('Errors', function() {
|
||||
describe('Create', function () {
|
||||
describe('Errors', function () {
|
||||
it('throws an error if given an invalid database type', async () => {
|
||||
let err
|
||||
try {
|
||||
@ -97,7 +105,7 @@ Object.keys(testAPIs).forEach(API => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('Success', function() {
|
||||
describe('Success', function () {
|
||||
before(async () => {
|
||||
db = await orbitdb.create('second', 'feed', { replicate: false })
|
||||
localDataPath = path.join(dbPath, orbitdb.id, 'cache')
|
||||
@ -122,14 +130,14 @@ Object.keys(testAPIs).forEach(API => {
|
||||
const address = db.id
|
||||
const manifestHash = address.split('/')[2]
|
||||
await db._cache._store.open()
|
||||
const value = await db._cache.get(address + '/_manifest')
|
||||
const value = await db._cache.get(path.join(address, '/_manifest'))
|
||||
assert.equal(value, manifestHash)
|
||||
})
|
||||
|
||||
it('saves database manifest file locally', async () => {
|
||||
const manifestHash = db.id.split('/')[2]
|
||||
const manifest = await io.read(ipfs, manifestHash)
|
||||
assert.notEqual(manifest, )
|
||||
assert.notEqual(manifest)
|
||||
assert.equal(manifest.name, 'second')
|
||||
assert.equal(manifest.type, 'feed')
|
||||
assert.notEqual(manifest.accessController, null)
|
||||
@ -142,7 +150,7 @@ Object.keys(testAPIs).forEach(API => {
|
||||
assert.equal(fs.existsSync(dir), true)
|
||||
})
|
||||
|
||||
it('loads cache from previous version of orbit-db', async() => {
|
||||
it('loads cache from previous version of orbit-db', async () => {
|
||||
const dbName = 'cache-schema-test'
|
||||
|
||||
db = await orbitdb.create(dbName, 'keyvalue')
|
||||
@ -153,7 +161,7 @@ Object.keys(testAPIs).forEach(API => {
|
||||
assert.equal((await db.get('key')), undefined)
|
||||
await db.drop()
|
||||
|
||||
await fs.copy(migrationFixturePath, migrationDataPath)
|
||||
await fs.copy(migrationFixturePath, migrationDataPath, { filter: filterFunc })
|
||||
db = await orbitdb.create(dbName, 'keyvalue')
|
||||
await db.load()
|
||||
|
||||
@ -161,18 +169,18 @@ Object.keys(testAPIs).forEach(API => {
|
||||
assert.equal((await db.get('key')), 'value')
|
||||
})
|
||||
|
||||
it('loads cache from previous version of orbit-db with the directory option', async() => {
|
||||
it('loads cache from previous version of orbit-db with the directory option', async () => {
|
||||
const dbName = 'cache-schema-test2'
|
||||
const directory = path.join(dbPath, "some-other-place")
|
||||
|
||||
await fs.copy(migrationFixturePath, directory)
|
||||
await fs.copy(migrationFixturePath, directory, { filter: filterFunc })
|
||||
db = await orbitdb.create(dbName, 'keyvalue', { directory })
|
||||
await db.load()
|
||||
|
||||
assert.equal((await db.get('key')), 'value')
|
||||
})
|
||||
|
||||
describe('Access Controller', function() {
|
||||
describe('Access Controller', function () {
|
||||
before(async () => {
|
||||
if (db) {
|
||||
await db.drop()
|
||||
@ -204,7 +212,7 @@ Object.keys(testAPIs).forEach(API => {
|
||||
assert.deepEqual(db.access.write, [orbitdb.identity.id])
|
||||
})
|
||||
})
|
||||
describe('Meta', function() {
|
||||
describe('Meta', function () {
|
||||
before(async () => {
|
||||
if (db) {
|
||||
await db.close()
|
||||
@ -237,8 +245,8 @@ Object.keys(testAPIs).forEach(API => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('determineAddress', function() {
|
||||
describe('Errors', function() {
|
||||
describe('determineAddress', function () {
|
||||
describe('Errors', function () {
|
||||
it('throws an error if given an invalid database type', async () => {
|
||||
let err
|
||||
try {
|
||||
@ -260,7 +268,7 @@ Object.keys(testAPIs).forEach(API => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('Success', function() {
|
||||
describe('Success', function () {
|
||||
before(async () => {
|
||||
address = await orbitdb.determineAddress('third', 'feed', { replicate: false })
|
||||
localDataPath = path.join(dbPath, address.root, address.path)
|
||||
@ -279,7 +287,7 @@ Object.keys(testAPIs).forEach(API => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('Open', function() {
|
||||
describe('Open', function () {
|
||||
beforeEach(async () => {
|
||||
db = await orbitdb.open('abc', { create: true, type: 'feed' })
|
||||
})
|
||||
@ -368,7 +376,7 @@ Object.keys(testAPIs).forEach(API => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("Close", function() {
|
||||
describe("Close", function () {
|
||||
before(async () => {
|
||||
if (orbitdb) await orbitdb.stop()
|
||||
orbitdb = await OrbitDB.createInstance(ipfs, { directory: dbPath })
|
||||
@ -389,15 +397,15 @@ Object.keys(testAPIs).forEach(API => {
|
||||
assert.strictEqual(db._cache._store._db.status, 'closed')
|
||||
})
|
||||
|
||||
it('successfully manages multiple caches', async() => {
|
||||
it('successfully manages multiple caches', async () => {
|
||||
// Cleaning up cruft from other tests
|
||||
const directory = path.join(dbPath, "custom-store")
|
||||
const directory2 = path.join(dbPath, "custom-store2")
|
||||
|
||||
const db1 = await orbitdb.open('xyz1', { create: true, type: 'feed', })
|
||||
const db2 = await orbitdb.open('xyz2', { create: true, type: 'feed', directory })
|
||||
const db3 = await orbitdb.open('xyz3', { create: true, type: 'feed', directory })
|
||||
const db4 = await orbitdb.open('xyz4', { create: true, type: 'feed', directory: directory2 })
|
||||
const db3 = await orbitdb.open('xyz3', { create: true, type: 'feed', directory })
|
||||
const db4 = await orbitdb.open('xyz4', { create: true, type: 'feed', directory: directory2 })
|
||||
const db5 = await orbitdb.open('xyz5', { create: true, type: 'feed', })
|
||||
|
||||
await db1.close()
|
||||
|
@ -53,7 +53,7 @@ Object.keys(testAPIs).forEach(API => {
|
||||
describe('addDatabaseType', function () {
|
||||
it('should have the correct custom type', async () => {
|
||||
OrbitDB.addDatabaseType(CustomStore.type, CustomStore)
|
||||
let store = await orbitdb.create(dbPath, CustomStore.type)
|
||||
let store = await orbitdb.create(dbPath.replace(/^\.\//, ''), CustomStore.type)
|
||||
assert.equal(store._type, CustomStore.type)
|
||||
})
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
<EFBFBD>
<12>
|
||||
<EFBFBD>
<12>
|
||||
IPFS -- Inter-Planetary File system
|
||||
|
||||
IPFS is a global, versioned, peer-to-peer filesystem. It combines good ideas
|
||||
|
@ -62,6 +62,20 @@ Object.keys(testAPIs).forEach(API => {
|
||||
assert.equal(result.toString().indexOf('/orbitdb'), 0)
|
||||
assert.equal(result.toString().indexOf('zd'), 9)
|
||||
})
|
||||
|
||||
it('parse address with backslashes (win32) successfully', () => {
|
||||
const address = '\\orbitdb\\Qmdgwt7w4uBsw8LXduzCd18zfGXeTmBsiR8edQ1hSfzcJC\\first-database'
|
||||
const result = OrbitDB.parseAddress(address)
|
||||
|
||||
const isInstanceOf = result instanceof OrbitDBAddress
|
||||
assert.equal(isInstanceOf, true)
|
||||
|
||||
assert.equal(result.root, 'Qmdgwt7w4uBsw8LXduzCd18zfGXeTmBsiR8edQ1hSfzcJC')
|
||||
assert.equal(result.path, 'first-database')
|
||||
|
||||
assert.equal(result.toString().indexOf('/orbitdb'), 0)
|
||||
assert.equal(result.toString().indexOf('Qm'), 9)
|
||||
})
|
||||
})
|
||||
|
||||
describe('isValid Address', () => {
|
||||
@ -97,6 +111,13 @@ Object.keys(testAPIs).forEach(API => {
|
||||
|
||||
assert.equal(result, false)
|
||||
})
|
||||
|
||||
it('validate address with backslashes (win32) successfully', () => {
|
||||
const address = '\\orbitdb\\Qmdgwt7w4uBsw8LXduzCd18zfGXeTmBsiR8edQ1hSfzcJC\\first-database'
|
||||
const result = OrbitDB.isValidAddress(address)
|
||||
|
||||
assert.equal(result, true)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -35,6 +35,7 @@ const ipfsFixturesDir = './test/fixtures/ipfs'
|
||||
|
||||
Object.keys(testAPIs).forEach(API => {
|
||||
describe(`orbit-db - Backward-Compatibility - Open & Load (${API})`, function () {
|
||||
this.retries(1) // windows...
|
||||
this.timeout(config.timeout)
|
||||
|
||||
let ipfsd, ipfs, orbitdb, db, address, store
|
||||
@ -44,9 +45,15 @@ Object.keys(testAPIs).forEach(API => {
|
||||
ipfsd = await startIpfs(API, config.daemon1)
|
||||
ipfs = ipfsd.api
|
||||
rmrf.sync(dbPath)
|
||||
|
||||
const filterFunc = (src, dest) => {
|
||||
// windows has problems copying these files...
|
||||
return !(src.includes('LOG') || src.includes('LOCK'))
|
||||
}
|
||||
|
||||
// copy data files to ipfs and orbitdb repos
|
||||
await fs.copy(path.join(ipfsFixturesDir, 'blocks'), path.join(ipfsd.path, 'blocks'))
|
||||
await fs.copy(path.join(ipfsFixturesDir, 'datastore'), path.join(ipfsd.path, 'datastore'))
|
||||
await fs.copy(path.join(ipfsFixturesDir, 'datastore'), path.join(ipfsd.path, 'datastore'), { filter: filterFunc })
|
||||
await fs.copy(dbFixturesDir, path.join(dbPath, ipfs._peerInfo.id._idB58String, 'cache'))
|
||||
|
||||
store = await storage.createStore(path.join(dbPath, ipfs._peerInfo.id._idB58String, 'keys'))
|
||||
@ -60,14 +67,14 @@ Object.keys(testAPIs).forEach(API => {
|
||||
after(async () => {
|
||||
await store.close()
|
||||
rmrf.sync(dbPath)
|
||||
if(orbitdb)
|
||||
if (orbitdb)
|
||||
await orbitdb.stop()
|
||||
|
||||
if (ipfsd)
|
||||
await stopIpfs(ipfsd)
|
||||
})
|
||||
|
||||
describe('Open & Load', function() {
|
||||
describe('Open & Load', function () {
|
||||
before(async () => {
|
||||
db = await orbitdb.open('/orbitdb/QmWDUfC4zcWJGgc9UHn1X3qQ5KZqBv4KCiCtjnpMmBT8JC/v0-db', { accessController: { type: 'legacy-ipfs', skipManifest: true } })
|
||||
const localFixtures = await db._cache.get('_localHeads')
|
||||
@ -77,6 +84,14 @@ Object.keys(testAPIs).forEach(API => {
|
||||
await db.load()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
if (process.platform === 'win32') {
|
||||
// for some reason Windows does not load the database correctly at the first time.
|
||||
// this is not a good solution but... it works.
|
||||
await db.load()
|
||||
}
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
if (db)
|
||||
await db.close()
|
||||
|
Loading…
x
Reference in New Issue
Block a user