Merge pull request #86 from orbitdb/module-loaders-retrieval

Module loaders retrieval
This commit is contained in:
Hayden Young 2023-06-22 04:23:44 +08:00 committed by GitHub
commit bb0b65a158
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 141 additions and 168 deletions

View File

@ -1,21 +1,30 @@
/**
* @module AccessControllers
* @description
* Provides a platform for managing access controllers. Supported access
* Provides a system for managing access controllers. Supported access
* controllers can be added and removed from the access controller list, and
* can load the associated module if they are supported.
*
* An AccessController module needs to only expose one function,
* canAppend(entry) which returns true if the entry can be appended to the
* oplog, or false otherwise:
* ```javascript
* const CustomAccessController = ({ write } = {}) => async => {
* An AccessController module needs to only expose one constant, type, and one function, canAppend(entry), which returns true if the entry can be appended to
* the oplog, or false otherwise:
* ```js
* type = 'custom'
*
* const CustomAccessController = ({ write } = {}) => async ({ orbitdb, identities, address }) => {
* const canAppend = async (entry) => {
* // Use entry.identity to determine whether the entry can be appended.
* // Return true if entry can be appended to OpLog.
* // Or return false otherwise.
* }
*
* return {
* canAppend,
* type
* }
* }
*
* export default CustomAccessController
* ```
*/
import IPFSAccessController from './ipfs.js'
import OrbitDBAccessController from './orbitdb.js'
@ -37,7 +46,7 @@ const accessControllers = {
* @return {AccessController} The access controller module.
*/
const getAccessController = (type) => {
if (!Object.keys(accessControllers).includes(type)) {
if (!accessControllers[type]) {
throw new Error(`AccessController type '${type}' is not supported`)
}
return accessControllers[type]
@ -53,12 +62,12 @@ const getAccessController = (type) => {
* controller module does not implement a type property.
*/
const addAccessController = (accessController) => {
if (accessControllers[accessController.type]) {
throw new Error(`Access controller '${accessController.type}' already added.`)
if (!accessController.type) {
throw new Error('Access controller does not contain required field \'type\'')
}
if (!accessController.type) {
throw new Error('Given AccessController class needs to implement: type.')
if (accessControllers[accessController.type]) {
throw new Error(`Access controller '${accessController.type}' already added.`)
}
accessControllers[accessController.type] = accessController
@ -73,8 +82,9 @@ const removeAccessController = type => {
}
export {
accessControllers,
getAccessController,
addAccessController,
removeAccessController
removeAccessController,
IPFSAccessController,
OrbitDBAccessController
}

View File

@ -1,4 +1,53 @@
export { default as Documents } from './documents.js'
export { default as Events } from './events.js'
export { default as KeyValue } from './keyvalue.js'
export { default as KeyValueIndexed } from './keyvalue-indexed.js'
import Documents from './documents.js'
import Events from './events.js'
import KeyValue from './keyvalue.js'
import KeyValueIndexed from './keyvalue-indexed.js'
/**
* An array of available database types.
* @name databaseTypes
* @ype []
* @return [] An array of database types.
* @memberof module:OrbitDB
*/
const databaseTypes = {
events: Events,
documents: Documents,
keyvalue: KeyValue,
keyvalueindexed: KeyValueIndexed
}
/**
* Add a new database type.
* @example
* import { addDatabaseType } from 'orbit-db'
* const CustomDBTypeModule = async (params) => {
* const database = await Database(...params)
* ...
* }
* addDatabaseType('customDBType', CustomDBTypeModule)
* @function addDatabaseType
* @param {string} type The database type.
* @param {module:Database} store A Database-compatible module.
* @memberof module:OrbitDB
*/
const addDatabaseType = (type, store) => {
if (databaseTypes[type]) {
throw new Error(`Type already exists: ${type}`)
}
databaseTypes[type] = store
}
const getDatabaseType = (type) => {
if (!type) {
throw new Error('Type not specified')
}
if (!databaseTypes[type]) {
throw new Error(`Unsupported database type: '${type}'`)
}
return databaseTypes[type]
}
export { addDatabaseType, getDatabaseType, Documents, Events, KeyValue, KeyValueIndexed }

View File

@ -13,7 +13,7 @@
* const Partial = KeyValueIndexed({ storage })
* const keyValueIndexed = await Partial({ ipfs })
*/
import { KeyValue } from './index.js'
import KeyValue from './keyvalue.js'
import LevelStorage from '../storage/level.js'
import pathJoin from '../utils/path-join.js'

View File

@ -5,7 +5,7 @@
* details and providers.
*/
import Identity, { isIdentity, isEqual, decodeIdentity } from './identity.js'
import { getProviderFor } from './providers/index.js'
import { getIdentityProvider } from './providers/index.js'
// import DIDIdentityProvider from './identity-providers/did.js'
// import EthIdentityProvider from './identity-providers/ethereum.js'
import KeyStore, { signMessage, verifyMessage } from '../key-store.js'
@ -75,7 +75,7 @@ const Identities = async ({ keystore, path, storage, ipfs } = {}) => {
options.keystore = keystore
const type = options.type || DefaultProviderType
const Provider = getProviderFor(type).default
const Provider = getIdentityProvider(type).default
const identityProvider = Provider(options)
const id = await identityProvider.getId(options)
const privateKey = await keystore.getKey(id) || await keystore.createKey(id)
@ -117,7 +117,7 @@ const Identities = async ({ keystore, path, storage, ipfs } = {}) => {
return isEqual(identity, verifiedIdentity)
}
const Provider = getProviderFor(identity.type)
const Provider = getIdentityProvider(identity.type)
const identityVerified = await Provider.verifyIdentity(identity)
if (identityVerified) {

View File

@ -33,12 +33,12 @@ const hashStringEncoding = base58btc
* @instance
*/
const Identity = async ({ id, publicKey, signatures, type, sign, verify } = {}) => {
if (id == null) throw new Error('Identity id is required')
if (publicKey == null) throw new Error('Invalid public key')
if (signatures == null) throw new Error('Signatures object is required')
if (signatures.id == null) throw new Error('Signature of id is required')
if (signatures.publicKey == null) throw new Error('Signature of publicKey+id is required')
if (type == null) throw new Error('Identity type is required')
if (!id) throw new Error('Identity id is required')
if (!publicKey) throw new Error('Invalid public key')
if (!signatures) throw new Error('Signatures object is required')
if (!signatures.id) throw new Error('Signature of id is required')
if (!signatures.publicKey) throw new Error('Signature of publicKey+id is required')
if (!type) throw new Error('Identity type is required')
signatures = Object.assign({}, signatures)
@ -90,14 +90,14 @@ const decodeIdentity = async (bytes) => {
* @static
*/
const isIdentity = (identity) => {
return identity.id != null &&
identity.hash != null &&
identity.bytes != null &&
identity.publicKey != null &&
identity.signatures != null &&
identity.signatures.id != null &&
identity.signatures.publicKey != null &&
identity.type != null
return Boolean(identity.id &&
identity.hash &&
identity.bytes &&
identity.publicKey &&
identity.signatures &&
identity.signatures.id &&
identity.signatures.publicKey &&
identity.type)
}
/**

View File

@ -7,7 +7,7 @@ export {
} from './identity.js'
export {
PublicKeyIdentityProvider,
addIdentityProvider,
identityProviders
getIdentityProvider,
PublicKeyIdentityProvider
} from './providers/index.js'

View File

@ -74,7 +74,7 @@ const isProviderSupported = (type) => {
* not supported.
* @static
*/
const getProviderFor = (type) => {
const getIdentityProvider = (type) => {
if (!isProviderSupported(type)) {
throw new Error(`IdentityProvider type '${type}' is not supported`)
}
@ -108,6 +108,4 @@ const addIdentityProvider = (IdentityProvider) => {
identityProviders[IdentityProvider.type] = IdentityProvider
}
// export { default as DIDIdentityProvider } from './did.js'
// export { default as EthIdentityProvider } from './ethereum.js'
export { identityProviders, addIdentityProvider, getProviderFor, PublicKeyIdentityProvider }
export { addIdentityProvider, getIdentityProvider, PublicKeyIdentityProvider }

View File

@ -1,9 +1,15 @@
export {
default as OrbitDB,
databaseTypes,
addDatabaseType
default as OrbitDB
} from './orbitdb.js'
export {
Documents,
Events,
KeyValue,
KeyValueIndexed,
addDatabaseType
} from './db/index.js'
export {
default as OrbitDBAddress,
isValidAddress,
@ -19,15 +25,15 @@ export { default as KeyStore } from './key-store.js'
export {
addAccessController,
removeAccessController,
getAccessController,
accessControllers
IPFSAccessController,
OrbitDBAccessController
} from './access-controllers/index.js'
export {
Identities,
isIdentity,
identityProviders,
addIdentityProvider
addIdentityProvider,
PublicKeyIdentityProvider
} from './identities/index.js'
export {

View File

@ -48,7 +48,7 @@
* const orbitdb = await OrbitDB({ ipfs, identities, id: 'userA' })
* const mydb = await orbitdb.open('mydb')
*/
import { Events, KeyValue, Documents } from './db/index.js'
import { getDatabaseType } from './db/index.js'
import KeyStore from './key-store.js'
import { Identities } from './identities/index.js'
import OrbitDBAddress, { isValidAddress } from './address.js'
@ -58,40 +58,6 @@ import pathJoin from './utils/path-join.js'
import { getAccessController } from './access-controllers/index.js'
import IPFSAccessController from './access-controllers/ipfs.js'
/**
* An array of available database types.
* @name databaseTypes
* @ype []
* @return [] An array of database types.
* @memberof module:OrbitDB
*/
const databaseTypes = {
events: Events,
documents: Documents,
keyvalue: KeyValue
}
/**
* Add a new database type.
* @example
* import { addDatabaseType } from 'orbit-db'
* const CustomDBTypeModule = async (params) => {
* const database = await Database(...params)
* ...
* }
* addDatabaseType('customDBType', CustomDBTypeModule)
* @function addDatabaseType
* @param {string} type The database type.
* @param {module:Database} store A Database-compatible module.
* @memberof module:OrbitDB
*/
const addDatabaseType = (type, store) => {
if (databaseTypes[type]) {
throw new Error(`Type already exists: ${type}`)
}
databaseTypes[type] = store
}
const DefaultDatabaseType = 'events'
const DefaultAccessController = IPFSAccessController
@ -181,10 +147,6 @@ const OrbitDB = async ({ ipfs, id, identities, directory } = {}) => {
const open = async (address, { type, meta, sync, Database, AccessController, headsStorage, entryStorage, indexStorage, referencesCount } = {}) => {
let name, manifest, accessController
if (type && !databaseTypes[type]) {
throw new Error(`Unsupported database type: '${type}'`)
}
if (databases[address]) {
return databases[address]
}
@ -212,7 +174,7 @@ const OrbitDB = async ({ ipfs, id, identities, directory } = {}) => {
meta = manifest.meta
}
Database = Database || databaseTypes[type]()
Database = Database || getDatabaseType(type)()
if (!Database) {
throw new Error(`Unsupported database type: '${type}'`)
@ -261,4 +223,4 @@ const OrbitDB = async ({ ipfs, id, identities, directory } = {}) => {
}
}
export { OrbitDB as default, OrbitDBAddress, addDatabaseType, databaseTypes }
export { OrbitDB as default, OrbitDBAddress }

View File

@ -3,7 +3,7 @@ import rmrf from 'rimraf'
import { copy } from 'fs-extra'
import * as IPFS from 'ipfs-core'
import { KeyStore, Identities } from '../../src/index.js'
import { Documents } from '../../src/db/index.js'
import Documents from '../../src/db/documents.js'
import config from '../config.js'
import testKeysPath from '../fixtures/test-keys-path.js'

View File

@ -3,7 +3,7 @@ import rmrf from 'rimraf'
import { copy } from 'fs-extra'
import * as IPFS from 'ipfs-core'
import { KeyStore, Identities } from '../../src/index.js'
import { Events } from '../../src/db/index.js'
import Events from '../../src/db/events.js'
import config from '../config.js'
import testKeysPath from '../fixtures/test-keys-path.js'

View File

@ -5,7 +5,7 @@ import rmrf from 'rimraf'
import { copy } from 'fs-extra'
import * as IPFS from 'ipfs-core'
import { KeyStore, Identities, MemoryStorage } from '../../src/index.js'
import { KeyValueIndexed } from '../../src/db/index.js'
import KeyValueIndexed from '../../src/db/keyvalue-indexed.js'
import config from '../config.js'
import testKeysPath from '../fixtures/test-keys-path.js'

View File

@ -3,7 +3,7 @@ import rmrf from 'rimraf'
import { copy } from 'fs-extra'
import * as IPFS from 'ipfs-core'
import { KeyStore, Identities } from '../../src/index.js'
import { KeyValue } from '../../src/db/index.js'
import KeyValue from '../../src/db/keyvalue.js'
import config from '../config.js'
import testKeysPath from '../fixtures/test-keys-path.js'

View File

@ -3,7 +3,7 @@ import rmrf from 'rimraf'
import { copy } from 'fs-extra'
import * as IPFS from 'ipfs-core'
import { KeyStore, Identities } from '../../../src/index.js'
import { Documents } from '../../../src/db/index.js'
import Documents from '../../../src/db/documents.js'
import config from '../../config.js'
import testKeysPath from '../../fixtures/test-keys-path.js'
import connectPeers from '../../utils/connect-nodes.js'

View File

@ -3,7 +3,7 @@ import rmrf from 'rimraf'
import { copy } from 'fs-extra'
import * as IPFS from 'ipfs-core'
import { KeyStore, Identities } from '../../../src/index.js'
import { Events } from '../../../src/db/index.js'
import Events from '../../../src/db/events.js'
import config from '../../config.js'
import testKeysPath from '../../fixtures/test-keys-path.js'
import connectPeers from '../../utils/connect-nodes.js'

View File

@ -3,7 +3,7 @@ import rmrf from 'rimraf'
import { copy } from 'fs-extra'
import * as IPFS from 'ipfs-core'
import { KeyStore, Identities } from '../../../src/index.js'
import { KeyValueIndexed } from '../../../src/db/index.js'
import KeyValueIndexed from '../../../src/db/keyvalue-indexed.js'
import config from '../../config.js'
import testKeysPath from '../../fixtures/test-keys-path.js'
import connectPeers from '../../utils/connect-nodes.js'

View File

@ -3,7 +3,7 @@ import rmrf from 'rimraf'
import { copy } from 'fs-extra'
import * as IPFS from 'ipfs-core'
import { KeyStore, Identities } from '../../../src/index.js'
import { KeyValue } from '../../../src/db/index.js'
import KeyValue from '../../../src/db/keyvalue.js'
import config from '../../config.js'
import testKeysPath from '../../fixtures/test-keys-path.js'
import connectPeers from '../../utils/connect-nodes.js'

View File

@ -3,11 +3,11 @@ import rmrf from 'rimraf'
import { copy } from 'fs-extra'
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
import KeyStore, { signMessage, verifyMessage } from '../../src/key-store.js'
import { Identities, identityProviders, addIdentityProvider, Identity, PublicKeyIdentityProvider } from '../../src/identities/index.js'
import { Identities, addIdentityProvider, getIdentityProvider, Identity } from '../../src/identities/index.js'
import testKeysPath from '../fixtures/test-keys-path.js'
import { CustomIdentityProvider, FakeIdentityProvider } from '../fixtures/providers.js'
const type = PublicKeyIdentityProvider.type
const type = 'publickey'
const keysPath = './testkeys'
describe('Identities', function () {
@ -15,15 +15,6 @@ describe('Identities', function () {
await copy(testKeysPath, keysPath)
})
afterEach(async () => {
// reset the identityProviders.
for (const [key] of Object.entries(identityProviders)) {
if (key !== 'publickey') {
delete identityProviders[key]
}
}
})
after(async () => {
await rmrf(keysPath)
})
@ -335,14 +326,10 @@ describe('Identities', function () {
})
describe('manage identity providers', () => {
it('has default identity providers', () => {
assert.deepStrictEqual(identityProviders, { publickey: PublicKeyIdentityProvider })
})
it('can add an identity provider', () => {
addIdentityProvider(CustomIdentityProvider)
assert.deepStrictEqual(identityProviders, { publickey: PublicKeyIdentityProvider, custom: CustomIdentityProvider })
assert.deepStrictEqual(getIdentityProvider('custom'), CustomIdentityProvider)
})
})
})

View File

@ -2,7 +2,7 @@ import { strictEqual, deepStrictEqual, notStrictEqual } from 'assert'
import rmrf from 'rimraf'
import * as IPFS from 'ipfs-core'
import OrbitDB from '../src/orbitdb.js'
import { accessControllers, addAccessController, removeAccessController } from '../src/access-controllers/index.js'
import { IPFSAccessController, OrbitDBAccessController, addAccessController, getAccessController, removeAccessController } from '../src/access-controllers/index.js'
import config from './config.js'
import pathJoin from '../src/utils/path-join.js'
@ -47,12 +47,8 @@ describe('Add a custom access controller', function () {
describe('Default supported access controllers', function () {
it('returns default supported access controllers', async () => {
const expected = [
'ipfs',
'orbitdb'
]
deepStrictEqual(Object.keys(accessControllers), expected)
deepStrictEqual(getAccessController('ipfs'), IPFSAccessController)
deepStrictEqual(getAccessController('orbitdb'), OrbitDBAccessController)
})
it('throws and error if custom access controller hasn\'t been added', async () => {
@ -93,24 +89,20 @@ describe('Add a custom access controller', function () {
})
it('returns custom access controller after adding it', async () => {
const expected = [
'ipfs',
'orbitdb',
type
]
deepStrictEqual(Object.keys(accessControllers), expected)
deepStrictEqual(getAccessController(type), CustomAccessController)
})
it('can be removed from supported access controllers', async () => {
const expected = [
'ipfs',
'orbitdb'
]
let err
removeAccessController(type)
deepStrictEqual(Object.keys(accessControllers), expected)
try {
getAccessController(type)
} catch (e) {
err = e.toString()
}
deepStrictEqual(err, 'Error: AccessController type \'custom!\' is not supported')
})
})
})

View File

@ -1,7 +1,8 @@
import { strictEqual, deepStrictEqual, notStrictEqual } from 'assert'
import rmrf from 'rimraf'
import * as IPFS from 'ipfs-core'
import { OrbitDB, addDatabaseType, databaseTypes, Database } from '../src/index.js'
import { getDatabaseType } from '../src/db/index.js'
import { OrbitDB, addDatabaseType, Database } from '../src/index.js'
import config from './config.js'
const type = 'custom!'
@ -35,24 +36,11 @@ describe('Add a custom database type', function () {
await ipfs.stop()
}
// Remove the added custom database type from OrbitDB import
delete databaseTypes[CustomStore.type]
await rmrf('./orbitdb')
await rmrf('./ipfs1')
})
describe('Default supported database types', function () {
it('returns default supported database types', async () => {
const expected = [
'events',
'documents',
'keyvalue'
]
deepStrictEqual(Object.keys(databaseTypes), expected)
})
it('throws and error if custom database type hasn\'t been added', async () => {
let err
try {
@ -90,26 +78,7 @@ describe('Add a custom database type', function () {
})
it('returns custom database type after adding it', async () => {
const expected = [
'events',
'documents',
'keyvalue',
type
]
deepStrictEqual(Object.keys(databaseTypes), expected)
})
it('can be removed from supported database types', async () => {
const expected = [
'events',
'documents',
'keyvalue'
]
delete databaseTypes[type]
deepStrictEqual(Object.keys(databaseTypes), expected)
deepStrictEqual(getDatabaseType(type), CustomStore)
})
})
})

View File

@ -4,7 +4,7 @@ import fs from 'fs'
import path from 'path'
import * as IPFS from 'ipfs-core'
import { OrbitDB, isValidAddress, LevelStorage } from '../src/index.js'
import { KeyValueIndexed } from '../src/db/index.js'
import KeyValueIndexed from '../src/db/keyvalue-indexed.js'
import config from './config.js'
import connectPeers from './utils/connect-nodes.js'
import waitFor from './utils/wait-for.js'