Skip to content

Instantly share code, notes, and snippets.

@intrnl
Last active September 3, 2021 14:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save intrnl/a7cc9a0864e130d9740e9b7baa2c3c08 to your computer and use it in GitHub Desktop.
Save intrnl/a7cc9a0864e130d9740e9b7baa2c3c08 to your computer and use it in GitHub Desktop.
Tree-shakeable class methods
import { Module } from './module';
export class Foo extends Module {
_foo = 'foo';
}
export class Bar extends Module {
_bar = 'bar';
}
export function fooOnly (foo: Foo, str: string) {
return foo._foo;
}
export function barOnly (bar: Bar, num: number) {
return bar._bar;
}
let foo = new Foo();
foo.do(fooOnly, ''); // should pass
foo.do(barOnly, 0); // should fail
let bar = new Bar();
bar.do(fooOnly, ''); // should fail
bar.do(barOnly, 0); // should pass
export type Extension<T> = (mod: T, ...args: any[]) => any;
export type ExtensionParameters<T extends (mod: any, ...args: any[]) => any> =
T extends (mod: any, ...args: infer P) => any ? P : never;
export abstract class Module {
do<T extends Extension<this>> (fn: T, ...args: ExtensionParameters<T>): ReturnType<T> {
return fn(this, ...args);
}
}
@intrnl
Copy link
Author

intrnl commented Sep 3, 2021

Treeshake-able IndexedDB key value store

export class IDBKeyval extends Module {
	_idb: Promise<IDBDatabase>;
	_name: string;

	constructor (db = 'keyval-store', store = 'store') {
		super();
	
		this._name = store;
		this._idb = new Promise((resolve, reject) => {
			const request = indexedDB.open(db);
			
			request.onupgradeneeded = () => request.result.createObjectStore(store);
			request.onerror = () => reject(request.error);
			request.onsuccess = () => resolve(request.result);
		});
	}
}

function perform<T> (store: IDBKeyval, mode: IDBTransactionMode, callback: (store: IDBObjectStore) => T | PromiseLike<T>): Promise<void> {
	return store._idb.then((db) => new Promise((resolve, reject) => {
		const transaction = db.transaction(store._name, mode);
		transaction.oncomplete = () => resolve();
		transaction.onerror = transaction.onabort = () => reject(transaction.error);

		callback(transaction.objectStore(store._name));
	}))
}

export function get<T> (store: IDBKeyval, key: IDBValidKey): Promise<T> {
	let request: IDBRequest<T>;
	
	return perform(store, 'readonly', (store) => request = store.get(key))
		.then(() => request.result);
}

export function keys (store: IDBKeyval): Promise<IDBValidKey[]> {
	let request: IDBRequest<IDBValidKey[]>;

	return perform(store, 'readonly', (store) => request = store.getAllKeys())
		.then(() => request.result)
}

export function set<T> (store: IDBKeyval, key: IDBValidKey, value: T): Promise<void> {
	return perform(store, 'readwrite', (store) => store.put(value, key));
}

export function remove (store: IDBKeyval, key: IDBValidKey): Promise<void> {
	return perform(store, 'readwrite', (store) => store.delete(key));
}

export function clear (store: IDBKeyval): Promise<void> {
	return perform(store, 'readwrite', (store) => store.clear());
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment