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

Commit ace9a06

Browse files
authored
chore: update to esm (#71)
- Refactors everything to esm - Moves memory and base datastores and errors to this module BREAKING CHANGE: deep requires/imports are no longer possible
1 parent 6fa2e7e commit ace9a06

23 files changed

+744
-193
lines changed

.github/workflows/main.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
strategy:
2828
matrix:
2929
os: [windows-latest, ubuntu-latest, macos-latest]
30-
node: [12, 14]
30+
node: [14, 16]
3131
fail-fast: true
3232
steps:
3333
- uses: actions/checkout@v2
@@ -57,11 +57,13 @@ jobs:
5757
steps:
5858
- uses: actions/checkout@v2
5959
- run: npm install
60-
- run: npx xvfb-maybe aegir test -t electron-main --bail
60+
- run: npm run pretest
61+
- run: npx xvfb-maybe aegir test -t electron-main --bail -f dist/cjs/node-test/*js
6162
test-electron-renderer:
6263
needs: check
6364
runs-on: ubuntu-latest
6465
steps:
6566
- uses: actions/checkout@v2
6667
- run: npm install
67-
- run: npx xvfb-maybe aegir test -t electron-renderer --bail
68+
- run: npm run pretest
69+
- run: npx xvfb-maybe aegir test -t electron-renderer --bail -f dist/cjs/browser-test/*js

README.md

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
[![codecov](https://img.shields.io/codecov/c/github/ipfs/js-datastore-core.svg?style=flat-square)](https://codecov.io/gh/ipfs/js-datastore-core)
77
[![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+)
88

9-
> Wrapping implementations for [interface-datastore](https://github.com/ipfs/interface-datastore).
9+
> Implementations for [interface-datastore](https://github.com/ipfs/js-ipfs-interfaces/packages/interface-datastore).
1010
1111
## Lead Maintainer <!-- omit in toc -->
1212

@@ -17,6 +17,7 @@
1717
- [Implementations](#implementations)
1818
- [Install](#install)
1919
- [Usage](#usage)
20+
- [BaseDatastore](#basedatastore)
2021
- [Wrapping Stores](#wrapping-stores)
2122
- [Contribute](#contribute)
2223
- [License](#license)
@@ -38,12 +39,41 @@ $ npm install datastore-core
3839

3940
## Usage
4041

42+
43+
### BaseDatastore
44+
45+
An base store is made available to make implementing your own datastore easier:
46+
47+
```javascript
48+
const { BaseDatastore } from 'datastore-core')
49+
50+
class MyDatastore extends BaseDatastore {
51+
constructor () {
52+
super()
53+
}
54+
55+
async put (key, val) {
56+
// your implementation here
57+
}
58+
59+
async get (key) {
60+
// your implementation here
61+
}
62+
63+
// etc...
64+
}
65+
```
66+
67+
See the [MemoryDatastore](./src/memory.js) for an example of how it is used.
68+
4169
### Wrapping Stores
4270

4371
```js
44-
const MemoryStore = require('interface-datastore').MemoryDatastore
45-
const MountStore = require('datastore-core').MountDatastore
46-
const Key = require('interface-datastore').Key
72+
import { Key } from 'interface-datastore'
73+
import {
74+
MemoryStore,
75+
MountStore
76+
} from 'datastore-core'
4777

4878
const store = new MountStore({prefix: new Key('/a'), datastore: new MemoryStore()})
4979
```

package.json

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,49 @@
44
"description": "Wrapper implementation for interface-datastore",
55
"leadMaintainer": "Alex Potsides <alex.potsides@protocol.ai>",
66
"main": "src/index.js",
7+
"type": "module",
78
"types": "dist/src/index.d.ts",
9+
"exports": {
10+
"./": {
11+
"import": "./src/index.js"
12+
},
13+
"./base": {
14+
"import": "./src/base.js"
15+
},
16+
"./errors": {
17+
"import": "./src/errors.js"
18+
},
19+
"./keytransform": {
20+
"import": "./src/keytransform.js"
21+
},
22+
"./memory": {
23+
"import": "./src/memory.js"
24+
},
25+
"./mount": {
26+
"import": "./src/mount.js"
27+
},
28+
"./namespace": {
29+
"import": "./src/namespace.js"
30+
},
31+
"./shard": {
32+
"import": "./src/shard.js"
33+
},
34+
"./sharding": {
35+
"import": "./src/sharding.js"
36+
},
37+
"./tiered": {
38+
"import": "./src/tiered.js"
39+
}
40+
},
841
"scripts": {
9-
"prepare": "aegir build --no-bundle",
42+
"clean": "rimraf dist types",
43+
"prepare": "aegir build",
44+
"pretest": "aegir build --no-bundle --esm-tests",
1045
"test": "aegir test",
1146
"test:node": "aegir test -t node",
1247
"test:browser": "aegir test -t browser",
1348
"test:webworker": "aegir test -t webworker",
14-
"lint": "aegir lint",
49+
"lint": "aegir ts -p check && aegir lint",
1550
"release": "aegir release",
1651
"release-minor": "aegir release --type minor",
1752
"release-major": "aegir release --type major",
@@ -41,13 +76,15 @@
4176
"devDependencies": {
4277
"@types/debug": "^4.1.5",
4378
"aegir": "^35.0.2",
44-
"interface-datastore-tests": "^1.0.0",
79+
"interface-datastore-tests": "^2.0.3",
4580
"it-all": "^1.0.4",
81+
"rimraf": "^3.0.2",
4682
"util": "^0.12.4"
4783
},
4884
"dependencies": {
4985
"debug": "^4.1.1",
50-
"interface-datastore": "^5.1.1",
86+
"err-code": "^3.0.1",
87+
"interface-datastore": "^6.0.2",
5188
"it-drain": "^1.0.4",
5289
"it-filter": "^1.0.2",
5390
"it-map": "^1.0.5",
@@ -61,7 +98,10 @@
6198
"node": ">=12.0.0"
6299
},
63100
"eslintConfig": {
64-
"extends": "ipfs"
101+
"extends": "ipfs",
102+
"parserOptions": {
103+
"sourceType": "module"
104+
}
65105
},
66106
"contributors": [
67107
"achingbrain <alex@achingbrain.net>",

src/base.js

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
import { sortAll } from './utils.js'
2+
import drain from 'it-drain'
3+
import filter from 'it-filter'
4+
import take from 'it-take'
5+
6+
/**
7+
* @typedef {import('interface-store').Options} Options
8+
* @typedef {import('interface-datastore').Key} Key
9+
* @typedef {import('interface-datastore').Pair} Pair
10+
* @typedef {import('interface-datastore').Datastore} Datastore
11+
* @typedef {import('interface-datastore').Query} Query
12+
* @typedef {import('interface-datastore').KeyQuery} KeyQuery
13+
* @typedef {import('interface-datastore').Batch} Batch
14+
*/
15+
16+
/**
17+
* @template O
18+
* @typedef {import('interface-store').AwaitIterable<O>} AwaitIterable
19+
*/
20+
21+
/**
22+
* @implements {Datastore}
23+
*/
24+
export class BaseDatastore {
25+
/**
26+
* @returns {Promise<void>}
27+
*/
28+
open () {
29+
return Promise.reject(new Error('.open is not implemented'))
30+
}
31+
32+
/**
33+
* @returns {Promise<void>}
34+
*/
35+
close () {
36+
return Promise.reject(new Error('.close is not implemented'))
37+
}
38+
39+
/**
40+
* @param {Key} key
41+
* @param {Uint8Array} val
42+
* @param {Options} [options]
43+
* @returns {Promise<void>}
44+
*/
45+
put (key, val, options) {
46+
return Promise.reject(new Error('.put is not implemented'))
47+
}
48+
49+
/**
50+
* @param {Key} key
51+
* @param {Options} [options]
52+
* @returns {Promise<Uint8Array>}
53+
*/
54+
get (key, options) {
55+
return Promise.reject(new Error('.get is not implemented'))
56+
}
57+
58+
/**
59+
* @param {Key} key
60+
* @param {Options} [options]
61+
* @returns {Promise<boolean>}
62+
*/
63+
has (key, options) {
64+
return Promise.reject(new Error('.has is not implemented'))
65+
}
66+
67+
/**
68+
* @param {Key} key
69+
* @param {Options} [options]
70+
* @returns {Promise<void>}
71+
*/
72+
delete (key, options) {
73+
return Promise.reject(new Error('.delete is not implemented'))
74+
}
75+
76+
/**
77+
* @param {AwaitIterable<Pair>} source
78+
* @param {Options} [options]
79+
* @returns {AsyncIterable<Pair>}
80+
*/
81+
async * putMany (source, options = {}) {
82+
for await (const { key, value } of source) {
83+
await this.put(key, value, options)
84+
yield { key, value }
85+
}
86+
}
87+
88+
/**
89+
* @param {AwaitIterable<Key>} source
90+
* @param {Options} [options]
91+
* @returns {AsyncIterable<Uint8Array>}
92+
*/
93+
async * getMany (source, options = {}) {
94+
for await (const key of source) {
95+
yield this.get(key, options)
96+
}
97+
}
98+
99+
/**
100+
* @param {AwaitIterable<Key>} source
101+
* @param {Options} [options]
102+
* @returns {AsyncIterable<Key>}
103+
*/
104+
async * deleteMany (source, options = {}) {
105+
for await (const key of source) {
106+
await this.delete(key, options)
107+
yield key
108+
}
109+
}
110+
111+
/**
112+
* @returns {Batch}
113+
*/
114+
batch () {
115+
/** @type {Pair[]} */
116+
let puts = []
117+
/** @type {Key[]} */
118+
let dels = []
119+
120+
return {
121+
put (key, value) {
122+
puts.push({ key, value })
123+
},
124+
125+
delete (key) {
126+
dels.push(key)
127+
},
128+
commit: async (options) => {
129+
await drain(this.putMany(puts, options))
130+
puts = []
131+
await drain(this.deleteMany(dels, options))
132+
dels = []
133+
}
134+
}
135+
}
136+
137+
/**
138+
* Extending classes should override `query` or implement this method
139+
*
140+
* @param {Query} q
141+
* @param {Options} [options]
142+
* @returns {AsyncIterable<Pair>}
143+
*/
144+
// eslint-disable-next-line require-yield
145+
async * _all (q, options) {
146+
throw new Error('._all is not implemented')
147+
}
148+
149+
/**
150+
* Extending classes should override `queryKeys` or implement this method
151+
*
152+
* @param {KeyQuery} q
153+
* @param {Options} [options]
154+
* @returns {AsyncIterable<Key>}
155+
*/
156+
// eslint-disable-next-line require-yield
157+
async * _allKeys (q, options) {
158+
throw new Error('._allKeys is not implemented')
159+
}
160+
161+
/**
162+
* @param {Query} q
163+
* @param {Options} [options]
164+
*/
165+
query (q, options) {
166+
let it = this._all(q, options)
167+
168+
if (q.prefix != null) {
169+
it = filter(it, (e) =>
170+
e.key.toString().startsWith(/** @type {string} */ (q.prefix))
171+
)
172+
}
173+
174+
if (Array.isArray(q.filters)) {
175+
it = q.filters.reduce((it, f) => filter(it, f), it)
176+
}
177+
178+
if (Array.isArray(q.orders)) {
179+
it = q.orders.reduce((it, f) => sortAll(it, f), it)
180+
}
181+
182+
if (q.offset != null) {
183+
let i = 0
184+
it = filter(it, () => i++ >= /** @type {number} */ (q.offset))
185+
}
186+
187+
if (q.limit != null) {
188+
it = take(it, q.limit)
189+
}
190+
191+
return it
192+
}
193+
194+
/**
195+
* @param {KeyQuery} q
196+
* @param {Options} [options]
197+
*/
198+
queryKeys (q, options) {
199+
let it = this._allKeys(q, options)
200+
201+
if (q.prefix != null) {
202+
it = filter(it, (key) =>
203+
key.toString().startsWith(/** @type {string} */ (q.prefix))
204+
)
205+
}
206+
207+
if (Array.isArray(q.filters)) {
208+
it = q.filters.reduce((it, f) => filter(it, f), it)
209+
}
210+
211+
if (Array.isArray(q.orders)) {
212+
it = q.orders.reduce((it, f) => sortAll(it, f), it)
213+
}
214+
215+
if (q.offset != null) {
216+
let i = 0
217+
it = filter(it, () => i++ >= /** @type {number} */ (q.offset))
218+
}
219+
220+
if (q.limit != null) {
221+
it = take(it, q.limit)
222+
}
223+
224+
return it
225+
}
226+
}

0 commit comments

Comments
 (0)