{"id":14384400,"url":"https://github.com/orbitdb-archive/orbit-db-store","last_synced_at":"2025-08-23T17:31:52.231Z","repository":{"id":8398646,"uuid":"58256381","full_name":"orbitdb-archive/orbit-db-store","owner":"orbitdb-archive","description":"Base class for orbit-db data stores","archived":true,"fork":false,"pushed_at":"2023-01-18T20:33:23.000Z","size":4540,"stargazers_count":40,"open_issues_count":11,"forks_count":22,"subscribers_count":10,"default_branch":"main","last_synced_at":"2024-08-29T18:34:18.634Z","etag":null,"topics":["database","datastore","orbitdb","store"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/orbitdb-archive.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-05-07T08:11:20.000Z","updated_at":"2024-02-01T06:55:25.000Z","dependencies_parsed_at":"2023-02-10T17:40:16.766Z","dependency_job_id":null,"html_url":"https://github.com/orbitdb-archive/orbit-db-store","commit_stats":null,"previous_names":["orbitdb-archive/orbit-db-store","orbitdb/orbit-db-store"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orbitdb-archive%2Forbit-db-store","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orbitdb-archive%2Forbit-db-store/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orbitdb-archive%2Forbit-db-store/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/orbitdb-archive%2Forbit-db-store/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/orbitdb-archive","download_url":"https://codeload.github.com/orbitdb-archive/orbit-db-store/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230716494,"owners_count":18269776,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","datastore","orbitdb","store"],"created_at":"2024-08-28T18:01:21.569Z","updated_at":"2024-12-21T12:30:32.287Z","avatar_url":"https://github.com/orbitdb-archive.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# orbit-db-store\n\n[![npm version](https://badge.fury.io/js/orbit-db-store.svg)](https://badge.fury.io/js/orbit-db-store) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/orbitdb/Lobby) [![Matrix](https://img.shields.io/badge/matrix-%23orbitdb%3Apermaweb.io-blue.svg)](https://riot.permaweb.io/#/room/#orbitdb:permaweb.io) \n\nBase class for [orbit-db](https://github.com/orbitdb/orbit-db) data stores. You generally don't need to use this module if you want to use `orbit-db`. This module contains shared methods between all data stores in `orbit-db` and can be used as a base class for a new data model.\n\n### Used in\n- [orbit-db-kvstore](https://github.com/orbitdb/orbit-db-kvstore)\n- [orbit-db-eventstore](https://github.com/orbitdb/orbit-db-eventstore)\n- [orbit-db-feedstore](https://github.com/orbitdb/orbit-db-feedstore)\n- [orbit-db-counterstore](https://github.com/orbitdb/orbit-db-counterstore)\n- [orbit-db-docstore](https://github.com/orbitdb/orbit-db-docstore)\n\n### Requirements\n\n- Node.js \u003e= 8.0.0\n\n## Table of Contents\n\n\u003c!-- toc --\u003e\n\n- [API](#api)\n  * [constructor(ipfs, identity, address, options)](#constructoripfs-identity-address-options)\n  * [Public methods](#public-methods)\n    + [load([amount], [opts])](#loadamount-opts)\n    + [loadMoreFrom(amount, entries)](#loadmorefromamount-entries)\n    + [setIdentity (identity)](#setidentity-identity)\n    + [saveSnapshot()](#savesnapshot)\n    + [loadFromSnapshot()](#loadfromsnapshot)\n    + [close()](#close)\n    + [drop()](#drop)\n    + [sync(heads)](#syncheads)\n  * [Properties](#properties)\n    + [address](#address)\n    + [identity](#identity)\n    + [all](#all)\n    + [type](#type)\n    + [replicationStatus](#replicationstatus)\n  * [Events](#events)\n  * [Private methods](#private-methods)\n    + [_addOperation(data, [options])](#_addoperationdata-options)\n  * [Creating Custom Data Stores](#creating-custom-data-stores)\n- [Contributing](#contributing)\n- [License](#license)\n\n\u003c!-- tocstop --\u003e\n\n## API\n\n### constructor(ipfs, identity, address, options)\n\n**ipfs** can be an [IPFS](https://github.com/ipfs/js-ipfs) instance or an [IPFS-API](https://github.com/ipfs/js-ipfs) instance. **identity** is an instance of [Identity](https://github.com/orbitdb/orbit-db-identity-provider/). **address** is the OrbitDB address to be used for the store.\n\n`options` is an object with the following required properties:\n\n- `cache`: A [Cache](https://github.com/orbitdb/orbit-db-cache) instance to use for storing heads and snapshots.\n- `Index` : By default it uses an instance of [Index](https://github.com/orbitdb/orbit-db-store/blob/master/src/Index.js).\n\nthe following properties are optional:\n\n- `maxHistory` (Integer): The number of entries to load (Default: `-1`).\n- `syncLocal` (Boolean): Load local database before performing any append operations. (Default: `false`).\n- `fetchEntryTimeout` (Integer): The number in `ms` specifying a timeout when fetching entries from IPFS. (Default: `null`).\n- `referenceCount` (Integer): The number of previous ipfs-log entries a new entry should reference (Default: `64`).\n- `replicationConcurrency` (Integer): The number of concurrent replication processes (Default: `128`).\n- `accessController` (Object): An instance of AccessController with the following [interface](https://github.com/orbitdb/orbit-db-access-controllers/blob/master/src/access-controller-interface.js). See [orbit-db-access-controllers](https://github.com/orbitdb/orbit-db-access-controllers) for more information on how to create custom access controllers. By default only the owner will have write access.\n- `sortFn` (Function): A function used to sort ipfs-log entries (Default: `undefined`).\n- `onClose` (Function): A function to be called with a string of the OrbitDB address of the database that is closing.\n- `onDrop` (Function): A function to be called with the orbit-db-store instance when the database is being removed.\n- `onLoad` (Function): A function to be called with the orbit-db-store instance when the database is being loaded.\n\n### Public methods\n\n#### load([amount], [opts])\n\u003e Load the database using locally persisted state.\n\nReturns a **Promise** that resolves once complete. Provide an optional `amount` argument to specify how many entries to load. By default the `maxHistory` option is used. Provide an optional `options` object with a `fetchEntryTimeout` property to be used when loading entries from IPFS.\n\n#### loadMoreFrom(amount, entries)\n\u003e TODO\n\n```javascript\n//TODO\ndb.loadMoreFrom()\n```\n\n#### setIdentity (identity)\n\u003e Set the identity for the database\n\n\n#### saveSnapshot()\n\u003e Save the current state of the database locally.\n\nReturns a **Promise** that resolves to an array containing an object with the following properties:\n\n- `path` of the snapshot file\n- `hash` representing the IPFS Multihash (as a Base58 encoded string) of the snapshot file\n- `size` of the snapshot file\n\n#### loadFromSnapshot()\n\u003e Load the state of the database from a snapshot.\n\nReturns a **Promise** that resolves to a store instance once it has been loaded.\n\n#### close()\n\u003e Uninitialize the store.\n\nReturns a **promise** that resolves once complete. Emits `close` after the store has been uninitialized.\n\n#### drop()\n\u003e Remove the database locally.\n\nReturns a **promise** that resolves once complete. This doesn't remove or delete the database from peers who have replicated the database.\n\n#### sync(heads)\n\u003e Sync this database with entries from **heads** where **heads** is an array of ipfs-log Entries.\n\nUsually, you don't need to call this method manually as OrbitDB takes care of this for you.\n\n### Properties\n\n#### address\n\u003e Get the address of this database.\n\nReturns an object `{ root: \u003cmanifestHash\u003e, path: \u003cpath\u003e }`. Convert to a string with `db.address.toString()`.\n\n```javascript\nconsole.log(db.address.toString())\n// /orbitdb/zdpuB383kQWjyCd5nv4FKqZwe2FH4nqxBBE7kzoDrmdtZ6GPu/databaseName\n```\n\n#### identity\n\nEach store has an `identity` property containing the public key used with this store to sign and access entries. This `publicKey` property of `identity` is the peer/node/user key.\n\n```javascript\nconsole.log(db.identity.publicKey)\n// 042c07044e7ea51a489c02854db5e09f0191690dc59db0afd95328c9db614a2976e088cab7c86d7e48183191258fc59dc699653508ce25bf0369d67f33d5d77839\n```\n\n#### all\n\u003e Get all of the entries in the store index\n\nReturns an array of all store entries within the index.\n\n```javascript\ndb.all\n```\n\n#### type\n\u003e Get the store type\n\nReturns a string of the type of datastore model of the current instance.\n\n```javascript\nconsole.log(db.type) // \"eventlog\"\n```\n\n#### replicationStatus\n\u003e Get database replication status information such as total number of entries and loading progress.\n\nReturns an instance of [ReplicationInfo](https://github.com/orbitdb/orbit-db-store/blob/master/src/replication-info.js).\n\n```javascript\nconsole.log(db.replicationStatus)\n// { buffered: 0, queued: 0, progress: 2, max: 5 }\n```\n\n### Events\n\n  Store has an `events` ([EventEmitter](https://nodejs.org/api/events.html)) object that emits events that describe what's happening in the database.\n\n  - `load` - (address, heads)\n\n    Emitted before loading the database history. **address** is a string of the OrbitDB address being loaded. **heads** is an array of ipfs-log Entries from which the history is loaded from. **heads** is omitted when this event is emitted as a result of `loadFromSnapshot`.\n\n    ```javascript\n    db.events.on('load', (address, heads) =\u003e ... )\n    db.load()\n    ```\n\n  - `ready` - (address, heads)\n\n    Emitted after fully loading the database history. **address** is a string of the OrbitDB address that emitted the event. **heads** is an array of ipfs-log Entries.\n\n    ```javascript\n    db.events.on('ready', (address, heads) =\u003e ... )\n    db.load()\n    ```\n\n  - `load.progress` - (address, hash, entry, progress, total)\n\n    Emitted for each entry during load. **address** is a string of the OrbitDB address that emitted the event. **hash** is the multihash of the entry that was just loaded. **entry** is the ipfs-log Entry that was loaded. **Progress** is the current load count. **Total** is the maximum load count (ie. length of the full database). These are useful eg. for displaying a load progress percentage.\n\n    ```javascript\n    db.events.on('load.progress', (address, hash, entry, progress, total) =\u003e ... )\n    db.load()\n    ```\n\n  - `replicate` - (address, entry)\n\n    Emitted before replicating a part of the database. **address** is a string of the OrbitDB address that emitted the event. **entry** is the ipfs-log Entry that is being processed.\n\n    ```javascript\n    db.events.on('replicate', (address, entry) =\u003e ... )\n    ```\n\n  - `replicate.progress` - (address, hash, entry, progress, total)\n\n    Emitted while replicating a database. **address** is a string of the OrbitDB address of the database that emitted the event. **hash** is the multihash of the entry that was just replicated. **entry** is the ipfs-log Entry that was replicated. **progress** is an integer representing the current progress. **total** is an integer representing the remaining operations.\n\n    ```javascript\n    db.events.on('replicate.progress', (address, hash, entry, progress, total) =\u003e ... )\n    ```\n  - `log.op.${operation}` - (entry)\n  \n    Emitted after an entry was added to the database regardless of whether the entry is added remotely, or locally. `${operation}` is replaced with a specified oplog operation. `none` is specified to listen for a oplog entry without an operation specified. The supported operations are diagrammed in the entry payload.\n    ```javascript\n    db.events.on('log.op.ADD', (id, hash, payload) =\u003e ... )\n    ```\n\n  - `replicated` - (address, count)\n\n    Emitted after the database was synced with an update from a peer database. **address** is a string of the OrbitDB address that emitted the event. **count** number of items replicated. **count** is omitted when this event is emitted as a result of `loadFromSnapshot`.\n\n    ```javascript\n    db.events.on('replicated', (address, count) =\u003e ... )\n    ```\n\n  - `write` - (address, entry, heads)\n\n    Emitted after an entry was added locally to the database. **address** is a string of the OrbitDB address that emitted the event. **entry** is the Entry that was added. **heads** is an array of ipfs-log Entries.\n\n    ```javascript\n    db.events.on('write', (address, entry, heads) =\u003e ... )\n    ```\n\n  - `closed` - (address)\n\n    Emitted once the database has finished closing. **address** is a string of the OrbitDB address that emitted the event.\n\n    ```javascript\n    db.events.on('closed', (address) =\u003e ... )\n    db.close()\n    ```\n\n### Private methods\n\n#### `_addOperation(data, [options])`\n\u003e Add an entry to the store.\n\nReturns a **Promise** that resolves to the IPFS Multihash of the added entry. Takes `data` as a parameter which can be of any type. Provide an optional `options` arguement, which is an object with the following properties:\n\n- `onProgressCallback` (Function): To be called once the data is appended.\n- `pin` (Boolean): To specify whether or not to pin the entry in IPFS. (Default: `false`).\n\n```javascript\nthis._addOperation({\n  op: 'PUT',\n  key: 'greeting',\n  value: 'hello world!'\n});\n```\n\n### Creating Custom Data Stores\nYou can create a custom data stores that stores data in a way you need it to. To do this, you need to import `orbit-db-store` to your custom store and extend your store class from orbit-db-store's `Store`. Below is the `orbit-db-kvstore` which is a custom data store for `orbit-db`.\n\n```javascript\nimport Store from 'orbit-db-store';\nimport KeyValueIndex from './KeyValueIndex.js';\n\nexport default class KeyValueStore extends Store {\n  constructor(ipfs, identity, address, options) {\n    Object.assign(options || {}, { Index: KeyValueIndex });\n    super(ipfs, identity, address, options)\n  }\n\n  get(key) {\n    return this._index.get(key);\n  }\n\n  set(key, data) {\n    this.put(key, data);\n  }\n\n  put(key, data) {\n    return this._addOperation({\n      op: 'PUT',\n      key: key,\n      value: data,\n      meta: {\n        ts: new Date().getTime()\n      }\n    });\n  }\n\n  del(key) {\n    return this._addOperation({\n      op: 'DEL',\n      key: key,\n      value: null,\n      meta: {\n        ts: new Date().getTime()\n      }\n    });\n  }\n}\n```\n\n### Indices\nThe `Store` class instances do not store the current state of the Store.\n\nIndex contains the state of a datastore, ie. what data we currently have.\nIndex receives a call from a Store when the operations log for the Store\nwas updated, ie. new operations were added. In updateIndex, the Index\nimplements its CRDT logic: add, remove or update items in the data\nstructure.\n\nImplementing each CRDT as an Index, we can implement both operation-based\nand state-based CRDTs with the same higher level abstractions. \n\nUsage:\n```javascript\nconst Index = new Index(userId)\n```\n\n### How to implement your own Index\nThe `KeyValueIndex` is implemented as follows and then used by `KeyValueStore`.\n\n```js\nexport default class KeyValueIndex {\n  constructor() {\n    this._index = {}\n  }\n\n  get(key) {\n    return this._index[key]\n  }\n\n  updateIndex(oplog) {\n    oplog.values\n      .slice()\n      .reverse()\n      .reduce((handled, item) =\u003e {\n        if(!handled.includes(item.payload.key)) {\n          handled.push(item.payload.key)\n          if(item.payload.op === 'PUT') {\n            this._index[item.payload.key] = item.payload.value\n          } else if(item.payload.op === 'DEL') {\n            delete this._index[item.payload.key]\n          }\n        }\n        return handled\n      }, [])\n  }\n}\n```\n[KeyValueIndex.js](https://github.com/orbitdb/orbit-db-kvstore/blob/master/src/KeyValueIndex.js)\n\n#### `updateIndex`\nWhenever you call `Store._addOperation` the `data` is stored and \nthen passed as an argument in chronological order into `updateIndex`,\nwhich implements the CRDT logic. \n\n#### `get`\nAn Index can implement whatever querying logic is most opportune or\ndesired by the Developers of that store.\n\nThis querying logic is then implemented in this get.\n\n## Contributing\n\nSee [orbit-db's contributing guideline](https://github.com/orbitdb/orbit-db#contributing).\n\n## License\n\n[MIT](LICENSE) ©️ 2016-2018 Protocol Labs Inc., Haja Networks Oy\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forbitdb-archive%2Forbit-db-store","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Forbitdb-archive%2Forbit-db-store","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forbitdb-archive%2Forbit-db-store/lists"}