tedb
Version:
TypeScript Embedded Database
284 lines (283 loc) • 10.4 kB
TypeScript
/**
* Created by tsturzl on 4/11/17.
*/
import Index from "./indices";
import { IindexOptions, IStorageDriver, IupdateOptions } from "./types";
import { Cursor, Ioptions } from "./index";
/**
* ~~~
* Array String Number, Date, Boolean, -> symbol was redacted. : Used for keys
* BTT.ASNDBS = Array<any[]|string|number|Date|boolean|null>|string|number|Date|boolean|null
* -> redacted symbol, Number, Date, Boolean, String, Array : Used for values
* BTT.SNDBSA = Array<{}|any[]|string|number|Date|boolean|null>;
* ~~~
*/
export interface IDatastore {
insert(doc: any): Promise<any>;
find(query: any): Cursor;
count(query: any): Cursor;
update(query: any, operation: any, options: IupdateOptions): Promise<any>;
remove(query: any): Promise<number>;
ensureIndex(options: IindexOptions): Promise<null>;
san(fieldName: string, index: Index): Promise<any>;
sanitize(): Promise<any>;
storageSan(fieldName: string): Promise<any>;
storageSanitize(): any;
removeIndex(fieldName: string): Promise<null>;
saveIndex(fieldName: string): Promise<null>;
insertIndex(key: string, index: any[]): Promise<null>;
getIndices(): Promise<any>;
getDocs(options: Ioptions, ids: string | string[]): Promise<any[]>;
search(fieldName: string, value: any): Promise<string[]>;
}
/**
* Datastore class
*
* Example:
* ~~~
* const UserStorage = new yourStorageClass("users");
* const Users = new Datastore({storage: UserStorage});
* ~~~
* Creates a new Datastore using a specified storageDriver
*/
export default class Datastore implements IDatastore {
/** A HashMap of all the indices keyed by the fieldName. <fieldName, Index> */
private indices;
/** StorageDriver that is used for this Datastore */
private storage;
/** whether or not to generate IDs automatically */
private generateId;
/**
* @param config - config object `{storage: IStorageDriver}`
*/
constructor(config: {
storage: IStorageDriver;
});
/**
* Insert a single document and insert any indices of document into
* its respective binary tree.
*
* ~~~
* Users.insert({name: "xyz", age: 30})
* .then((doc) => console.log(doc)) // {_id: "...", name: "xyz", age: 30}
* .catch((e) => console.log(e));
* ~~~
*
* @param doc - document to insert
* @returns {Promise<any>}
*/
insert(doc: any): Promise<any>;
/**
* Find documents
*
* Examples:
* ~~~
* Users.find()
* .sort({age: -1})
* .skip(1)
* .limit(10)
* .exec()
* .then((users) => console.log(users))
* .catch((e) => console.log(e));
*
* Users.find({$or: [{name: "a"}, {name: "b"}]})
* .then((docs) => console.log(docs.length)) // 2 if unique
* .catch((e) => console.log(e));
*
* return Users.find({age: {$gt: 0, $lte: 27, $ne: 5}});
*
* // sort from doc creation date. Auto generated by the _id
* Users.find({})
* .sort({$created_at: -1}) // descending
* .exec()
* .then(resolve)
* .catch(reject);
* ~~~
* @param query
* @returns {Cursor}
*/
find(query?: any): Cursor;
/**
* Count documents
* @param query
*/
count(query?: any): Cursor;
/**
* Update document/s
*
* Examples: -> lets say two users {name: "bob", age: 1},
* {name: "slydel", age: 45, companies: {name: "Initech", alternate: "Intertrode"}}
* ~~~
* Users.update({name: "bob"},{$rename: {name: "first"}, $set: {job: "consultant"}},
* {returnUpdatedDocs: true})
* .then((docs) => console.log(docs[0]) // {_id: "...", first: "bob", age: 1, job: "consultant"}
* .catch();
*
* Users.update({first: "bob"},{$unset: {"companies.alternate": ""}, $inc: {age: -44},
* $mul: {age: 5}}, {returnUpdatedDocs: true})
* .then((docs) => console.log(docs[0]) // {_id: "...", name: "bob", age: 5, companies: {name: "Initech"}}
* .catch();
*
* Users.update({name: "Charles", age: 22}, {$inc: {age: 4}}, {upser: true, returnUpdatedDocs: true}})
* .then((docs) => console.log(docs[0]) // {_id: "...", name: "Charles", age: 26}
* .catch();
*
* Users.update({age: {$gt: 0}},{$unset: {age: "", name: ""}},{ multi: true, returnUpdatedDocs: true})
* .then((docs) => console.log(docs)) // {_id: ".."}, {_id: ".."}, {_id: "..", companies: {name: "Initech"}}
* .catch();
* ~~~
* @param query - query document/s to update
* @param operation - update operation, either a new doc or modifies portions of a document(eg. `$set`)
* @param options - { fieldName, unique?, compareKeys?, checkKeyEquality? }
* @returns {Promise<any>}
*/
update(query: any, operation: any, options?: IupdateOptions): Promise<any>;
san(fieldName: string, index: Index): Promise<any>;
storageSan(fieldName: string): Promise<any>;
storageSanitize(): any;
/**
* Method used after a remove depending on the want of the user
* to make sure that if an _id exists in the index that it should
* exist in the storage driver saved location. If not then the
* indexed item is removed from the index as to not cause lookup
* errors.
* @returns {Promise<any>}
*/
sanitize(): Promise<any>;
/**
* Removes document/s by query - uses find method to retrieve ids. multi always
* @param query
* @returns {Promise<number>}
*/
remove(query?: any): Promise<number>;
/**
* Ensure an index on the datastore
*
* Example:
* ~~~
* return Users.ensureIndex({fieldName: "username", unique: true});
* ~~~
* @param options
* @returns {Promise<null>}
*/
ensureIndex(options: IindexOptions): Promise<null>;
/**
* Remove index will delete the index from the Map which also
* holds the Btree of the indices. If you need to remove the
* index from the persisted version in from the storage driver,
* call the removeIndex from the storage driver from a different source.
* This method should not assume you saved the index.
* @param fieldName - Field that needs index removed
* @returns {Promise<null>}
*/
removeIndex(fieldName: string): Promise<null>;
/**
* Save the index currently in memory to the persisted version if need be
* through the storage driver.
* @param fieldName
* @returns {Promise<any>}
*/
saveIndex(fieldName: string): Promise<null>;
/**
* Insert a stored index into the index of this datastore
* @param key - the index fieldName
* @param index - the key value pair obj
* @returns {Promise<null>}
*/
insertIndex(key: string, index: any[]): Promise<null>;
/**
* Retrieve the indices of this datastore.
*
* Example:
* ~~~
* Users.getIndices()
* .then((indices) => {
* let usernameIndex = indices.get("username");
* if(usernameIndex) {
* return usernameIndex.toJSON(); // a method on index bTree
* }
* }); // no reject, will always resolve
* ~~~
* @returns {Promise<any>}
*/
getIndices(): Promise<any>;
/**
* Get Document by ID/s
* Used internally
* @param options - sort limit skip options
* @param ids - ID or Array of IDs
* @returns {Promise<any>}
*/
getDocs(options: Ioptions, ids: string | string[]): Promise<any>;
/**
* Search for IDs, chooses best strategy. Handles logical operators($or, $and)
* Returns array of IDs
* Used Internally
* @param fieldName - element name or query start $or/$and
* @param value - string,number,date,null - or [{ field: value }, { field: value }]
* @returns {Promise<T>}
*/
search(fieldName?: string, value?: any): Promise<any>;
/**
* Get Date from ID ... do we need this on the dataStore?
*
* Example:
* ~~~
* let id = "UE9UQVJWd0JBQUE9cmZ4Y2MxVzNlOFk9TXV4dmJ0WU5JUFk9d0FkMW1oSHY2SWs9"; // an ID
* Users.getIdDate(id); // date object -> 2017-05-26T17:14:48.252Z
* ~~~
* @param id - the `_id` of the document to get date of
* @returns {Date}
*/
getIdDate(id: string): Date;
/**
* Search for IDs, chooses best strategy, preferring to search indices if they exist for the given field.
* Returns array of IDs
* @param fieldName
* @param value
* @returns {Promise<BTT.SNDBSA>}
*/
private searchField(fieldName?, value?);
/**
* Search indices by field
* Example 1: dbName.searchIndices("fieldName", "1234");
* will return the value id of that key as an array of one element.
* Example 2: dbName.searchIndices("fieldName", { $gte: 1, $lte 10, $ne: 3 }
* will return an array of ids from the given range.
* Returns array of IDs
* @param fieldName - field to search
* @param value - value to search by
* @returns {Promise<BTT.SNDBSA>}
*/
private searchIndices(fieldName, value);
/**
* Search collection by field, essentially a collection scan
* Returns array of IDs
* @param fieldName - field to search
* @param value - value to search by
* @returns {Promise<T>}
*/
private searchCollection(fieldName?, value?);
/**
* Actual method to update the documents and associated indices
* @param docs - an array of documents to be updated
* @param promises - reference to promise array to be resolved later
* @param indexPromises - reference to promise array to be resolved later
* @param operation - operation query from update method
* @param operators - array of operators passed by reference from the update method
* @param operationKeys - Each key from the query. could be less than operators array length
* @param reject - passed reference to reject from update method.
*/
private updateDocsIndices(docs, promises, indexPromises, operation, operators, operationKeys, reject);
/**
* Return fill provided promise array with promises from the storage driver
* @param promises
* @param ids
*/
private createIdsArray(ids);
/**
* Create Unique ID that contains timestamp
* @returns {string}
*/
private createId();
}