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

deps!: update to interface-datastore 8.x.x #172

Merged
merged 4 commits into from
Mar 13, 2023
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
18 changes: 6 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"import": "./src/index.js"
"import": "./dist/src/index.js"
}
},
"eslintConfig": {
Expand Down Expand Up @@ -161,24 +161,18 @@
"dep-check": "aegir dep-check"
},
"dependencies": {
"abstract-level": "^1.0.3",
"datastore-core": "^8.0.1",
"interface-datastore": "^7.0.0",
"datastore-core": "^9.0.1",
"interface-datastore": "^8.0.0",
"it-filter": "^2.0.0",
"it-map": "^2.0.0",
"it-sort": "^2.0.0",
"it-take": "^2.0.0",
"level": "^8.0.0"
},
"devDependencies": {
"@ipld/dag-cbor": "^8.0.0",
"@types/rimraf": "^3.0.2",
"aegir": "^37.5.1",
"interface-datastore-tests": "^3.0.0",
"aegir": "^38.1.7",
"interface-datastore-tests": "^4.0.0",
"ipfs-utils": "^9.0.4",
"level-mem": "^6.0.1",
"memory-level": "^1.0.0",
"multiformats": "^10.0.2",
"rimraf": "^3.0.2"
"memory-level": "^1.0.0"
}
}
177 changes: 77 additions & 100 deletions src/index.js → src/index.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import { Key } from 'interface-datastore'
import { Batch, Key, KeyQuery, Pair, Query } from 'interface-datastore'
import { BaseDatastore, Errors } from 'datastore-core'
import filter from 'it-filter'
import map from 'it-map'
import take from 'it-take'
import sort from 'it-sort'
import { Level } from 'level'
import type { DatabaseOptions, OpenOptions, IteratorOptions } from 'level'

/**
* @typedef {import('interface-datastore').Datastore} Datastore
* @typedef {import('interface-datastore').Pair} Pair
* @typedef {import('interface-datastore').Batch} Batch
* @typedef {import('interface-datastore').Query} Query
* @typedef {import('interface-datastore').KeyQuery} KeyQuery
* @typedef {import('interface-datastore').Options} QueryOptions
* @typedef {import('abstract-level').AbstractLevel<any, string, Uint8Array>} LevelDb
*/
interface BatchPut {
type: 'put'
key: string
value: Uint8Array
}

interface BatchDel {
type: 'del'
key: string
}

type BatchOp = BatchPut | BatchDel

/**
* A datastore backed by leveldb
*/
export class LevelDatastore extends BaseDatastore {
/**
* @param {string | LevelDb} path
* @param {import('level').DatabaseOptions<string, Uint8Array> & import('level').OpenOptions} [opts]
*/
constructor (path, opts = {}) {
public db: Level<string, Uint8Array>
private readonly opts: OpenOptions

constructor (path: string | Level<string, Uint8Array>, opts: DatabaseOptions<string, Uint8Array> & OpenOptions = {}) {
super()

/** @type {LevelDb} */
this.db = typeof path === 'string'
? new Level(path, {
...opts,
Expand All @@ -36,91 +38,77 @@ export class LevelDatastore extends BaseDatastore {
})
: path

/** @type {import('level').OpenOptions} */
this.opts = {
createIfMissing: true,
compression: false, // same default as go
...opts
}
}

async open () {
async open (): Promise<void> {
try {
await this.db.open(this.opts)
} catch (/** @type {any} */ err) {
} catch (err: any) {
throw Errors.dbOpenFailedError(err)
}
}

/**
* @param {Key} key
* @param {Uint8Array} value
*/
async put (key, value) {
async put (key: Key, value: Uint8Array): Promise<void> {
try {
await this.db.put(key.toString(), value)
} catch (/** @type {any} */ err) {
} catch (err: any) {
throw Errors.dbWriteFailedError(err)
}
}

/**
* @param {Key} key
* @returns {Promise<Uint8Array>}
*/
async get (key) {
async get (key: Key): Promise<Uint8Array> {
let data
try {
data = await this.db.get(key.toString())
} catch (/** @type {any} */ err) {
if (err.notFound) throw Errors.notFoundError(err)
} catch (err: any) {
if (err.notFound != null) {
throw Errors.notFoundError(err)
}

throw Errors.dbWriteFailedError(err)
}
return data
}

/**
* @param {Key} key
* @returns {Promise<boolean>}
*/
async has (key) {
async has (key: Key): Promise<boolean> {
try {
await this.db.get(key.toString())
} catch (/** @type {any} */ err) {
if (err.notFound) return false
} catch (err: any) {
if (err.notFound != null) {
return false
}

throw err
}
return true
}

/**
* @param {Key} key
* @returns {Promise<void>}
*/
async delete (key) {
async delete (key: Key): Promise<void> {
try {
await this.db.del(key.toString())
} catch (/** @type {any} */ err) {
} catch (err: any) {
throw Errors.dbDeleteFailedError(err)
}
}

close () {
return this.db && this.db.close()
async close (): Promise<void> {
await this.db.close()
}

/**
* @returns {Batch}
*/
batch () {
/** @type {Array<{ type: 'put', key: string, value: Uint8Array; } | { type: 'del', key: string }>} */
const ops = []
batch (): Batch {
const ops: BatchOp[] = []

return {
put: (key, value) => {
ops.push({
type: 'put',
key: key.toString(),
value: value
value
})
},
delete: (key) => {
Expand All @@ -129,16 +117,17 @@ export class LevelDatastore extends BaseDatastore {
key: key.toString()
})
},
commit: () => {
return this.db.batch(ops)
commit: async () => {
if (this.db.batch == null) {
throw new Error('Batch operations unsupported by underlying Level')
}

await this.db.batch(ops)
}
}
}

/**
* @param {Query} q
*/
query (q) {
query (q: Query): AsyncIterable<Pair> {
let it = this._query({
values: true,
prefix: q.prefix
Expand All @@ -153,22 +142,19 @@ export class LevelDatastore extends BaseDatastore {
}

const { offset, limit } = q
if (offset) {
if (offset != null) {
let i = 0
it = filter(it, () => i++ >= offset)
}

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

return it
}

/**
* @param {KeyQuery} q
*/
queryKeys (q) {
queryKeys (q: KeyQuery): AsyncIterable<Key> {
let it = map(this._query({
values: false,
prefix: q.prefix
Expand All @@ -183,27 +169,20 @@ export class LevelDatastore extends BaseDatastore {
}

const { offset, limit } = q
if (offset) {
if (offset != null) {
let i = 0
it = filter(it, () => i++ >= offset)
}

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

return it
}

/**
* @param {object} opts
* @param {boolean} opts.values
* @param {string} [opts.prefix]
* @returns {AsyncIterable<Pair>}
*/
_query (opts) {
/** @type {import('level').IteratorOptions<string, Uint8Array>} */
const iteratorOpts = {
_query (opts: { values: boolean, prefix?: string }): AsyncIterable<Pair> {
const iteratorOpts: IteratorOptions<string, Uint8Array> = {
keys: true,
keyEncoding: 'buffer',
values: opts.values
Expand All @@ -220,7 +199,7 @@ export class LevelDatastore extends BaseDatastore {

const iterator = this.db.iterator(iteratorOpts)

if (iterator[Symbol.asyncIterator]) {
if (iterator[Symbol.asyncIterator] != null) {
return levelIteratorToIterator(iterator)
}

Expand All @@ -234,47 +213,45 @@ export class LevelDatastore extends BaseDatastore {
}
}

/**
* @param {import('level').Iterator<LevelDb, string, Uint8Array>} li - Level iterator
* @returns {AsyncIterable<Pair>}
*/
async function * levelIteratorToIterator (li) {
async function * levelIteratorToIterator (li: AsyncIterable<[string, Uint8Array]> & { close: () => Promise<void> }): AsyncIterable<Pair> {
for await (const [key, value] of li) {
yield { key: new Key(key, false), value }
}

await li.close()
}

/**
* @typedef {object} LevelIterator
* @property {(cb: (err: Error, key: string | Uint8Array | null, value: any)=> void)=>void} next
* @property {(cb: (err: Error) => void) => void } end
*/
interface OldLevelIterator {
next: (cb: (err: Error, key: string | Uint8Array | null, value: any) => void) => void
end: (cb: (err: Error) => void) => void
}

/**
* @param {LevelIterator} li - Level iterator
* @returns {AsyncIterable<Pair>}
*/
function oldLevelIteratorToIterator (li) {
function oldLevelIteratorToIterator (li: OldLevelIterator): AsyncIterable<Pair> {
return {
[Symbol.asyncIterator] () {
return {
next: () => new Promise((resolve, reject) => {
next: async () => await new Promise((resolve, reject) => {
li.next((err, key, value) => {
if (err) return reject(err)
if (err != null) {
reject(err); return
}
if (key == null) {
return li.end(err => {
if (err) return reject(err)
li.end(err => {
if (err != null) {
reject(err)
return
}
resolve({ done: true, value: undefined })
})
}); return
}
resolve({ done: false, value: { key: new Key(key, false), value } })
})
}),
return: () => new Promise((resolve, reject) => {
return: async () => await new Promise((resolve, reject) => {
li.end(err => {
if (err) return reject(err)
if (err != null) {
reject(err); return
}
resolve({ done: true, value: undefined })
})
})
Expand Down
8 changes: 4 additions & 4 deletions test/browser.js → test/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { interfaceDatastoreTests } from 'interface-datastore-tests'
describe('LevelDatastore', () => {
describe('interface-datastore (leveljs)', () => {
interfaceDatastoreTests({
setup: () => new LevelDatastore('hello-' + Math.random()),
setup: () => new LevelDatastore(`hello-${Math.random()}`),
teardown: () => {}
})
})
Expand All @@ -18,13 +18,13 @@ describe('LevelDatastore', () => {
setup () {
return new MountDatastore([{
prefix: new Key('/a'),
datastore: new LevelDatastore('one-' + Math.random())
datastore: new LevelDatastore(`one-${Math.random()}`)
}, {
prefix: new Key('/q'),
datastore: new LevelDatastore('two-' + Math.random())
datastore: new LevelDatastore(`two-${Math.random()}`)
}, {
prefix: new Key('/z'),
datastore: new LevelDatastore('three-' + Math.random())
datastore: new LevelDatastore(`three-${Math.random()}`)
}])
},
teardown () {}
Expand Down
Loading