diff --git a/types/datastore-core/datastore-core-tests.ts b/types/datastore-core/datastore-core-tests.ts index 1f8b4e750d..7b65e801b3 100644 --- a/types/datastore-core/datastore-core-tests.ts +++ b/types/datastore-core/datastore-core-tests.ts @@ -1,14 +1,14 @@ -import { Key, MemoryDatastore, Datastore } from 'interface-datastore'; +import { Key, MemoryDatastore, Adapter } from 'interface-datastore'; import { KeytransformDatastore, MountDatastore, NamespaceDatastore, ShardingDatastore, TieredDatastore, - shard + shard, } from 'datastore-core'; -const store: Datastore = new MemoryDatastore(); +const store = new MemoryDatastore(); // KeytransformDatastore @@ -23,7 +23,7 @@ const transform = { throw new Error('missing prefix, convert failed?'); } return Key.withNamespaces(l.slice(1)); - } + }, }; const kStore = new KeytransformDatastore(store, transform); @@ -52,10 +52,12 @@ m1.put(new Key('/cool/hello'), hello).then(() => { m1.get(new Key('/hello')).then(console.log); }); -const m3 = new MountDatastore([{ - datastore: store, - prefix: new Key('cool') -}]); +const m3 = new MountDatastore([ + { + datastore: store, + prefix: new Key('cool'), + }, +]); m3.put(new Key('/hello'), hello).then(() => { m3.get(new Key('/cool/hello')).then(value => { @@ -75,16 +77,20 @@ m3.put(new Key('/cool/hello'), hello).then(() => { }); }); -const mount = new MountDatastore([{ - prefix: new Key('/a'), - datastore: new MemoryDatastore() -}, { - prefix: new Key('/z'), - datastore: new MemoryDatastore() -}, { - prefix: new Key('/q'), - datastore: new MemoryDatastore() -}]); +const mount = new MountDatastore([ + { + prefix: new Key('/a'), + datastore: new MemoryDatastore(), + }, + { + prefix: new Key('/z'), + datastore: new MemoryDatastore(), + }, + { + prefix: new Key('/q'), + datastore: new MemoryDatastore(), + }, +]); console.log(mount.mounts); @@ -95,7 +101,7 @@ const n2 = new NamespaceDatastore(store, new Key('')); n1.put(key, Buffer.from(key.toString())).then(() => { n2.put(key, Buffer.from(key.toString())).then(() => { - n1.get(new Key('abc').child(key)).then(async (value) => { + n1.get(new Key('abc').child(key)).then(async value => { for await (const { key, value } of n2.query({})) { console.log(key, value); } @@ -117,7 +123,7 @@ ShardingDatastore.create(ms, sh).then(store => { ms.get(new Key(shard.README_FN)).then(console.log); }); -(async () => { +async () => { await ShardingDatastore.create(ms, sh); await ShardingDatastore.open(ms); const ss = await ShardingDatastore.createOrOpen(ms, sh); @@ -125,7 +131,7 @@ ShardingDatastore.create(ms, sh).then(store => { await ss.put(new Key('hello'), Buffer.from('test')); const res = await ms.get(new Key('ll').child(new Key('hello'))); console.log(res); -}); +}; ShardingDatastore.createOrOpen(new MemoryDatastore(), new shard.NextToLast(2)).then(test => { console.log(test); @@ -149,7 +155,7 @@ console.log(shard.parseShardFun('/repo/flatfs/shard/v1/prefix/10').name); // pre // TieredDatastore -const stores: Datastore[] = []; +const stores: Adapter[] = []; stores.push(new MemoryDatastore()); stores.push(new MemoryDatastore()); const td1 = new TieredDatastore(stores); @@ -175,8 +181,5 @@ Promise.all([stores[0].has(key), stores[1].has(key)]).then(arr => { }); }); -const td = new TieredDatastore([ - new MemoryDatastore(), - new MemoryDatastore() -]); +const td = new TieredDatastore([new MemoryDatastore(), new MemoryDatastore()]); console.log(td.stores); diff --git a/types/datastore-core/index.d.ts b/types/datastore-core/index.d.ts index 5296996a48..756f6f7676 100644 --- a/types/datastore-core/index.d.ts +++ b/types/datastore-core/index.d.ts @@ -1,10 +1,10 @@ -// Type definitions for datastore-core 0.7 +// Type definitions for datastore-core 1.1 // Project: https://github.com/ipfs/js-datastore-core#readme // Definitions by: Carson Farmer // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 3.6 -import { Datastore, Key } from 'interface-datastore'; +import { Adapter, Key } from 'interface-datastore'; /** * Transform function object to converting back-and-forth between key spaces. @@ -35,7 +35,7 @@ export interface Mount { /** * The child datastore. */ - datastore: Datastore; + datastore: Adapter; /** * The mount prefix. */ @@ -48,17 +48,17 @@ export namespace shard { const PREFIX = '/repo/flatfs/shard/'; const readme: string; class Shard { - constructor(length: number) + constructor(length: number); name: string; param: number; _padding: string; fun(str: string): string; toString(): string; } - class Prefix extends Shard { } - class Suffix extends Shard { } - class NextToLast extends Shard { } - function readShardFun(path: string, store: Datastore): Promise; + class Prefix extends Shard {} + class Suffix extends Shard {} + class NextToLast extends Shard {} + function readShardFun(path: string, store: Adapter): Promise; function parseShardFun(str: string): Shard; } @@ -67,13 +67,13 @@ export namespace shard { * the way keys look to the user, for example namespacing * keys, reversing them, etc. */ -export interface KeytransformDatastore extends Datastore { - child: Datastore; +export interface KeytransformDatastore extends Adapter { + child: Adapter; transform: Transform; } export interface KeytransformDatastoreConstructor { - new (child: Datastore, transform: Transform): KeytransformDatastore; + new (child: Adapter, transform: Transform): KeytransformDatastore; } export const KeytransformDatastore: KeytransformDatastoreConstructor; @@ -82,12 +82,12 @@ export const KeytransformDatastore: KeytransformDatastoreConstructor; * A datastore that can combine multiple stores inside various * key prefixs. */ -export interface MountDatastore extends Datastore { +export interface MountDatastore extends Adapter { mounts: Array>; } export interface MountDatastoreConstructor { - new(mounts: Array>): MountDatastore; + new (mounts: Array>): MountDatastore; } export const MountDatastore: MountDatastoreConstructor; @@ -106,7 +106,7 @@ export interface NamespaceDatastore extends KeytransformDatastor } export interface NamespaceDatastoreConstructor { - new(child: Datastore, prefix: Key): NamespaceDatastore; + new (child: Adapter, prefix: Key): NamespaceDatastore; } export const NamespaceDatastore: NamespaceDatastoreConstructor; @@ -118,12 +118,12 @@ export const NamespaceDatastore: NamespaceDatastoreConstructor; * last one first. * */ -export interface TieredDatastore extends Datastore { - stores: Array>; +export interface TieredDatastore extends Adapter { + stores: Array>; } export interface TieredDatastoreConstructor { - new(stores: Array>): TieredDatastore; + new (stores: Array>): TieredDatastore; } export const TieredDatastore: TieredDatastoreConstructor; @@ -134,16 +134,16 @@ export const TieredDatastore: TieredDatastoreConstructor; * Wraps another datastore such that all values are stored * sharded according to the given sharding function. */ -export interface ShardingDatastore extends Datastore { +export interface ShardingDatastore extends Adapter { child: KeytransformDatastore; shard: shard.Shard; } export interface ShardingDatastoreConstructor { - new (stores: Array>): ShardingDatastore; - createOrOpen(store: Datastore, shard: shard.Shard): Promise>; - open(store: Datastore): Promise>; - create(store: Datastore, shard: shard.Shard): Promise>; + new (stores: Array>): ShardingDatastore; + createOrOpen(store: Adapter, shard: shard.Shard): Promise>; + open(store: Adapter): Promise>; + create(store: Adapter, shard: shard.Shard): Promise>; } export const ShardingDatastore: ShardingDatastoreConstructor; diff --git a/types/datastore-level/datastore-level-tests.ts b/types/datastore-level/datastore-level-tests.ts index 9bfdf2c946..641cd7cbe8 100644 --- a/types/datastore-level/datastore-level-tests.ts +++ b/types/datastore-level/datastore-level-tests.ts @@ -1,12 +1,12 @@ import leveldown from 'leveldown'; import levelup from 'levelup'; -import { Key, Result, Query, Batch, Datastore } from 'interface-datastore'; -import LevelDatastore, { LevelDatastore as Interface } from 'datastore-level'; +import { Key, Pair, Query, Batch, Datastore } from 'interface-datastore'; +import * as LevelDatastore from 'datastore-level'; const levelStore: Datastore = new LevelDatastore('init-default'); levelStore.open(); -const store: Interface = new LevelDatastore('path', { db: (path, opts) => levelup(leveldown(path), opts) }); +const store = new LevelDatastore('path', { db: (path, opts) => levelup(leveldown(path), opts) }); store.open(); const k = new Key('/z/one'); @@ -68,10 +68,10 @@ const hello = { key: new Key('/q/1hello'), value: Buffer.from('1') }; const world = { key: new Key('/z/2world'), value: Buffer.from('2') }; const hello2 = { key: new Key('/z/3hello2'), value: Buffer.from('3') }; -const filter1: Query.Filter = (entry: Result) => !entry.key.toString().endsWith('hello'); -const filter2 = (entry: Result) => entry.key.toString().endsWith('hello2'); +const filter1: Query.Filter = (entry: Pair) => !entry.key.toString().endsWith('hello'); +const filter2 = (entry: Pair) => entry.key.toString().endsWith('hello2'); -const order: Query.Order = (res: Result[]) => { +const order: Query.Order = (res: Pair[]) => { return res.sort((a, b) => { if (a.value.toString() < b.value.toString()) { return -1; @@ -96,11 +96,11 @@ const query: Query = { filters: [filter1, filter2], orders: [order], offset: 1, - limit: 1 + limit: 1, }; const test = async () => { - const res: Result[] = []; + const res: Pair[] = []; for await (const item of store.query(query)) { res.push(item); const key = item.key.toString(); diff --git a/types/datastore-level/index.d.ts b/types/datastore-level/index.d.ts index 402d4daf1f..42c7977e2e 100644 --- a/types/datastore-level/index.d.ts +++ b/types/datastore-level/index.d.ts @@ -1,35 +1,35 @@ -// Type definitions for datastore-level 0.14 +// Type definitions for datastore-level 1.1 // Project: https://github.com/ipfs/js-datastore-level#readme -// Definitions by: Carson Farmer +// Definitions by: Carson Farmer // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped /// // TypeScript Version: 3.6 import { LevelUp } from 'levelup'; -import { Datastore, Batch } from 'interface-datastore'; +import { Batch, Adapter } from 'interface-datastore'; import { AbstractLevelDOWN, AbstractIterator, AbstractBatch } from 'abstract-leveldown'; -export interface LevelDatastoreBatch extends Batch { +interface LevelDatastoreBatch extends Batch { ops: Array>; } /** * A datastore backed by leveldb. */ -export interface LevelDatastore extends Datastore { +interface LevelDatastore extends Adapter { db: LevelUp, AbstractIterator>; batch(): LevelDatastoreBatch; } -export interface LevelDatastoreOptions { +interface LevelDatastoreOptions { db?: (location: string, options?: any) => LevelUp; [key: string]: any; } -export interface LevelDatastoreConstructor { +interface LevelDatastoreConstructor { new (path: string, options?: LevelDatastoreOptions): LevelDatastore; (path: string, options?: LevelDatastoreOptions): LevelDatastore; } declare const LevelDatastore: LevelDatastoreConstructor; -export default LevelDatastore; +export = LevelDatastore; diff --git a/types/interface-datastore/index.d.ts b/types/interface-datastore/index.d.ts index 7d3be15cc7..908084dd4c 100644 --- a/types/interface-datastore/index.d.ts +++ b/types/interface-datastore/index.d.ts @@ -1,8 +1,9 @@ -// Type definitions for interface-datastore 0.8 +// Type definitions for interface-datastore 1.0 // Project: https://github.com/ipfs/interface-datastore#readme -// Definitions by: Carson Farmer +// Definitions by: Carson Farmer // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped /// +/// // TypeScript Version: 3.6 // From https://github.com/IndigoUnited/js-err-code @@ -17,6 +18,103 @@ export namespace Errors { function dbDeleteFailedError(error: Error): ErrCode; function dbWriteFailedError(error: Error): ErrCode; function notFoundError(error: Error): ErrCode; + function abortedError(error: Error): ErrCode; +} + +/** + * Key/Value pair. + */ +export interface Pair { + key: Key; + value: Value; +} + +/** + * Options for async operations. + */ +export interface Options { + signal: AbortSignal; +} + +/** + * Base Interface Datastore Adapter. + */ +export abstract class Adapter { + abstract open(): Promise; + abstract close(): Promise; + /** + * Store the passed value under the passed key + * + * @param key + * @param val + * @param options + */ + abstract put(key: Key, val: Value, options?: Options): Promise; + /** + * Store the given key/value pairs + * + * @param source + * @param options + */ + putMany( + source: AsyncIterable> | Iterable>, + options?: Options, + ): AsyncIterableIterator>; + + /** + * Retrieve the value for the passed key + * + * @param key + * @param options + */ + abstract get(key: Key, options?: Options): Promise; + /** + * Retrieve values for the passed keys + * + * @param source + * @param options + */ + getMany(source: AsyncIterable | Iterable, options?: Options): AsyncIterableIterator; + + /** + * Check for the existence of a value for the passed key + * + * @param key + */ + abstract has(key: Key): Promise; + + /** + * Remove the record for the passed key + * + * @param key + * @param options + */ + abstract delete(key: Key, options?: Options): Promise; + /** + * Remove values for the passed keys + * + * @param source + * @param options + */ + deleteMany(source: AsyncIterable | Iterable, options?: Options): AsyncIterableIterator; + /** + * Create a new batch object. + */ + batch(): Batch; + /** + * Yield all datastore values + * + * @param q + * @param options + */ + abstract _all(q?: Query, options?: Options): AsyncIterable>; + /** + * Query the store. + * + * @param q + * @param options + */ + query(q: Query, options?: Options): AsyncIterable>; } export namespace utils { @@ -28,32 +126,26 @@ export namespace utils { function tmpdir(): string; } -export class MemoryDatastore implements Datastore { +export class MemoryDatastore extends Adapter { constructor(); open(): Promise; + close(): Promise; put(key: Key, val: Value): Promise; get(key: Key): Promise; has(key: Key): Promise; delete(key: Key): Promise; - batch(): Batch; - query(q: Query): AsyncIterable>; - close(): Promise; + _all(): AsyncIterable>; } export interface Batch { put(key: Key, value: Value): void; delete(key: Key): void; - commit(): Promise; -} - -export interface Result { - key: Key; - value: Value; + commit(options?: Options): Promise; } export namespace Query { - type Filter = (item: Result) => boolean; - type Order = (items: Array>) => Array>; + type Filter = (item: Pair) => boolean; + type Order = (items: Array>) => Array>; } export interface Query { @@ -242,13 +334,4 @@ export class Key { static isKey(key: any): boolean; } -export interface Datastore { - open(): Promise; - put(key: Key, val: Value): Promise; - get(key: Key): Promise; - has(key: Key): Promise; - delete(key: Key): Promise; - batch(): Batch; - query(q: Query): AsyncIterable>; - close(): Promise; -} +export type Datastore = Adapter; diff --git a/types/interface-datastore/interface-datastore-tests.ts b/types/interface-datastore/interface-datastore-tests.ts index 881121e5fb..b39911f32b 100644 --- a/types/interface-datastore/interface-datastore-tests.ts +++ b/types/interface-datastore/interface-datastore-tests.ts @@ -1,4 +1,4 @@ -import { Key, MemoryDatastore, Result, Query, Batch, Errors, utils, Datastore } from 'interface-datastore'; +import { Key, MemoryDatastore, Pair, Query, Batch, Errors, utils, Datastore, Adapter } from 'interface-datastore'; const store: Datastore = new MemoryDatastore(); @@ -41,6 +41,51 @@ store.put(k, Buffer.from('hello')).then(() => { }); }); +const putMany = async () => { + const source = []; + for (let i = 0; i < 100; i++) { + source.push({ key: new Key(`/z/key${i}`), value: Buffer.from(`data${i}`) }); + } + for await (const { key, value } of store.putMany(source)) { + console.log(key, value); + } +}; + +putMany(); + +const getMany = async () => { + const k = new Key('/z/one'); + await store.put(k, Buffer.from('hello')); + const source = [k]; + + for await (const value of store.getMany(source)) { + console.log(value); + } +}; + +getMany(); + +const deleteMany = async () => { + const data = []; + for (let i = 0; i < 100; i++) { + data.push({ key: new Key(`/a/key${i}`), value: Buffer.from(`data${i}`) }); + } + + // Drain them all + for await (const { key, value } of store.putMany(data)) { + console.log(key, value); + } + + const res0 = await Promise.all(data.map(d => store.has(d.key))); + res0.forEach(res => typeof res === 'boolean'); + + for await (const key of store.deleteMany(data.map(d => d.key))) { + console.log(key.toString()); + } +}; + +deleteMany(); + const b: Batch = store.batch(); store.put(new Key('/z/old'), Buffer.from('old')).then(() => { @@ -61,10 +106,10 @@ const hello = { key: new Key('/q/1hello'), value: Buffer.from('1') }; const world = { key: new Key('/z/2world'), value: Buffer.from('2') }; const hello2 = { key: new Key('/z/3hello2'), value: Buffer.from('3') }; -const filter1: Query.Filter = (entry: Result) => !entry.key.toString().endsWith('hello'); -const filter2 = (entry: Result) => entry.key.toString().endsWith('hello2'); +const filter1: Query.Filter = (entry: Pair) => !entry.key.toString().endsWith('hello'); +const filter2 = (entry: Pair) => entry.key.toString().endsWith('hello2'); -const order: Query.Order = (res: Result[]) => { +const order: Query.Order = (res: Pair[]) => { return res.sort((a, b) => { if (a.value.toString() < b.value.toString()) { return -1; @@ -89,11 +134,11 @@ const query: Query = { filters: [filter1, filter2], orders: [order], offset: 1, - limit: 1 + limit: 1, }; const test = async () => { - const res: Result[] = []; + const res: Pair[] = []; for await (const item of store.query(query)) { res.push(item); const key = item.key.toString();