Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

chore: update to esm #71

Merged
merged 2 commits into from
Sep 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
node: [12, 14]
node: [14, 16]
fail-fast: true
steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -57,11 +57,13 @@ jobs:
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npx xvfb-maybe aegir test -t electron-main --bail
- run: npm run pretest
- run: npx xvfb-maybe aegir test -t electron-main --bail -f dist/cjs/node-test/*js
test-electron-renderer:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npx xvfb-maybe aegir test -t electron-renderer --bail
- run: npm run pretest
- run: npx xvfb-maybe aegir test -t electron-renderer --bail -f dist/cjs/browser-test/*js
38 changes: 34 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-datastore-core.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-datastore-core)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/ipfs/js-datastore-core/ci?label=ci&style=flat-square)](https://github.com/ipfs/js-datastore-core/actions?query=branch%3Amaster+workflow%3Aci+)

> Wrapping implementations for [interface-datastore](https://github.com/ipfs/interface-datastore).
> Implementations for [interface-datastore](https://github.com/ipfs/js-ipfs-interfaces/packages/interface-datastore).

## Lead Maintainer <!-- omit in toc -->

Expand All @@ -17,6 +17,7 @@
- [Implementations](#implementations)
- [Install](#install)
- [Usage](#usage)
- [BaseDatastore](#basedatastore)
- [Wrapping Stores](#wrapping-stores)
- [Contribute](#contribute)
- [License](#license)
Expand All @@ -38,12 +39,41 @@ $ npm install datastore-core

## Usage


### BaseDatastore

An base store is made available to make implementing your own datastore easier:

```javascript
const { BaseDatastore } from 'datastore-core')

class MyDatastore extends BaseDatastore {
constructor () {
super()
}

async put (key, val) {
// your implementation here
}

async get (key) {
// your implementation here
}

// etc...
}
```

See the [MemoryDatastore](./src/memory.js) for an example of how it is used.

### Wrapping Stores

```js
const MemoryStore = require('interface-datastore').MemoryDatastore
const MountStore = require('datastore-core').MountDatastore
const Key = require('interface-datastore').Key
import { Key } from 'interface-datastore'
import {
MemoryStore,
MountStore
} from 'datastore-core'

const store = new MountStore({prefix: new Key('/a'), datastore: new MemoryStore()})
```
Expand Down
50 changes: 45 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,49 @@
"description": "Wrapper implementation for interface-datastore",
"leadMaintainer": "Alex Potsides <[email protected]>",
"main": "src/index.js",
"type": "module",
"types": "dist/src/index.d.ts",
"exports": {
"./": {
"import": "./src/index.js"
},
"./base": {
"import": "./src/base.js"
},
"./errors": {
"import": "./src/errors.js"
},
"./keytransform": {
"import": "./src/keytransform.js"
},
"./memory": {
"import": "./src/memory.js"
},
"./mount": {
"import": "./src/mount.js"
},
"./namespace": {
"import": "./src/namespace.js"
},
"./shard": {
"import": "./src/shard.js"
},
"./sharding": {
"import": "./src/sharding.js"
},
"./tiered": {
"import": "./src/tiered.js"
}
},
"scripts": {
"prepare": "aegir build --no-bundle",
"clean": "rimraf dist types",
"prepare": "aegir build",
"pretest": "aegir build --no-bundle --esm-tests",
"test": "aegir test",
"test:node": "aegir test -t node",
"test:browser": "aegir test -t browser",
"test:webworker": "aegir test -t webworker",
"lint": "aegir lint",
"lint": "aegir ts -p check && aegir lint",
"release": "aegir release",
"release-minor": "aegir release --type minor",
"release-major": "aegir release --type major",
Expand Down Expand Up @@ -41,13 +76,15 @@
"devDependencies": {
"@types/debug": "^4.1.5",
"aegir": "^35.0.2",
"interface-datastore-tests": "^1.0.0",
"interface-datastore-tests": "^2.0.3",
"it-all": "^1.0.4",
"rimraf": "^3.0.2",
"util": "^0.12.4"
},
"dependencies": {
"debug": "^4.1.1",
"interface-datastore": "^5.1.1",
"err-code": "^3.0.1",
"interface-datastore": "^6.0.2",
"it-drain": "^1.0.4",
"it-filter": "^1.0.2",
"it-map": "^1.0.5",
Expand All @@ -61,7 +98,10 @@
"node": ">=12.0.0"
},
"eslintConfig": {
"extends": "ipfs"
"extends": "ipfs",
"parserOptions": {
"sourceType": "module"
}
},
"contributors": [
"achingbrain <[email protected]>",
Expand Down
226 changes: 226 additions & 0 deletions src/base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
import { sortAll } from './utils.js'
import drain from 'it-drain'
import filter from 'it-filter'
import take from 'it-take'

/**
* @typedef {import('interface-store').Options} Options
* @typedef {import('interface-datastore').Key} Key
* @typedef {import('interface-datastore').Pair} Pair
* @typedef {import('interface-datastore').Datastore} Datastore
* @typedef {import('interface-datastore').Query} Query
* @typedef {import('interface-datastore').KeyQuery} KeyQuery
* @typedef {import('interface-datastore').Batch} Batch
*/

/**
* @template O
* @typedef {import('interface-store').AwaitIterable<O>} AwaitIterable
*/

/**
* @implements {Datastore}
*/
export class BaseDatastore {
/**
* @returns {Promise<void>}
*/
open () {
return Promise.reject(new Error('.open is not implemented'))
}

/**
* @returns {Promise<void>}
*/
close () {
return Promise.reject(new Error('.close is not implemented'))
}

/**
* @param {Key} key
* @param {Uint8Array} val
* @param {Options} [options]
* @returns {Promise<void>}
*/
put (key, val, options) {
return Promise.reject(new Error('.put is not implemented'))
}

/**
* @param {Key} key
* @param {Options} [options]
* @returns {Promise<Uint8Array>}
*/
get (key, options) {
return Promise.reject(new Error('.get is not implemented'))
}

/**
* @param {Key} key
* @param {Options} [options]
* @returns {Promise<boolean>}
*/
has (key, options) {
return Promise.reject(new Error('.has is not implemented'))
}

/**
* @param {Key} key
* @param {Options} [options]
* @returns {Promise<void>}
*/
delete (key, options) {
return Promise.reject(new Error('.delete is not implemented'))
}

/**
* @param {AwaitIterable<Pair>} source
* @param {Options} [options]
* @returns {AsyncIterable<Pair>}
*/
async * putMany (source, options = {}) {
for await (const { key, value } of source) {
await this.put(key, value, options)
yield { key, value }
}
}

/**
* @param {AwaitIterable<Key>} source
* @param {Options} [options]
* @returns {AsyncIterable<Uint8Array>}
*/
async * getMany (source, options = {}) {
for await (const key of source) {
yield this.get(key, options)
}
}

/**
* @param {AwaitIterable<Key>} source
* @param {Options} [options]
* @returns {AsyncIterable<Key>}
*/
async * deleteMany (source, options = {}) {
for await (const key of source) {
await this.delete(key, options)
yield key
}
}

/**
* @returns {Batch}
*/
batch () {
/** @type {Pair[]} */
let puts = []
/** @type {Key[]} */
let dels = []

return {
put (key, value) {
puts.push({ key, value })
},

delete (key) {
dels.push(key)
},
commit: async (options) => {
await drain(this.putMany(puts, options))
puts = []
await drain(this.deleteMany(dels, options))
dels = []
}
}
}

/**
* Extending classes should override `query` or implement this method
*
* @param {Query} q
* @param {Options} [options]
* @returns {AsyncIterable<Pair>}
*/
// eslint-disable-next-line require-yield
async * _all (q, options) {
throw new Error('._all is not implemented')
}

/**
* Extending classes should override `queryKeys` or implement this method
*
* @param {KeyQuery} q
* @param {Options} [options]
* @returns {AsyncIterable<Key>}
*/
// eslint-disable-next-line require-yield
async * _allKeys (q, options) {
throw new Error('._allKeys is not implemented')
}

/**
* @param {Query} q
* @param {Options} [options]
*/
query (q, options) {
let it = this._all(q, options)

if (q.prefix != null) {
it = filter(it, (e) =>
e.key.toString().startsWith(/** @type {string} */ (q.prefix))
)
}

if (Array.isArray(q.filters)) {
it = q.filters.reduce((it, f) => filter(it, f), it)
}

if (Array.isArray(q.orders)) {
it = q.orders.reduce((it, f) => sortAll(it, f), it)
}

if (q.offset != null) {
let i = 0
it = filter(it, () => i++ >= /** @type {number} */ (q.offset))
}

if (q.limit != null) {
it = take(it, q.limit)
}

return it
}

/**
* @param {KeyQuery} q
* @param {Options} [options]
*/
queryKeys (q, options) {
let it = this._allKeys(q, options)

if (q.prefix != null) {
it = filter(it, (key) =>
key.toString().startsWith(/** @type {string} */ (q.prefix))
)
}

if (Array.isArray(q.filters)) {
it = q.filters.reduce((it, f) => filter(it, f), it)
}

if (Array.isArray(q.orders)) {
it = q.orders.reduce((it, f) => sortAll(it, f), it)
}

if (q.offset != null) {
let i = 0
it = filter(it, () => i++ >= /** @type {number} */ (q.offset))
}

if (q.limit != null) {
it = take(it, q.limit)
}

return it
}
}
Loading