Skip to content

Commit

Permalink
WIP: Factory pattern on place
Browse files Browse the repository at this point in the history
So that each db has its own versions of Table, Collection etc and addons only extend the prototypes bound to the db and not globally.
  • Loading branch information
dfahlander committed Jan 31, 2018
1 parent f7bb2aa commit 91b5eef
Show file tree
Hide file tree
Showing 38 changed files with 563 additions and 567 deletions.
54 changes: 28 additions & 26 deletions api/collection.d.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,43 @@
import { ThenShortcut } from "./then-shortcut";
import { IndexableType, IndexableTypeArray } from "./indexable-type";
import { IDBValidKey, IndexableTypeArray } from "./indexeddb";
import { WhereClause } from "./where-clause";
import Promise from "./promise-extended";
import { PromiseExtended } from "./promise-extended";
import { Database } from "./database";

export interface Collection<T=any, TKey extends IndexableType=any> {
export interface Collection<T=any, TKey extends IDBValidKey=IDBValidKey> {
//db: Database;
and(filter: (x: T) => boolean): Collection<T, TKey>;
clone(props?: Object): Collection<T, TKey>;
count(): Promise<number>;
count<R>(thenShortcut: ThenShortcut<number, R>): Promise<R>;
count(): PromiseExtended<number>;
count<R>(thenShortcut: ThenShortcut<number, R>): PromiseExtended<R>;
distinct(): Collection<T, TKey>;
each(callback: (obj: T, cursor: {key: IndexableType, primaryKey: TKey}) => any): Promise<void>;
eachKey(callback: (key: IndexableType, cursor: {key: IndexableType, primaryKey: TKey}) => any): Promise<void>;
eachPrimaryKey(callback: (key: TKey, cursor: {key: IndexableType, primaryKey: TKey}) => any): Promise<void>;
eachUniqueKey(callback: (key: IndexableType, cursor: {key: IndexableType, primaryKey: TKey}) => any): Promise<void>;
each(callback: (obj: T, cursor: {key: IDBValidKey, primaryKey: TKey}) => any): PromiseExtended<void>;
eachKey(callback: (key: IDBValidKey, cursor: {key: IDBValidKey, primaryKey: TKey}) => any): PromiseExtended<void>;
eachPrimaryKey(callback: (key: TKey, cursor: {key: IDBValidKey, primaryKey: TKey}) => any): PromiseExtended<void>;
eachUniqueKey(callback: (key: IDBValidKey, cursor: {key: IDBValidKey, primaryKey: TKey}) => any): PromiseExtended<void>;
filter(filter: (x: T) => boolean): Collection<T, TKey>;
first(): Promise<T | undefined>;
first<R>(thenShortcut: ThenShortcut<T | undefined, R>): Promise<R>;
keys(): Promise<IndexableTypeArray>;
keys<R>(thenShortcut: ThenShortcut<IndexableTypeArray, R>): Promise<R>;
primaryKeys(): Promise<TKey[]>;
primaryKeys<R>(thenShortcut: ThenShortcut<TKey[], R>): Promise<R>;
last(): Promise<T | undefined>;
last<R>(thenShortcut: ThenShortcut<T | undefined, R>): Promise<R>;
first(): PromiseExtended<T | undefined>;
first<R>(thenShortcut: ThenShortcut<T | undefined, R>): PromiseExtended<R>;
keys(): PromiseExtended<IndexableTypeArray>;
keys<R>(thenShortcut: ThenShortcut<IndexableTypeArray, R>): PromiseExtended<R>;
primaryKeys(): PromiseExtended<TKey[]>;
primaryKeys<R>(thenShortcut: ThenShortcut<TKey[], R>): PromiseExtended<R>;
last(): PromiseExtended<T | undefined>;
last<R>(thenShortcut: ThenShortcut<T | undefined, R>): PromiseExtended<R>;
limit(n: number): Collection<T, TKey>;
offset(n: number): Collection<T, TKey>;
or(indexOrPrimayKey: string): WhereClause<T, TKey>;
raw(): Collection<T, TKey>;
reverse(): Collection<T, TKey>;
sortBy(keyPath: string): Promise<T[]>;
sortBy<R>(keyPath: string, thenShortcut: ThenShortcut<T[], R>) : Promise<R>;
toArray(): Promise<Array<T>>;
toArray<R>(thenShortcut: ThenShortcut<T[], R>) : Promise<R>;
uniqueKeys(): Promise<IndexableTypeArray>;
uniqueKeys<R>(thenShortcut: ThenShortcut<IndexableTypeArray, R>): Promise<R>;
sortBy(keyPath: string): PromiseExtended<T[]>;
sortBy<R>(keyPath: string, thenShortcut: ThenShortcut<T[], R>) : PromiseExtended<R>;
toArray(): PromiseExtended<Array<T>>;
toArray<R>(thenShortcut: ThenShortcut<T[], R>) : PromiseExtended<R>;
uniqueKeys(): PromiseExtended<IndexableTypeArray>;
uniqueKeys<R>(thenShortcut: ThenShortcut<IndexableTypeArray, R>): PromiseExtended<R>;
until(filter: (value: T) => boolean, includeStopEntry?: boolean): Collection<T, TKey>;
// Mutating methods
delete(): Promise<number>;
modify(changeCallback: (obj: T, ctx:{value: T}) => void): Promise<number>;
modify(changes: { [keyPath: string]: any } ): Promise<number>;
delete(): PromiseExtended<number>;
modify(changeCallback: (obj: T, ctx:{value: T}) => void): PromiseExtended<number>;
modify(changes: { [keyPath: string]: any } ): PromiseExtended<number>;
}
31 changes: 31 additions & 0 deletions api/database.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Table } from "./table";
import { IDBValidKey } from "./indexeddb";
import { TransactionMode } from "./transaction-mode";
import { PromiseExtended } from "./promise-extended";
import { WhereClause } from "./where-clause";
import { Collection } from "./collection";

export interface Database {
readonly name: string;
readonly tables: Table[];

table<T=any, TKey extends IDBValidKey=IDBValidKey>(tableName: string): Table<T, TKey>;

transaction<U>(mode: TransactionMode, table: Table<any, any>, scope: () => PromiseLike<U> | U): PromiseExtended<U>;

transaction<U>(mode: TransactionMode, table: Table<any, any>, table2: Table<any, any>, scope: () => PromiseLike<U> | U): PromiseExtended<U>;

transaction<U>(mode: TransactionMode, table: Table<any, any>, table2: Table<any, any>, table3: Table<any, any>, scope: () => PromiseLike<U> | U): PromiseExtended<U>;

transaction<U>(mode: TransactionMode, table: Table<any, any>, table2: Table<any, any>, table3: Table<any, any>, table4: Table<any,any>, scope: () => PromiseLike<U> | U): PromiseExtended<U>;

transaction<U>(mode: TransactionMode, table: Table<any, any>, table2: Table<any, any>, table3: Table<any, any>, table4: Table<any,any>, table5: Table<any,any>, scope: () => PromiseLike<U> | U): PromiseExtended<U>;

transaction<U>(mode: TransactionMode, tables: Table<any, any>[], scope: () => PromiseLike<U> | U): PromiseExtended<U>;

// Make it possible to touch physical class constructors where they reside - as properties on db instance.
// For example, checking if (x instanceof db.Table). Can't do (x instanceof Dexie.Table because it's just a virtual interface)
Table : {prototype: Table};
WhereClause: {prototype: WhereClause};
Collection: {prototype: Collection};
}
6 changes: 3 additions & 3 deletions api/dexie-constructor.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ThenShortcut } from "./then-shortcut";
import { TableSchema } from "./table-schema";
import { IndexSpec } from "./index-spec";
import { DexieExceptionClasses } from "./errors";
import { PromiseConstructorExtended } from "./promise-extended";
import { PromiseExtendedConstructor } from "./promise-extended";
import { DexieEventSet } from "./dexie-event-set";

export interface DexieOptions {
Expand Down Expand Up @@ -43,9 +43,9 @@ export interface DexieConstructor extends DexieExceptionClasses {
indexedDB: IDBFactory,
IDBKeyRange: IDBKeyRange
};
default: Dexie;
default: Dexie; // Work-around for different build tools handling default imports differently.

Promise: PromiseConstructorExtended;
Promise: PromiseExtendedConstructor;
//TableSchema: {}; // Deprecate!
//IndexSpec: {new():IndexSpec}; //? Deprecate
Events: (ctx?)=>DexieEventSet;
Expand Down
16 changes: 6 additions & 10 deletions api/dexie.d.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { Table } from "./table";
import { Version } from "./version";
import { DbEvents } from "./db-events";
import { TransactionMode } from "../types/transaction-mode";
import { TransactionMode } from "./transaction-mode";
import { Transaction } from "./transaction";
import { WhereClause } from "./where-clause";
import { Collection } from "./collection";
import { DbSchema } from "./db-schema";
import { DexieInternal } from "./dexie-internal";
import { IndexableType } from "./indexed-db";
import { IDBValidKey } from "./indexeddb";
import { TableSchema } from "./table-schema";
import { DexieConstructor } from "./dexie-constructor";
import { PromiseExtended } from "./promise-extended";
import { Database } from "./database";

export interface Dexie {
readonly constructor: DexieConstructor;
export interface Dexie extends Database {
readonly name: string;
readonly tables: Table<any, any>[];
readonly tables: Table[];
readonly verno: number;

readonly _allTables: {[name: string]: Table<any,any>};
Expand All @@ -35,11 +35,7 @@ export interface Dexie {

open(): PromiseExtended<Dexie>;

table(tableName: string): Table<any, any>;

table<T>(tableName: string): Table<T, any>;

table<T, Key extends IndexableType>(tableName: string): Table<T, Key>;
table<T=any, TKey extends IDBValidKey=IDBValidKey>(tableName: string): Table<T, TKey>;

transaction<U>(mode: TransactionMode, table: Table<any, any>, scope: () => PromiseLike<U> | U): PromiseExtended<U>;

Expand Down
2 changes: 1 addition & 1 deletion api/errors.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IndexableTypeArrayReadonly } from "./indexable-type";
import { IndexableTypeArrayReadonly } from "./indexeddb";

/** DexieError
*
Expand Down
5 changes: 0 additions & 5 deletions api/indexable-type.d.ts

This file was deleted.

13 changes: 11 additions & 2 deletions api/promise-extended.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
export interface PromiseConstructorExtended extends PromiseConstructor {
export interface PromiseExtendedConstructor extends PromiseConstructor {
new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): PromiseExtended<T>;
}

/** The interface of Dexie.Promise, which basically extends standard Promise with methods:
*
* finally() - also subject for standardization
* timeout() - set a completion timeout
* catch(ErrorClass, handler) - java style error catching
* catch(errorName, handler) - cross-domain safe type error catching (checking error.name instead of instanceof)
*
*/
export interface PromiseExtended<T=any> extends Promise<T> {
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): PromiseExtended<TResult1 | TResult2>;
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): PromiseExtended<T | TResult>;
catch<TResult = never>(ConstructorOrName: Function | string, onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): PromiseExtended<T | TResult>;
catch<TResult = never>(ErrorConstructor: Function, onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): PromiseExtended<T | TResult>;
catch<TResult = never>(errorName: string, onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): PromiseExtended<T | TResult>;
finally<U>(onFinally?: () => U | PromiseLike<U>): PromiseExtended<T>;
timeout (ms: number, msg?: string): PromiseExtended<T>;
}
Expand Down
8 changes: 4 additions & 4 deletions api/table-hooks.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ interface DeletingHookContext<T,Key> {
onerror?: (err: any) => void;
}

interface TableHooks<T,Key> extends DexieEventSet {
(eventName: 'creating', subscriber: (this: CreatingHookContext<T,Key>, primKey:Key, obj:T, transaction:Transaction) => any): void;
interface TableHooks<T=any,TKey=IDBValidKey> extends DexieEventSet {
(eventName: 'creating', subscriber: (this: CreatingHookContext<T,TKey>, primKey:TKey, obj:T, transaction:Transaction) => any): void;
(eventName: 'reading', subscriber: (obj:T) => T | any): void;
(eventName: 'updating', subscriber: (this: UpdatingHookContext<T,Key>, modifications:Object, primKey:Key, obj:T, transaction:Transaction) => any): void;
(eventName: 'deleting', subscriber: (this: DeletingHookContext<T,Key>, primKey:Key, obj:T, transaction:Transaction) => any): void;
(eventName: 'updating', subscriber: (this: UpdatingHookContext<T,TKey>, modifications:Object, primKey:TKey, obj:T, transaction:Transaction) => any): void;
(eventName: 'deleting', subscriber: (this: DeletingHookContext<T,TKey>, primKey:TKey, obj:T, transaction:Transaction) => any): void;
creating: DexieEvent;
reading: DexieEvent;
updating: DexieEvent;
Expand Down
17 changes: 9 additions & 8 deletions api/table.d.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { TableSchema } from "./table-schema";
import { IndexableType } from "./indexed-db/index";
import { IDBValidKey, IndexableTypeArrayReadonly } from "./indexeddb";
import { TableHooks } from "./table-hooks";
import { Collection } from "./collection";
import { ThenShortcut } from "../types/then-shortcut";
import { IndexableTypeArrayReadonly } from "../types/indexable-type";
import { ThenShortcut } from "./then-shortcut";
import { WhereClause } from "./where-clause";
import Promise from "./promise-extended";
import { Database } from "./database";

export interface Table<T=any, TKey extends IndexableType=any> {
export interface Table<T=any, TKey extends IDBValidKey=IDBValidKey> {
db: Database;
name: string;
schema: TableSchema;
hook: TableHooks<T, TKey>;

get(key: TKey): Promise<T | undefined>;
get<R>(key: TKey, thenShortcut: ThenShortcut<T | undefined,R>): Promise<R>;
get(equalityCriterias: {[key:string]:IndexableType}): Promise<T | undefined>;
get<R>(equalityCriterias: {[key:string]:IndexableType}, thenShortcut: ThenShortcut<T | undefined, R>): Promise<R>;
get(equalityCriterias: {[key:string]:IDBValidKey}): Promise<T | undefined>;
get<R>(equalityCriterias: {[key:string]:IDBValidKey}, thenShortcut: ThenShortcut<T | undefined, R>): Promise<R>;
where(index: string | string[]): WhereClause<T, TKey>;
where(equalityCriterias: {[key:string]:IndexableType}): Collection<T, TKey>;
where(equalityCriterias: {[key:string]:IDBValidKey}): Collection<T, TKey>;

filter(fn: (obj: T) => boolean): Collection<T, TKey>;

Expand All @@ -28,7 +29,7 @@ export interface Table<T=any, TKey extends IndexableType=any> {

limit(n: number): Collection<T, TKey>;

each(callback: (obj: T, cursor: {key: IndexableType, primaryKey: TKey}) => any): Promise<void>;
each(callback: (obj: T, cursor: {key: IDBValidKey, primaryKey: TKey}) => any): Promise<void>;

toArray(): Promise<Array<T>>;
toArray<R>(thenShortcut: ThenShortcut<T[], R>): Promise<R>;
Expand Down
11 changes: 11 additions & 0 deletions api/transaction-events.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DexieEvent } from "./dexie-event";
import { DexieEventSet } from "./dexie-event-set";

export interface TransactionEvents extends DexieEventSet {
(eventName: 'complete', subscriber: () => any): void;
(eventName: 'abort', subscriber: () => any): void;
(eventName: 'error', subscriber: (error:any) => any): void;
complete: DexieEvent;
abort: DexieEvent;
error: DexieEvent;
}
9 changes: 5 additions & 4 deletions api/transaction.d.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { Dexie } from "./dexie";
import { Table } from "./table";
import { Database } from "./database";
import { IDBValidKey } from "./indexeddb";
import { TransactionEvents } from "./transaction-events";

export interface Transaction {
//db: Database;
active: boolean;
db: Dexie;
mode: string;
idbtrans: IDBTransaction;
tables: { [type: string]: Table<any, any> };
storeNames: Array<string>;
on: TransactionEvents;
abort(): void;
table(tableName: string): Table<any, any>;
table<T>(tableName: string): Table<T, any>;
table<T, Key>(tableName: string): Table<T, Key>;
table<T, Key extends IDBValidKey>(tableName: string): Table<T, Key>;
}
44 changes: 22 additions & 22 deletions api/where-clause.d.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { IndexableType, IndexableTypeArray, IndexableTypeArrayReadonly } from "../types/indexable-type";
import { IDBValidKey, IndexableTypeArray, IndexableTypeArrayReadonly } from "./indexeddb";
import { Collection } from "./collection";

export interface WhereClause<T=any, Key extends IndexableType=any> {
above(key: IndexableType): Collection<T, Key>;
aboveOrEqual(key: IndexableType): Collection<T, Key>;
anyOf(keys: IndexableTypeArrayReadonly): Collection<T, Key>;
anyOf(...keys: IndexableTypeArray): Collection<T, Key>;
anyOfIgnoreCase(keys: string[]): Collection<T, Key>;
anyOfIgnoreCase(...keys: string[]): Collection<T, Key>;
below(key: IndexableType): Collection<T, Key>;
belowOrEqual(key: IndexableType): Collection<T, Key>;
between(lower: IndexableType, upper: IndexableType, includeLower?: boolean, includeUpper?: boolean): Collection<T, Key>;
equals(key: IndexableType): Collection<T, Key>;
equalsIgnoreCase(key: string): Collection<T, Key>;
inAnyRange(ranges: Array<IndexableTypeArrayReadonly>): Collection<T, Key>;
startsWith(key: string): Collection<T, Key>;
startsWithAnyOf(prefixes: string[]): Collection<T, Key>;
startsWithAnyOf(...prefixes: string[]): Collection<T, Key>;
startsWithIgnoreCase(key: string): Collection<T, Key>;
startsWithAnyOfIgnoreCase(prefixes: string[]): Collection<T, Key>;
startsWithAnyOfIgnoreCase(...prefixes: string[]): Collection<T, Key>;
noneOf(keys: Array<IndexableType>): Collection<T, Key>;
notEqual(key: IndexableType): Collection<T, Key>;
export interface WhereClause<T=any, TKey extends IDBValidKey=IDBValidKey> {
above(key: IDBValidKey): Collection<T, TKey>;
aboveOrEqual(key: IDBValidKey): Collection<T, TKey>;
anyOf(keys: IndexableTypeArrayReadonly): Collection<T, TKey>;
anyOf(...keys: IndexableTypeArray): Collection<T, TKey>;
anyOfIgnoreCase(keys: string[]): Collection<T, TKey>;
anyOfIgnoreCase(...keys: string[]): Collection<T, TKey>;
below(key: IDBValidKey): Collection<T, TKey>;
belowOrEqual(key: IDBValidKey): Collection<T, TKey>;
between(lower: IDBValidKey, upper: IDBValidKey, includeLower?: boolean, includeUpper?: boolean): Collection<T, TKey>;
equals(key: IDBValidKey): Collection<T, TKey>;
equalsIgnoreCase(key: string): Collection<T, TKey>;
inAnyRange(ranges: Array<IndexableTypeArrayReadonly>): Collection<T, TKey>;
startsWith(key: string): Collection<T, TKey>;
startsWithAnyOf(prefixes: string[]): Collection<T, TKey>;
startsWithAnyOf(...prefixes: string[]): Collection<T, TKey>;
startsWithIgnoreCase(key: string): Collection<T, TKey>;
startsWithAnyOfIgnoreCase(prefixes: string[]): Collection<T, TKey>;
startsWithAnyOfIgnoreCase(...prefixes: string[]): Collection<T, TKey>;
noneOf(keys: Array<IDBValidKey>): Collection<T, TKey>;
notEqual(key: IDBValidKey): Collection<T, TKey>;
}
7 changes: 0 additions & 7 deletions src/Dexie.d.ts

This file was deleted.

6 changes: 3 additions & 3 deletions src/Promise.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import {PromiseExtended, PromiseConstructorExtended} from './interfaces/promise-extended';
import {PromiseExtended, PromiseExtendedConstructor} from '../api/promise-extended';

export const NativePromise : PromiseConstructor;
export const AsyncFunction : FunctionConstructor;
Expand All @@ -10,5 +10,5 @@ export function newScope<T> (fn: (...args)=>T, props?, a1?, a2?) : T;
export function usePSD<T> (psd, fn: (...args)=>T, a1?, a2?, a3?) : T;
export function rejection (failure: any) : PromiseExtended<never>;

declare var PromiseExtended : PromiseConstructorExtended;
export default PromiseExtended;
declare var Promise : PromiseExtendedConstructor;
export default Promise;
Loading

0 comments on commit 91b5eef

Please sign in to comment.