Thanks to visit codestin.com
Credit goes to github.com

Skip to content
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ KVS libraries provide following common features.
- provide `get`, `set`, `has`, `delete`, and `clear` API
- Version migration API
- Upgrade date via `version`
- Tiny package
- Almost package size is 1kb(gzip)

## Packages

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"build": "lerna run build",
"clean": "lerna run clean",
"test": "lerna run test",
"ci": "lerna run test --ignore '@kvs/localstorage'",
"versionup": "lerna version --conventional-commits",
"versionup:patch": "lerna version patch --conventional-commits",
"versionup:minor": "lerna version minor --conventional-commits",
Expand Down
10 changes: 5 additions & 5 deletions packages/common-test-case/src/common-test-case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ export type KVSTestCaseOptions = {
setTestDataList: { name: string; value: any; type?: "object" }[];
};
export type KVSTestCaseRef = {
current: KVS<any, any> | null;
updateRef(ref: KVS<any, any>): void;
current: KVS<any> | null;
updateRef(ref: KVS<any>): void;
};
// version always be defined
export const createKVSTestCase = (
kvsStorageConstructor: (options: Partial<KVSOptions<any, any>> & { version: number }) => Promise<KVS<any, any>>,
kvsStorageConstructor: (options: Partial<KVSOptions<any>> & { version: number }) => Promise<KVS<any>>,
options: KVSTestCaseOptions
) => {
const ref: KVSTestCaseRef = {
current: null,
updateRef(target: KVS<any, any>) {
updateRef(target: KVS<any>) {
ref.current = target;
}
};
let kvs: KVS<any, any>;
let kvs: KVS<any>;
return {
ref,
run: () => {
Expand Down
12 changes: 6 additions & 6 deletions packages/env/src/browser.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { JsonValue, KvsStorage } from "@kvs/storage";
import { kvsIndexedDB } from "@kvs/indexeddb";
import { KvsEnvStorageOptions } from "./share";
import { KvsStorage } from "@kvs/storage";
import { kvsIndexedDB, KvsIndexedDBOptions } from "@kvs/indexeddb";
import { KvsEnvStorageOptions, KvsEnvStorageSchema } from "./share";

export const kvsEnvStorage = async <K extends string, V extends JsonValue>(
options: KvsEnvStorageOptions<K, V>
): Promise<KvsStorage<K, V>> => {
export const kvsEnvStorage = async <Schema extends KvsEnvStorageSchema>(
options: KvsEnvStorageOptions<Schema> & KvsIndexedDBOptions<Schema>
): Promise<KvsStorage<Schema>> => {
return kvsIndexedDB(options);
};
10 changes: 5 additions & 5 deletions packages/env/src/node.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { JsonValue, KvsStorage } from "@kvs/storage";
import { kvsLocalStorage } from "@kvs/node-localstorage";
import { kvsLocalStorage, KvsLocalStorage, KvsLocalStorageOptions } from "@kvs/node-localstorage";
import { KvsEnvStorageOptions } from "./share";
import { KVSIndexedSchema } from "@kvs/indexeddb/lib";

export const kvsEnvStorage = async <K extends string, V extends JsonValue>(
options: KvsEnvStorageOptions<K, V>
): Promise<KvsStorage<K, V>> => {
export const kvsEnvStorage = async <Schema extends KVSIndexedSchema>(
options: KvsEnvStorageOptions<Schema> & KvsLocalStorageOptions<Schema>
): Promise<KvsLocalStorage<Schema>> => {
return kvsLocalStorage(options);
};
12 changes: 7 additions & 5 deletions packages/env/src/share.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { JsonValue, KVSStorageKey } from "@kvs/storage";
import { KVS } from "@kvs/types";
import { KvsLocalStorageOptions } from "@kvs/node-localstorage";
import { JsonValue } from "@kvs/storage";
import { KVS, KVSOptions } from "@kvs/types";

export type KvsEnvStorage<K extends KVSStorageKey, V extends JsonValue> = KVS<K, V>;
export type KvsEnvStorageOptions<K extends KVSStorageKey, V extends JsonValue> = KvsLocalStorageOptions<K, V>;
export type KvsEnvStorageSchema = {
[index: string]: JsonValue;
};
export type KvsEnvStorage<Schema extends KvsEnvStorageSchema> = KVS<Schema>;
export type KvsEnvStorageOptions<Schema extends KvsEnvStorageSchema> = KVSOptions<Schema>;
24 changes: 23 additions & 1 deletion packages/indexeddb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,29 @@ Install with [npm](https://www.npmjs.com/):

## Usage

- [ ] Write usage instructions
```ts
import { KVSIndexedDB, kvsIndexedDB } from "@kvs/indexeddb";
(async () => {
type StorageSchema = {
a1: string;
b2: number;
c3: boolean;
};
const storage = await kvsIndexedDB<StorageSchema>({
name: "test",
version: 1,
});
await storage.set("a1", "string");
await storage.set("b2", 42);
await storage.set("c3", false);
const a1 = await storage.get("a1");
const b2 = await storage.get("b2");
const c3 = await storage.get("c3");
assert.strictEqual(a1, "string");
assert.strictEqual(b2, 42);
assert.strictEqual(c3, false);
})();
```

## Changelog

Expand Down
74 changes: 44 additions & 30 deletions packages/indexeddb/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { KVS, KVSOptions } from "@kvs/types";
import type { KVS, KVSOptions, StoreNames, StoreValue } from "@kvs/types";
import { JsonValue } from "@kvs/storage";

type IndexedDBKey = string;
const debug = {
enabled: false,
log(...args: any[]) {
Expand Down Expand Up @@ -97,11 +97,15 @@ const dropInstance = (database: IDBDatabase, databaseName: string): Promise<void
});
};

const getItem = <K extends IndexedDBKey, V>(database: IDBDatabase, tableName: string, key: K): Promise<V> => {
const getItem = <Schema extends KVSIndexedSchema>(
database: IDBDatabase,
tableName: string,
key: StoreNames<Schema>
): Promise<StoreValue<Schema, StoreNames<Schema>>> => {
return new Promise((resolve, reject) => {
const transaction = database.transaction(tableName, "readonly");
const objectStore = transaction.objectStore(tableName);
const request = objectStore.get(key);
const request = objectStore.get(String(key));
request.onsuccess = () => {
resolve(request.result);
};
Expand All @@ -110,11 +114,15 @@ const getItem = <K extends IndexedDBKey, V>(database: IDBDatabase, tableName: st
};
});
};
const hasItem = async <K extends IndexedDBKey>(database: IDBDatabase, tableName: string, key: K): Promise<boolean> => {
const hasItem = async <Schema extends KVSIndexedSchema>(
database: IDBDatabase,
tableName: string,
key: StoreNames<Schema>
): Promise<boolean> => {
return new Promise((resolve, reject) => {
const transaction = database.transaction(tableName, "readonly");
const objectStore = transaction.objectStore(tableName);
const request = objectStore.count(key);
const request = objectStore.count(String(key));
request.onsuccess = () => {
resolve(request.result !== 0);
};
Expand All @@ -123,22 +131,22 @@ const hasItem = async <K extends IndexedDBKey>(database: IDBDatabase, tableName:
};
});
};
const setItem = async <K extends IndexedDBKey, V>(
const setItem = async <Schema extends KVSIndexedSchema>(
database: IDBDatabase,
tableName: string,
key: K,
value: V
key: StoreNames<Schema>,
value: StoreValue<Schema, StoreNames<Schema>> | undefined
): Promise<void> => {
// If the value is undefined, delete the key
// This behavior aim to align localStorage implementation
if (value === undefined) {
await deleteItem(database, tableName, key);
await deleteItem<Schema>(database, tableName, key);
return;
}
return new Promise((resolve, reject) => {
const transaction = database.transaction(tableName, "readwrite");
const objectStore = transaction.objectStore(tableName);
const request = objectStore.put(value, key);
const request = objectStore.put(value, String(key));
transaction.oncomplete = () => {
resolve();
};
Expand All @@ -150,15 +158,15 @@ const setItem = async <K extends IndexedDBKey, V>(
};
});
};
const deleteItem = async <K extends IndexedDBKey>(
const deleteItem = async <Schema extends KVSIndexedSchema>(
database: IDBDatabase,
tableName: string,
key: K
key: StoreNames<Schema>
): Promise<boolean> => {
return new Promise((resolve, reject) => {
const transaction = database.transaction(tableName, "readwrite");
const objectStore = transaction.objectStore(tableName);
const request = objectStore.delete(key);
const request = objectStore.delete(String(key));
transaction.oncomplete = () => {
resolve();
};
Expand Down Expand Up @@ -186,7 +194,10 @@ const clearItems = async (database: IDBDatabase, tableName: string): Promise<voi
};
});
};
const iterator = <K extends IndexedDBKey, V>(database: IDBDatabase, tableName: string): AsyncIterator<[K, V]> => {
const iterator = <Schema extends KVSIndexedSchema, K extends StoreNames<Schema>, V extends StoreValue<Schema, K>>(
database: IDBDatabase,
tableName: string
): AsyncIterator<[K, V]> => {
const handleCursor = <T>(request: IDBRequest<T | null>): Promise<{ done: boolean; value?: T }> => {
return new Promise((resolve, reject) => {
request.onsuccess = () => {
Expand Down Expand Up @@ -237,23 +248,23 @@ interface StoreOptions {
tableName: string;
}

const createStore = <K extends IndexedDBKey, V>({
const createStore = <Schema extends KVSIndexedSchema>({
database,
databaseName,
tableName
}: StoreOptions): KVSIndexedDB<K, V> => {
const store: KVSIndexedDB<K, V> = {
delete(key: K): Promise<boolean> {
return deleteItem(database, tableName, key).then(() => true);
}: StoreOptions): KVSIndexedDB<Schema> => {
const store: KVSIndexedDB<Schema> = {
delete(key: StoreNames<Schema>): Promise<boolean> {
return deleteItem<Schema>(database, tableName, key).then(() => true);
},
get(key: K): Promise<V | undefined> {
return getItem(database, tableName, key);
get<K extends StoreNames<Schema>>(key: K): Promise<StoreValue<Schema, K> | undefined> {
return getItem<Schema>(database, tableName, key);
},
has(key: K): Promise<boolean> {
has(key: StoreNames<Schema>): Promise<boolean> {
return hasItem(database, tableName, key);
},
set(key: K, value: V) {
return setItem(database, tableName, key, value).then(() => store);
set<K extends StoreNames<Schema>>(key: K, value: StoreValue<Schema, K>) {
return setItem<Schema>(database, tableName, key, value).then(() => store);
},
clear(): Promise<void> {
return clearItems(database, tableName);
Expand All @@ -274,11 +285,14 @@ const createStore = <K extends IndexedDBKey, V>({
return store;
};

export type KVSIndexedDB<K extends IndexedDBKey, V> = KVS<K, V> & IndexedDBResults;
export type KvsIndexedDBOptions<K extends IndexedDBKey, V> = KVSOptions<K, V> & IndexedDBOptions;
export const kvsIndexedDB = async <K extends IndexedDBKey, V>(
options: KvsIndexedDBOptions<K, V>
): Promise<KVSIndexedDB<K, V>> => {
export type KVSIndexedSchema = {
[index: string]: JsonValue;
};
export type KVSIndexedDB<Schema extends KVSIndexedSchema> = KVS<Schema> & IndexedDBResults;
export type KvsIndexedDBOptions<Schema extends KVSIndexedSchema> = KVSOptions<Schema> & IndexedDBOptions;
export const kvsIndexedDB = async <Schema extends KVSIndexedSchema>(
options: KvsIndexedDBOptions<Schema>
): Promise<KVSIndexedDB<Schema>> => {
const { name, version, upgrade, ...indexDBOptions } = options;
if (indexDBOptions.debug) {
debug.enabled = indexDBOptions.debug;
Expand Down
23 changes: 22 additions & 1 deletion packages/indexeddb/test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { KVSIndexedDB, kvsIndexedDB } from "../src";
import { createKVSTestCase } from "@kvs/common-test-case";
import assert from "assert";

const databaseName = "kvs-test";
const kvsTestCase = createKVSTestCase(
Expand Down Expand Up @@ -46,7 +47,7 @@ const kvsTestCase = createKVSTestCase(
}
);
const deleteAllDB = async () => {
const kvs = kvsTestCase.ref.current as KVSIndexedDB<any, any> | null;
const kvs = kvsTestCase.ref.current as KVSIndexedDB<any> | null;
if (!kvs) {
return;
}
Expand All @@ -62,4 +63,24 @@ describe("@kvs/indexedDB", () => {
before(deleteAllDB);
afterEach(deleteAllDB);
kvsTestCase.run();
it("example", async () => {
type StorageSchema = {
a1: string;
b2: number;
c3: boolean;
};
const storage = await kvsIndexedDB<StorageSchema>({
name: databaseName,
version: 1
});
await storage.set("a1", "string");
await storage.set("b2", 42);
await storage.set("c3", false);
const a1 = await storage.get("a1");
const b2 = await storage.get("b2");
const c3 = await storage.get("c3");
assert.strictEqual(a1, "string");
assert.strictEqual(b2, 42);
assert.strictEqual(c3, false);
});
});
26 changes: 24 additions & 2 deletions packages/localstorage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,30 @@ Install with [npm](https://www.npmjs.com/):

## Usage

- [ ] Write usage instructions

```ts
import assert from "assert";
import { kvsLocalStorage } from "@kvs/localstorage";
(async () => {
type StorageSchema = {
a1: string;
b2: number;
c3: boolean;
};
const storage = await kvsLocalStorage<StorageSchema>({
name: "test",
version: 1
});
await storage.set("a1", "string");
await storage.set("b2", 42);
await storage.set("c3", false);
const a1 = await storage.get("a1");
const b2 = await storage.get("b2");
const c3 = await storage.get("c3");
assert.strictEqual(a1, "string");
assert.strictEqual(b2, 42);
assert.strictEqual(c3, false);
})();
```
## Changelog

See [Releases page](https://github.com/azu/kvs/releases).
Expand Down
15 changes: 9 additions & 6 deletions packages/localstorage/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { JsonValue, KvsStorage, kvsStorage, KVSStorageKey } from "@kvs/storage";
import { JsonValue, KvsStorage, kvsStorage } from "@kvs/storage";
import { KVS, KVSOptions } from "@kvs/types";

export type KvsLocalStorage<K extends KVSStorageKey, V extends JsonValue> = KVS<K, V>;
export type KvsLocalStorageOptions<K extends KVSStorageKey, V extends JsonValue> = KVSOptions<K, V> & {
export type KvsLocalStorageSchema = {
[index: string]: JsonValue;
};
export type KvsLocalStorage<Schema extends KvsLocalStorageSchema> = KVS<Schema>;
export type KvsLocalStorageOptions<Schema extends KvsLocalStorageSchema> = KVSOptions<Schema> & {
kvsVersionKey?: string;
};
export const kvsLocalStorage = async <K extends KVSStorageKey, V extends JsonValue>(
options: KvsLocalStorageOptions<K, V>
): Promise<KvsStorage<K, V>> => {
export const kvsLocalStorage = async <Schema extends KvsLocalStorageSchema>(
options: KvsLocalStorageOptions<Schema>
): Promise<KvsStorage<Schema>> => {
return kvsStorage({
...options,
storage: window.localStorage
Expand Down
15 changes: 9 additions & 6 deletions packages/memorystorage/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { JsonValue, KvsStorage, kvsStorage, KVSStorageKey } from "@kvs/storage";
import { JsonValue, KvsStorage, kvsStorage } from "@kvs/storage";
import { KVS, KVSOptions } from "@kvs/types";
// @ts-ignore
import localstorage from "localstorage-memory";

export type KvsLocalStorage<K extends KVSStorageKey, V extends JsonValue> = KVS<K, V>;
export type KvsLocalStorageOptions<K extends KVSStorageKey, V extends JsonValue> = KVSOptions<K, V> & {
export type KvsMemoryStorageSchema = {
[index: string]: JsonValue;
};
export type KvsMemoryStorage<Schema extends KvsMemoryStorageSchema> = KVS<Schema>;
export type KvsMemoryStorageOptions<Schema extends KvsMemoryStorageSchema> = KVSOptions<Schema> & {
kvsVersionKey?: string;
};
export const kvsMemoryStorage = async <K extends KVSStorageKey, V extends JsonValue>(
options: KvsLocalStorageOptions<K, V>
): Promise<KvsStorage<K, V>> => {
export const kvsMemoryStorage = async <Schema extends KvsMemoryStorageSchema>(
options: KvsMemoryStorageOptions<Schema>
): Promise<KvsStorage<Schema>> => {
return kvsStorage({
...options,
storage: localstorage
Expand Down
Loading