mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-03-30 15:08:28 +00:00
586 lines
14 KiB
JavaScript
586 lines
14 KiB
JavaScript
import { deepStrictEqual, strictEqual, notStrictEqual } from 'assert'
|
|
import { rimraf } from 'rimraf'
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
import { createOrbitDB, isValidAddress } from '../src/index.js'
|
|
import KeyValueIndexed from '../src/databases/keyvalue-indexed.js'
|
|
import connectPeers from './utils/connect-nodes.js'
|
|
import waitFor from './utils/wait-for.js'
|
|
import createHelia from './utils/create-helia.js'
|
|
|
|
describe('Open databases', function () {
|
|
this.timeout(5000)
|
|
|
|
let ipfs1, ipfs2
|
|
let orbitdb1, orbitdb2
|
|
|
|
before(async () => {
|
|
[ipfs1, ipfs2] = await Promise.all([createHelia(), createHelia()])
|
|
await connectPeers(ipfs1, ipfs2)
|
|
})
|
|
|
|
after(async () => {
|
|
if (ipfs1) {
|
|
await ipfs1.stop()
|
|
}
|
|
if (ipfs2) {
|
|
await ipfs2.stop()
|
|
}
|
|
await rimraf('./orbitdb1')
|
|
await rimraf('./orbitdb2')
|
|
await rimraf('./ipfs1')
|
|
await rimraf('./ipfs2')
|
|
})
|
|
|
|
describe('creating a database instance', () => {
|
|
let db
|
|
|
|
before(async () => {
|
|
orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1', directory: './orbitdb1' })
|
|
db = await orbitdb1.open('helloworld')
|
|
})
|
|
|
|
after(async () => {
|
|
if (db) {
|
|
await db.drop()
|
|
await db.close()
|
|
}
|
|
if (orbitdb1) {
|
|
await orbitdb1.stop()
|
|
}
|
|
await rimraf('./orbitdb1')
|
|
})
|
|
|
|
it('creates a database instance', async () => {
|
|
notStrictEqual(db, undefined)
|
|
})
|
|
|
|
it('has an address', async () => {
|
|
notStrictEqual(db.address, undefined)
|
|
})
|
|
|
|
it('has a valid OrbitDB address', async () => {
|
|
strictEqual(isValidAddress(db.address), true)
|
|
})
|
|
|
|
it('has a name', async () => {
|
|
strictEqual(db.name, 'helloworld')
|
|
})
|
|
|
|
it('has an identity', async () => {
|
|
notStrictEqual(db.identity, undefined)
|
|
})
|
|
|
|
it('has a close function', async () => {
|
|
notStrictEqual(db.close, undefined)
|
|
strictEqual(typeof db.close, 'function')
|
|
})
|
|
|
|
it('has a drop function', async () => {
|
|
notStrictEqual(db.drop, undefined)
|
|
strictEqual(typeof db.drop, 'function')
|
|
})
|
|
|
|
it('has a addOperation function', async () => {
|
|
notStrictEqual(db.addOperation, undefined)
|
|
strictEqual(typeof db.addOperation, 'function')
|
|
})
|
|
|
|
it('has a log', async () => {
|
|
notStrictEqual(db.log, undefined)
|
|
})
|
|
|
|
it('has a log where the logId matches the databaseId', async () => {
|
|
strictEqual(db.log.id, db.address.toString())
|
|
})
|
|
|
|
it('has a events emitter', async () => {
|
|
notStrictEqual(db.events, undefined)
|
|
})
|
|
|
|
it('has a type', async () => {
|
|
notStrictEqual(db.type, undefined)
|
|
})
|
|
|
|
it('has a type that equals the database type', async () => {
|
|
strictEqual(db.type, 'events')
|
|
})
|
|
|
|
it('has a add function', async () => {
|
|
notStrictEqual(db.add, undefined)
|
|
strictEqual(typeof db.add, 'function')
|
|
})
|
|
|
|
it('has a get function', async () => {
|
|
notStrictEqual(db.get, undefined)
|
|
strictEqual(typeof db.get, 'function')
|
|
})
|
|
|
|
it('has an iterator function', async () => {
|
|
notStrictEqual(db.iterator, undefined)
|
|
strictEqual(typeof db.iterator, 'function')
|
|
})
|
|
|
|
it('has an all function', async () => {
|
|
notStrictEqual(db.all, undefined)
|
|
strictEqual(typeof db.all, 'function')
|
|
})
|
|
|
|
it('has a meta object', async () => {
|
|
notStrictEqual(db.meta, undefined)
|
|
strictEqual(typeof db.meta, 'object')
|
|
})
|
|
|
|
it('creates a directory for the database oplog', async () => {
|
|
const expectedPath = path.join(orbitdb1.directory, `./${db.address}`, '/log/_heads')
|
|
const directoryExists = fs.existsSync(expectedPath)
|
|
strictEqual(directoryExists, true)
|
|
})
|
|
})
|
|
|
|
describe('creating a database with meta info in the manifest', () => {
|
|
let db
|
|
const expected = { hello: 'world' }
|
|
|
|
before(async () => {
|
|
orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1', directory: './orbitdb1' })
|
|
db = await orbitdb1.open('helloworld', { meta: expected })
|
|
})
|
|
|
|
after(async () => {
|
|
if (db) {
|
|
await db.drop()
|
|
await db.close()
|
|
}
|
|
if (orbitdb1) {
|
|
await orbitdb1.stop()
|
|
}
|
|
await rimraf('./orbitdb1')
|
|
})
|
|
|
|
it('contains the given meta info', async () => {
|
|
deepStrictEqual(db.meta, expected)
|
|
})
|
|
})
|
|
|
|
describe('opening a database', () => {
|
|
let db
|
|
|
|
const amount = 10
|
|
|
|
before(async () => {
|
|
orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1' })
|
|
db = await orbitdb1.open('helloworld')
|
|
|
|
for (let i = 0; i < amount; i++) {
|
|
await db.add('hello' + i)
|
|
}
|
|
|
|
await db.close()
|
|
})
|
|
|
|
after(async () => {
|
|
if (db) {
|
|
await db.close()
|
|
}
|
|
if (orbitdb1) {
|
|
await orbitdb1.stop()
|
|
}
|
|
await rimraf('./orbitdb')
|
|
})
|
|
|
|
it('returns all entries in the database', async () => {
|
|
db = await orbitdb1.open('helloworld')
|
|
|
|
strictEqual(db.type, 'events')
|
|
strictEqual(db.name, 'helloworld')
|
|
|
|
const expected = []
|
|
for (let i = 0; i < amount; i++) {
|
|
expected.push('hello' + i)
|
|
}
|
|
|
|
const all = []
|
|
for await (const event of db.iterator()) {
|
|
all.unshift(event)
|
|
}
|
|
|
|
deepStrictEqual(all.map(e => e.value), expected)
|
|
})
|
|
|
|
it('re-opens a database by address', async () => {
|
|
const dbReopened = await orbitdb1.open(db.address)
|
|
|
|
strictEqual(dbReopened.address, db.address)
|
|
|
|
dbReopened.close()
|
|
})
|
|
})
|
|
|
|
describe('opening a database as a different user', () => {
|
|
let db, address
|
|
|
|
const amount = 10
|
|
|
|
before(async () => {
|
|
orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1' })
|
|
db = await orbitdb1.open('helloworld2')
|
|
|
|
for (let i = 0; i < amount; i++) {
|
|
await db.add('hello' + i)
|
|
}
|
|
|
|
address = db.address
|
|
|
|
await db.close()
|
|
await orbitdb1.stop()
|
|
|
|
orbitdb2 = await createOrbitDB({ ipfs: ipfs2, id: 'user2' })
|
|
})
|
|
|
|
after(async () => {
|
|
if (db) {
|
|
await db.close()
|
|
}
|
|
if (orbitdb2) {
|
|
await orbitdb2.stop()
|
|
}
|
|
await rimraf('./orbitdb')
|
|
})
|
|
|
|
it('returns all entries in the database', async () => {
|
|
db = await orbitdb2.open(address)
|
|
|
|
strictEqual(db.type, 'events')
|
|
strictEqual(db.name, 'helloworld2')
|
|
|
|
const expected = []
|
|
for (let i = 0; i < amount; i++) {
|
|
expected.push('hello' + i)
|
|
}
|
|
|
|
const all = []
|
|
for await (const event of db.iterator()) {
|
|
all.unshift(event)
|
|
}
|
|
|
|
deepStrictEqual(all.map(e => e.value), expected)
|
|
})
|
|
})
|
|
|
|
describe('opening a replicated database', () => {
|
|
let db1, db2
|
|
let address
|
|
|
|
const amount = 10
|
|
|
|
before(async () => {
|
|
orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1', directory: './orbitdb1' })
|
|
orbitdb2 = await createOrbitDB({ ipfs: ipfs2, id: 'user2', directory: './orbitdb2' })
|
|
db1 = await orbitdb1.open('helloworld2')
|
|
for (let i = 0; i < amount; i++) {
|
|
await db1.add('hello' + i)
|
|
}
|
|
address = db1.address
|
|
})
|
|
|
|
after(async () => {
|
|
if (db1) {
|
|
await db1.close()
|
|
}
|
|
if (db2) {
|
|
await db2.close()
|
|
}
|
|
if (orbitdb1) {
|
|
await orbitdb1.stop()
|
|
}
|
|
if (orbitdb2) {
|
|
await orbitdb2.stop()
|
|
}
|
|
await rimraf('./orbitdb1')
|
|
await rimraf('./orbitdb2')
|
|
})
|
|
|
|
it('replicates the database', async () => {
|
|
console.time('replicate')
|
|
let updateCount = 0
|
|
let connected = false
|
|
|
|
const onError = (err) => {
|
|
console.error(err)
|
|
}
|
|
|
|
const onConnected = async (peerId, heads) => {
|
|
connected = true
|
|
}
|
|
|
|
const onUpdate = (entry) => {
|
|
++updateCount
|
|
}
|
|
|
|
db2 = await orbitdb2.open(address)
|
|
|
|
db2.events.on('error', onError)
|
|
db2.events.on('update', onUpdate)
|
|
db2.events.on('join', onConnected)
|
|
|
|
await waitFor(() => connected, () => true)
|
|
await waitFor(() => updateCount > 0, () => true)
|
|
|
|
const expected = []
|
|
for (let i = 0; i < amount; i++) {
|
|
expected.push('hello' + i)
|
|
}
|
|
|
|
const all = []
|
|
for await (const event of db2.iterator()) {
|
|
all.unshift(event)
|
|
}
|
|
console.timeEnd('replicate')
|
|
|
|
deepStrictEqual(all.map(e => e.value), expected)
|
|
})
|
|
|
|
it('opens the replicated database', async () => {
|
|
if (db1) {
|
|
await db1.drop()
|
|
await db1.close()
|
|
db1 = null
|
|
}
|
|
if (db2) {
|
|
await db2.close()
|
|
}
|
|
if (orbitdb1) {
|
|
await orbitdb1.stop()
|
|
orbitdb1 = null
|
|
}
|
|
|
|
db2 = await orbitdb2.open(address)
|
|
|
|
const expected = []
|
|
for (let i = 0; i < amount; i++) {
|
|
expected.push('hello' + i)
|
|
}
|
|
|
|
const all = []
|
|
for await (const event of db2.iterator()) {
|
|
all.unshift(event)
|
|
}
|
|
|
|
deepStrictEqual(all.map(e => e.value), expected)
|
|
})
|
|
})
|
|
|
|
describe('opening a keyvalue database', () => {
|
|
let db, address
|
|
|
|
const amount = 10
|
|
|
|
before(async () => {
|
|
orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1' })
|
|
db = await orbitdb1.open('helloworld', { type: 'keyvalue' })
|
|
address = db.address
|
|
|
|
for (let i = 0; i < amount; i++) {
|
|
await db.put('key' + i, 'hello' + i)
|
|
}
|
|
|
|
await db.close()
|
|
})
|
|
|
|
after(async () => {
|
|
if (db) {
|
|
await db.close()
|
|
}
|
|
if (orbitdb1) {
|
|
await orbitdb1.stop()
|
|
}
|
|
await rimraf('./orbitdb')
|
|
})
|
|
|
|
it('returns all entries in the database', async () => {
|
|
db = await orbitdb1.open(address)
|
|
|
|
strictEqual(db.type, 'keyvalue')
|
|
strictEqual(db.name, 'helloworld')
|
|
|
|
const expected = []
|
|
for (let i = 0; i < amount; i++) {
|
|
expected.push({ key: 'key' + i, value: 'hello' + i })
|
|
}
|
|
|
|
const all = []
|
|
for await (const { key, value } of db.iterator()) {
|
|
all.unshift({ key, value })
|
|
}
|
|
|
|
deepStrictEqual(all, expected)
|
|
})
|
|
})
|
|
|
|
describe('opening an indexed keyvalue database', () => {
|
|
let db, address
|
|
|
|
const amount = 10
|
|
|
|
before(async () => {
|
|
orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1' })
|
|
db = await orbitdb1.open('helloworld', { Database: KeyValueIndexed() })
|
|
address = db.address
|
|
|
|
for (let i = 0; i < amount; i++) {
|
|
await db.put('key' + i, 'hello' + i)
|
|
}
|
|
|
|
await db.close()
|
|
})
|
|
|
|
after(async () => {
|
|
if (db) {
|
|
await db.close()
|
|
}
|
|
if (orbitdb1) {
|
|
await orbitdb1.stop()
|
|
}
|
|
await rimraf('./index')
|
|
await rimraf('./orbitdb')
|
|
})
|
|
|
|
it('returns all entries in the database and in the index', async () => {
|
|
db = await orbitdb1.open(address, { Database: KeyValueIndexed() })
|
|
|
|
strictEqual(db.address, address)
|
|
strictEqual(db.type, 'keyvalue')
|
|
strictEqual(db.name, 'helloworld')
|
|
|
|
const expected = []
|
|
for (let i = 0; i < amount; i++) {
|
|
expected.push({ key: 'key' + i, value: 'hello' + i })
|
|
}
|
|
|
|
const result = []
|
|
for await (const { key, value } of db.iterator()) {
|
|
result.unshift({ key, value })
|
|
}
|
|
|
|
deepStrictEqual(result, expected)
|
|
})
|
|
})
|
|
|
|
describe('opening an documents database', () => {
|
|
let db, address
|
|
|
|
const amount = 10
|
|
|
|
before(async () => {
|
|
orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1' })
|
|
db = await orbitdb1.open('helloworld', { type: 'documents' })
|
|
address = db.address
|
|
|
|
for (let i = 0; i < amount; i++) {
|
|
await db.put({ _id: 'hello' + i, msg: 'hello' + i })
|
|
}
|
|
|
|
await db.close()
|
|
})
|
|
|
|
after(async () => {
|
|
if (db) {
|
|
await db.close()
|
|
}
|
|
if (orbitdb1) {
|
|
await orbitdb1.stop()
|
|
}
|
|
await rimraf('./orbitdb')
|
|
})
|
|
|
|
it('returns all entries in the database', async () => {
|
|
db = await orbitdb1.open(address)
|
|
|
|
strictEqual(db.type, 'documents')
|
|
strictEqual(db.name, 'helloworld')
|
|
|
|
const expected = []
|
|
for (let i = 0; i < amount; i++) {
|
|
expected.push({ _id: 'hello' + i, msg: 'hello' + i })
|
|
}
|
|
|
|
const all = []
|
|
for await (const doc of db.iterator()) {
|
|
all.unshift(doc)
|
|
}
|
|
|
|
deepStrictEqual(all.map(e => e.value), expected)
|
|
})
|
|
})
|
|
|
|
describe('opening same database', () => {
|
|
let db1, db2
|
|
|
|
before(async () => {
|
|
orbitdb1 = await createOrbitDB({ ipfs: ipfs1, id: 'user1' })
|
|
})
|
|
|
|
after(async () => {
|
|
if (db1) {
|
|
await db1.close()
|
|
}
|
|
if (db2) {
|
|
await db2.close()
|
|
}
|
|
if (orbitdb1) {
|
|
await orbitdb1.stop()
|
|
}
|
|
await rimraf('./orbitdb')
|
|
})
|
|
|
|
it('returns the database instance when opened with a name multiple times', async () => {
|
|
let err
|
|
|
|
try {
|
|
db1 = await orbitdb1.open('helloworld1')
|
|
db2 = await orbitdb1.open('helloworld1')
|
|
} catch (e) {
|
|
err = e
|
|
}
|
|
|
|
strictEqual(err, undefined)
|
|
strictEqual(db1.name, 'helloworld1')
|
|
strictEqual(db2.name, 'helloworld1')
|
|
strictEqual(db1.address, db2.address)
|
|
})
|
|
})
|
|
|
|
describe('opening same database after stopping OrbitDB', () => {
|
|
let orbitdb
|
|
let db
|
|
|
|
after(async () => {
|
|
if (db) {
|
|
await db.close()
|
|
}
|
|
if (orbitdb) {
|
|
await orbitdb.stop()
|
|
}
|
|
await rimraf('./orbitdb')
|
|
})
|
|
|
|
it('returns the database instance', async () => {
|
|
let err
|
|
|
|
try {
|
|
orbitdb = await createOrbitDB({ ipfs: ipfs1, id: 'user1' })
|
|
db = await orbitdb.open('helloworld1')
|
|
await orbitdb.stop()
|
|
orbitdb = await createOrbitDB({ ipfs: ipfs1, id: 'user1' })
|
|
db = await orbitdb.open('helloworld1')
|
|
} catch (e) {
|
|
err = e
|
|
}
|
|
|
|
strictEqual(err, undefined)
|
|
strictEqual(db.name, 'helloworld1')
|
|
})
|
|
})
|
|
})
|