UNPKG

tedb

Version:

TypeScript Embedded Database

284 lines (283 loc) 10.4 kB
/** * 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(); }