mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-03-30 15:08:28 +00:00
188 lines
7.0 KiB
JavaScript
188 lines
7.0 KiB
JavaScript
/**
|
|
* @module OrbitDB
|
|
* @description Provides an interface for users to interact with OrbitDB.
|
|
*/
|
|
import { getDatabaseType } from './databases/index.js'
|
|
import KeyStore from './key-store.js'
|
|
import { Identities } from './identities/index.js'
|
|
import OrbitDBAddress, { isValidAddress } from './address.js'
|
|
import ManifestStore from './manifest-store.js'
|
|
import { createId } from './utils/index.js'
|
|
import pathJoin from './utils/path-join.js'
|
|
import { getAccessController } from './access-controllers/index.js'
|
|
import IPFSAccessController from './access-controllers/ipfs.js'
|
|
|
|
const DefaultDatabaseType = 'events'
|
|
|
|
const DefaultAccessController = IPFSAccessController
|
|
|
|
/**
|
|
* Creates an instance of OrbitDB.
|
|
* @function
|
|
* @param {Object} params One or more parameters for configuring OrbitDB.
|
|
* @param {IPFS} params.ipfs An IPFS instance.
|
|
* @param {string} [params.id] The id of the OrbitDB instance.
|
|
* @param {module:Identities} [params.identities] An Identities instance.
|
|
* @param {string} [params.directory] A location for storing OrbitDB-related
|
|
* data.
|
|
* @return {module:OrbitDB~OrbitDB} An instance of OrbitDB.
|
|
* @throws IPFSinstance is required argument if no IPFS instance is provided.
|
|
* @instance
|
|
*/
|
|
const OrbitDB = async ({ ipfs, id, identities, directory } = {}) => {
|
|
/**
|
|
* @namespace module:OrbitDB~OrbitDB
|
|
* @description The instance returned by {@link module:OrbitDB}.
|
|
*/
|
|
|
|
if (ipfs == null) {
|
|
throw new Error('IPFS instance is a required argument.')
|
|
}
|
|
|
|
id = id || await createId()
|
|
const { id: peerId } = await ipfs.id()
|
|
directory = directory || './orbitdb'
|
|
|
|
let keystore
|
|
|
|
if (identities) {
|
|
keystore = identities.keystore
|
|
} else {
|
|
keystore = await KeyStore({ path: pathJoin(directory, './keystore') })
|
|
identities = await Identities({ ipfs, keystore })
|
|
}
|
|
|
|
const identity = await identities.createIdentity({ id })
|
|
|
|
const manifestStore = await ManifestStore({ ipfs })
|
|
|
|
let databases = {}
|
|
|
|
/**
|
|
* Open a database or create one if it does not already exist.
|
|
*
|
|
* By default, OrbitDB will create a database of type [DefaultDatabaseType]{@link module:OrbitDB~DefaultDatabaseType}:
|
|
* ```
|
|
* const mydb = await orbitdb.open('mydb')
|
|
* ```
|
|
* To create a database of a different type, specify the type param:
|
|
* ```
|
|
* const mydb = await orbitdb.open('mydb', {type: 'documents'})
|
|
* ```
|
|
* The type must be listed in [databaseTypes]{@link module:OrbitDB.databaseTypes} or an error is thrown.
|
|
* To open an existing database, pass its address to the `open` function:
|
|
* ```
|
|
* const existingDB = await orbitdb.open(dbAddress)
|
|
* ```
|
|
* The address of a newly created database can be retrieved using
|
|
* `db.address`.
|
|
* @function
|
|
* @param {string} address The address of an existing database to open, or
|
|
* the name of a new database.
|
|
* @param {Object} params One or more database configuration parameters.
|
|
* @param {string} [params.type=events] The database's type.
|
|
* @param {*} [params.meta={}] The database's metadata. Only applies when
|
|
* creating a database and is not used when opening an existing database.
|
|
* @param {boolean} [params.sync=true] If true, sync databases automatically.
|
|
* Otherwise, false.
|
|
* @param {module:Database} [params.Database=[Events]{@link module:Database.Database-Events}] A Database-compatible
|
|
* module.
|
|
* @param {module:AccessControllers}
|
|
* [params.AccessController=[IPFSAccessController]{@link module:AccessControllers.AccessControllers-IPFS}]
|
|
* An AccessController-compatible module.
|
|
* @param {module:Storage} [params.headsStorage=[ComposedStorage]{@link module:Storage.Storage-Composed}] A compatible storage instance for storing
|
|
* log heads. Defaults to ComposedStorage(LRUStorage, LevelStorage).
|
|
* @param {module:Storage} [params.entryStorage=[ComposedStorage]{@link module:Storage.Storage-Composed}] A compatible storage instance for storing
|
|
* log entries. Defaults to ComposedStorage(LRUStorage, IPFSBlockStorage).
|
|
* @param {module:Storage} [params.indexStorage=[ComposedStorage]{@link module:Storage.Storage-Composed}] A compatible storage instance for storing an " index of log entries. Defaults to ComposedStorage(LRUStorage, LevelStorage).
|
|
* @param {number} [params.referencesCount] The number of references to
|
|
* previous entries that should be stored with this entry.
|
|
* @memberof module:OrbitDB
|
|
* @return {module:Database} A database instance.
|
|
* @throws Unsupported database type if the type specified is not in the list
|
|
* of known databaseTypes.
|
|
* @memberof module:OrbitDB~OrbitDB
|
|
* @instance
|
|
* @async
|
|
*/
|
|
const open = async (address, { type, meta, sync, Database, AccessController, headsStorage, entryStorage, indexStorage, referencesCount } = {}) => {
|
|
let name, manifest, accessController
|
|
|
|
if (databases[address]) {
|
|
return databases[address]
|
|
}
|
|
|
|
if (isValidAddress(address)) {
|
|
// If the address given was a valid OrbitDB address, eg. '/orbitdb/zdpuAuK3BHpS7NvMBivynypqciYCuy2UW77XYBPUYRnLjnw13'
|
|
const addr = OrbitDBAddress(address)
|
|
manifest = await manifestStore.get(addr.hash)
|
|
const acType = manifest.accessController.split('/', 2).pop()
|
|
const acAddress = manifest.accessController.replaceAll(`/${acType}/`, '')
|
|
AccessController = getAccessController(acType)()
|
|
accessController = await AccessController({ orbitdb: { open, identity, ipfs }, identities, address: acAddress })
|
|
name = manifest.name
|
|
type = type || manifest.type
|
|
meta = manifest.meta
|
|
} else {
|
|
// If the address given was not valid, eg. just the name of the database
|
|
type = type || DefaultDatabaseType
|
|
AccessController = AccessController || DefaultAccessController()
|
|
accessController = await AccessController({ orbitdb: { open, identity, ipfs }, identities })
|
|
const m = await manifestStore.create({ name: address, type, accessController: accessController.address, meta })
|
|
manifest = m.manifest
|
|
address = OrbitDBAddress(m.hash)
|
|
name = manifest.name
|
|
meta = manifest.meta
|
|
}
|
|
|
|
Database = Database || getDatabaseType(type)()
|
|
|
|
if (!Database) {
|
|
throw new Error(`Unsupported database type: '${type}'`)
|
|
}
|
|
|
|
address = address.toString()
|
|
|
|
const db = await Database({ ipfs, identity, address, name, access: accessController, directory, meta, syncAutomatically: sync, headsStorage, entryStorage, indexStorage, referencesCount })
|
|
|
|
db.events.on('close', onDatabaseClosed(address))
|
|
|
|
databases[address] = db
|
|
|
|
return db
|
|
}
|
|
|
|
const onDatabaseClosed = (address) => () => {
|
|
delete databases[address]
|
|
}
|
|
|
|
/**
|
|
* Stops OrbitDB, closing the underlying keystore and manifest.
|
|
* @function stop
|
|
* @memberof module:OrbitDB~OrbitDB
|
|
* @instance
|
|
* @async
|
|
*/
|
|
const stop = async () => {
|
|
if (keystore) {
|
|
await keystore.close()
|
|
}
|
|
if (manifestStore) {
|
|
await manifestStore.close()
|
|
}
|
|
databases = {}
|
|
}
|
|
|
|
return {
|
|
open,
|
|
stop,
|
|
ipfs,
|
|
directory,
|
|
keystore,
|
|
identity,
|
|
peerId
|
|
}
|
|
}
|
|
|
|
export { OrbitDB as default, OrbitDBAddress }
|