ipfs-repo

IPFS Repo implementation
Table of contents
Install
$ npm i ipfs-repo
This is the implementation of the IPFS repo spec in JavaScript.
Lead Maintainer
Alex Potsides
Background
Here is the architectural reasoning for this repo:
ββββββββββββββββββββββββββββββββββββββββββ
β IPFSRepo β
ββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββ
β / β
βββββββββββββββββββ€
β Datastore β
βββββββββββββββββββ
βββββββββββββ΄ββββββββββββ
βββββββββββββββββββ βββββββββββββββββββ
β /blocks β β /datastore β
βββββββββββββββββββ€ βββββββββββββββββββ€
β Datastore β β LevelDatastore β
βββββββββββββββββββ βββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββββββββ
β IPFSRepo - Default Node.js β β IPFSRepo - Default Browser β
ββββββββββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββ βββββββββββββββββββ
β / β β / β
βββββββββββββββββββ€ βββββββββββββββββββ€
β FsDatastore β β IdbDatastore β
βββββββββββββββββββ βββββββββββββββββββ
βββββββββββββ΄ββββββββββββ βββββββββββββ΄ββββββββββββ
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β /blocks β β /datastore β β /blocks β β /datastore β
βββββββββββββββββββ€ βββββββββββββββββββ€ βββββββββββββββββββ€ βββββββββββββββββββ€
β FlatfsDatastore β βLevelDBDatastore β β IdbDatastore β β IdbDatastore β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
This provides a well defined interface for creating and interacting with an IPFS repo.
> npm install ipfs-repo
import { createRepo } from 'ipfs-repo'
Usage
Example:
import { createRepo } from 'ipfs-repo'
const repo = createRepo('/tmp/ipfs-repo')
await repo.init({ cool: 'config' })
await repo.open()
console.log('repo is ready')
This now has created the following structure, either on disk or as an in memory representation:
βββ blocks
β βββ SHARDING
β βββ _README
βββ config
βββ datastore
βββ keys
βββ version
API
Setup
createRepo(path[, options])
Creates an IPFS Repo.
Arguments:
path
(string, mandatory): the path for this repo
options
(object, optional): may contain the following values
autoMigrate
(bool, defaults to true
): controls automatic migrations of repository.
onMigrationProgress
(function(version, percentComplete, message)): callback function to be notified of migration progress
lock
(Lock or string Deprecated): what type of lock to use. Lock has to be acquired when opening. string can be "fs"
or "memory"
.
storageBackends
(object, optional): may contain the following values, which should each be a class implementing the datastore interface:
root
(defaults to datastore-fs
in Node.js and datastore-level
in the browser). Defines the back-end type used for gets and puts of values at the root (repo.set()
, repo.get()
)
blocks
(defaults to datastore-fs
in Node.js and datastore-level
in the browser). Defines the back-end type used for gets and puts of values at repo.blocks
.
keys
(defaults to datastore-fs
in Node.js and datastore-level
in the browser). Defines the back-end type used for gets and puts of encrypted keys at repo.keys
datastore
(defaults to datastore-level
). Defines the back-end type used as the key-value store used for gets and puts of values at repo.datastore
.
const repo = createRepo('path/to/repo')
Promise repo.init()
Creates the necessary folder structure inside the repo
Promise repo.open()
Locks the repo to prevent conflicts arising from simultaneous access
Promise repo.close()
Unlocks the repo.
Promise<boolean> repo.exists()
Tells whether this repo exists or not. Returned promise resolves to a boolean
Promise<Boolean> repo.isInitialized()
The returned promise resolves to false
if the repo has not been initialized and true
if it has
Repos
Root repo:
Promise repo.put(key, value:Uint8Array)
Put a value at the root of the repo
key
can be a Uint8Array, a string or a Key
Promise<Uint8Array> repo.get(key)
Get a value at the root of the repo
key
can be a Uint8Array, a string or a Key
Blocks
Promise<Block> repo.blocks.put(block:Block)
block
should be of type Block
AsyncIterator<Block> repo.blocks.putMany(source:AsyncIterable<Block>)
Put many blocks.
source
should be an AsyncIterable that yields entries of type Block
Promise<Block> repo.blocks.get(cid:CID)
Get block.
cid
is the content id of type CID
AsyncIterable<Block> repo.blocks.getMany(source:AsyncIterable<CID>)
Get many blocks
source
should be an AsyncIterable that yields entries of type CID
Promise<boolean> repo.blocks.has (cid:CID)
Indicate if a block is present for the passed CID
cid
should be of the type CID
Promise<boolean> repo.blocks.delete (cid:CID)
Deletes a block
cid
should be of the type CID
AsyncIterator<Block|CID> repo.blocks.query (query)
Query what blocks are available in blockstore.
If query.keysOnly
is true, the returned iterator will yield CIDs, otherwise it will yield Blocks
Datastore:
Promise<CID> repo.blocks.delete(cid:CID)
cid
should be of the type CID
Delete a block
AsyncIterator<CID> repo.blocks.deleteMany(source:AsyncIterable<CID>)
source
should be an Iterable or AsyncIterable that yields entries of the type CID
Delete many blocks
Datastore
repo.datastore
This contains a full implementation of the interface-datastore
API.
Config
Instead of using repo.set('config')
this exposes an API that allows you to set and get a decoded config object, as well as, in a safe manner, change any of the config values individually.
Promise repo.config.set(key:String, value:Object)
Set a config value. value
can be any object that is serializable to JSON.
key
is a string specifying the object path. Example:
await repo.config.set('a.b.c', 'c value')
const config = await repo.config.get()
assert.equal(config.a.b.c, 'c value')
Promise repo.config.replace(value:Object)
Set the whole config value. value
can be any object that is serializable to JSON.
Promise<?> repo.config.get(key:String)
Get a config value. Returned promise resolves to the same type that was set before.
key
is a string specifying the object path. Example:
const value = await repo.config.get('a.b.c')
console.log('config.a.b.c = ', value)
Promise<Object> repo.config.getAll()
Get the entire config value.
Promise<boolean> repo.config.exists()
Whether the config sub-repo exists.
Version
Promise<Number> repo.version.get()
Gets the repo version (an integer).
Promise repo.version.set (version:Number)
Sets the repo version
API Addr
Promise<String> repo.apiAddr.get()
Gets the API address.
Promise repo.apiAddr.set(value)
Sets the API address.
value
should be a Multiaddr or a String representing a valid one.
Status
Promise<Object> repo.stat()
Gets the repo status.
Returned promise resolves to an Object
with the following keys:
numObjects
repoPath
repoSize
version
storageMax
Lock
IPFS Repo comes with two built in locks: memory and fs. These can be imported via the following:
import { FSLock } from 'ipfs-repo/locks/fs'
import { MemoryLock } from 'ipfs-repo/locks/memory'
You can also provide your own custom Lock. It must be an object with the following interface:
Promise lock.lock(dir)
Sets the lock if one does not already exist. If a lock already exists, should throw an error.
dir
is a string to the directory the lock should be created at. The repo typically creates the lock at its root.
Returns closer
, where closer
has a close
method for removing the lock.
Promise closer.close()
Closes the lock created by lock.open
If no error was thrown, the lock was successfully removed.
Promise<boolean> lock.locked(dir)
Checks the existence of the lock.
dir
is the path to the directory to check for the lock. The repo typically checks for the lock at its root.
Returned promise resolves to a boolean
indicating the existence of the lock.
Notes
Migrations
When there is a new repo migration and the version of the repo is increased, don't
forget to propagate the changes into the test repo (test/test-repo
).
For tools that run mainly in the browser environment, be aware that disabling automatic
migrations leaves the user with no way to run the migrations because there is no CLI in the browser. In such
a case, you should provide a way to trigger migrations manually.
Contribute
There are some ways you can make this module better:
- Consult our open issues and take on one of them
- Help our tests reach 100% coverage!
This repository falls under the IPFS Code of Conduct.

License
Licensed under either of
Contribute
Feel free to join in. All welcome. Open an issue!
This repository falls under the IPFS Code of Conduct.
