diff --git a/node-mysql-wrapper/node-mysql-wrapper-tests.ts b/node-mysql-wrapper/node-mysql-wrapper-tests.ts index 869aa823e..3d26b6e8b 100644 --- a/node-mysql-wrapper/node-mysql-wrapper-tests.ts +++ b/node-mysql-wrapper/node-mysql-wrapper-tests.ts @@ -1,4 +1,7 @@ /// +/// +/// + var express = require('express'); var app = express(); var server = require('http').createServer(app); @@ -9,42 +12,37 @@ class User { //or interface userId: number; username: string; mail: string; + password:string; comments: Comment[]; + myComments: Comment[]; + info: UserInfo; } interface Comment { commentId: number; content: string; + likes: CommentLike[]; } +interface CommentLike { + commentLikeId: number; + userId: number; + commentId: number; +} + +interface UserInfo { + userInfoId: number; + userId: number; + hometown: string; +} db.ready(() => { var usersDb = db.table("users"); - usersDb.rules.orderBy("userId", true); - + + //or var usersDb = db.table("users"); if you don't want intel auto complete from your ide/editor - usersDb.findAll().then(users=> { - users.forEach(user=> { - console.log(user.userId); - }); - }); - - - //define new table rules: usersDb.rules.clear().orderBy....limit....groupBy... - - //define rules but keep unchanged (table's rules) in find method: - usersDb.find({ yearsOld: 22 }, (_users) => { - - console.log("-------------------------------------------------------"); - _users.forEach(_user=> { - console.log(_user.userId + " " + _user.username + " found with limit 3 but this doesnt..."); - - }); - - }).limit(3).execute(); - usersDb.findById(16, (_user) => { console.log("TEST1: \n"); @@ -56,20 +54,27 @@ db.ready(() => { }, (err) => { console.log("ERROR ON FETCHING FINDBY ID: " + err) }); */ - usersDb.find({ userId: 18, comments: { userId: '=' } }, _users=> { - - var _user = _users[0]; - - console.log("TEST2: \n"); - console.log(_user.username + " with "); - console.log(_user.comments.length + " comments "); - _user.comments.forEach(_comment=> { - console.log("--------------\n" + _comment.content); + usersDb.findSingle( + { + userId: 18, + myComments: { + userId: '=', + tableRules: { //NEW: SET rules to joined tables too! + table: "comments", //NEW SET table name inside any property u want! + limit: 50, + orderByDesc: "commentId" //give me the first 50 comments ordered by -commentId (DESC) from table 'comments' and put them at 'myComments' property inside the result object. + } + } + }).then(_user=> { // to get this promise use : .promise() + console.log("\n-------------TEST 2 ------------\n"); + console.log(_user.username + " with "); + console.log(_user.myComments.length + " comments "); + _user.myComments.forEach(_comment=> { + console.log("--------------\n" + _comment.content); + }); }); - }).execute(); - - usersDb.safeRemove(5620, answer=> { + usersDb.remove(5620, answer=> { console.log("TEST 3: \n"); console.log(answer.affectedRows + ' (1) has removed from table: ' + answer.table); @@ -86,8 +91,107 @@ db.ready(() => { }); + + usersDb.find( + { + yearsOld: 22, + comments: { + userId: "=", + tableRules: { + limit: 2 + } + } + + }, (_users) => { + + console.log("---------------TEST 6----------------------------------------"); + _users.forEach(_user=> { + console.log(_user.userId + " " + _user.username + " found with " + _user.comments.length + " comments"); + + }); + + }); + //if no rules setted to find method it's uses the table's rules ( if exists) + + + + let _criteriaFromBuilder = usersDb.criteria + .except("password") // or .exclude(...columns). the only column you cannot except/exclude is the primary key (because it is used at where clause), be careful. + .where("userId", 24) + .joinAs("info", "userInfos", "userId") + .at("info") + .limit(1) //because we make it limit 1 it will return this result as object not as array. + .parent() + .joinAs("myComments", "comments", "userId") + .at("myComments").limit(2) + .joinAs("likes", "commentLikes", "commentId") + .original().orderBy("userId", true).build(); + + /* console.dir(_criteriaFromBuilder); + prints this object: ( of course you can create your own in order to pass it on .find table methods ) + { + userId:23, + + myComments:{ + userId: '=', + + tableRules:{ + table: 'comments', + limit:2 + + }, + + likes:{ + commentId: '=', + + tableRules:{ + table: 'commentLikes' + } + + } + }, + + tableRules:{ + orderByDesc: 'userId', + except: ['password'] + } + + } + + + */ + + + + usersDb.find(_criteriaFromBuilder).then(_users=> { + console.log("\n----------------\nTEST ADVANCED 1\n-------------------\n "); + _users.forEach(_user=> { + console.log(_user.userId + " " + _user.username); + + if (_user.info !== undefined) { + console.log(' from ' + _user.info.hometown); + //console.dir(_user.userInfos); + } + + if (_user.myComments !== undefined) { + _user.myComments.forEach(_comment=> { + console.log(_comment.commentId + " " + _comment.content); + + if (_comment.likes !== undefined) { + console.log(' with ' + _comment.likes.length + ' likes!'); + } + }); + } + }); + + }); + + }); +server.on('uncaughtException', function(err:any) { + console.log(err); +}) var httpPort = 1193;//config.get('Server.port') || 1193; server.listen(httpPort, function() { diff --git a/node-mysql-wrapper/node-mysql-wrapper.d.ts b/node-mysql-wrapper/node-mysql-wrapper.d.ts index 095038faa..af100bbf4 100644 --- a/node-mysql-wrapper/node-mysql-wrapper.d.ts +++ b/node-mysql-wrapper/node-mysql-wrapper.d.ts @@ -1,5 +1,5 @@ // Type definitions for node-mysql-wrapper -// Project: https://github.com/kataras/node-mysql-wrapper +// Project: https://github.com/nodets/node-mysql-wrapper // Definitions by: Makis Maropoulos // Definitions: https://github.com/borisyankov/DefinitelyTyped @@ -12,11 +12,42 @@ declare module "node-mysql-wrapper" { import {EventEmitter} from 'events'; var EQUAL_TO_PROPERTY_SYMBOL: string; + var TABLE_RULES_PROPERTY: string; + + type DeleteAnswer = { + affectedRows: number; + table: string; + }; + + type RawRules = { + table: string, + begin: string, + orderBy: string, + orderByDesc: string, + groupBy: string, + limit: number, // limit = limitStart =0 and limitEnd = limit. + limitStart: number, + limitEnd: number, + end: string + + }; + + type TableToSearchPart = { tableName: string, propertyName: string }; interface Map { [index: string]: T; } + interface IQuery { + _table: Table; + execute(rawCriteria: any, callback?: (_results: any) => any): Promise; + } + + interface IQueryConstructor { + new (_table: Table): IQuery; + } + + class Helper { /** * Callback like forEach @@ -61,9 +92,7 @@ declare module "node-mysql-wrapper" { * @return {string} */ static toRowProperty(objectKey: string): string; - - /** * Iterate object's keys and return their values to the callback. * @param {Map} map the object. @@ -80,17 +109,38 @@ declare module "node-mysql-wrapper" { * @returnType {U} * @return {U} */ + static forEachKey(map: Map, callback: (key: string) => U): U; + + /** + * Checks if anything is a function. + * @param {functionToCheck} the object or function to pass + * @return boolean + */ + static isFunction(functionToCheck: any): boolean; + + /** + * Checks if an object has 'tableRules' property. + * @param {obj} the object to pass + * @return boolean + */ + static hasRules(obj: any): boolean; } - interface ICriteria { + + interface ICriteriaParts { rawCriteriaObject: any; - tables: string[]; + tables: TableToSearchPart[]; noDatabaseProperties: string[]; whereClause: string; + + selectFromClause(_table: Table): string; + } - class Criteria implements ICriteria { + + + class CriteriaParts implements ICriteriaParts { /** * The raw format of the criteria eg: {yearsOld:22}. @@ -100,7 +150,7 @@ declare module "node-mysql-wrapper" { /** * Which tables to search after the find method of the proto table finish. */ - tables: string[]; + tables: TableToSearchPart[]; /** * The properties of the criteria which don't belong to the database's table. @@ -112,10 +162,12 @@ declare module "node-mysql-wrapper" { */ whereClause: string; - constructor(rawCriteriaObject: any, tables: string[], noDatabaseProperties: string[], whereClause: string); + constructor(rawCriteriaObject: any, tables: TableToSearchPart[], noDatabaseProperties: string[], whereClause: string); + + selectFromClause(_table: Table): string; } - class CriteriaBuilder { + class CriteriaDivider { private _table; constructor(table: Table); @@ -125,70 +177,131 @@ declare module "node-mysql-wrapper" { * @returnType {Criteria} * @return {Criteria} */ - build(rawCriteriaObject: any): Criteria; + build(rawCriteriaObject: any): CriteriaParts; } class SelectQueryRules { - orderByClause: string; - groupByClause: string; - limitClause: string; - - + private lastPropertyClauseName: string; + manuallyEndClause: string; + manuallyBeginClause: string; + exceptColumns: string[]; + orderByColumn: string; + orderByDescColumn: string; + groupByColumn: string; + limitStart: number; + limitEnd: number; + public tableName: string; //auto den benei oute sto last, oute sto from. static build(): SelectQueryRules; - static build(parentRule?: SelectQueryRules): SelectQueryRules; + private last(propertyClauseName); + except(...columns: string[]): SelectQueryRules; + + /** + * Same as .except(...columns) + */ + exclude(...columns: string[]): SelectQueryRules; orderBy(columnKey: string, descending?: boolean): SelectQueryRules; - groupBy(columnKey: string): SelectQueryRules; - limit(limitRowsOrStart: number, limitEnd?: number): SelectQueryRules; - + appendToBegin(manualAfterWhereString: string): SelectQueryRules; + appendToEnd(manualAfterWhereString: string): SelectQueryRules; + append(appendToCurrent: string): SelectQueryRules; clearOrderBy(): SelectQueryRules; - clearGroupBy(): SelectQueryRules; - clearLimit(): SelectQueryRules; - + clearEndClause(): SelectQueryRules; + clearBeginClause(): SelectQueryRules; clear(): SelectQueryRules; - from(parentRule: SelectQueryRules): SelectQueryRules; - + isEmpty(): boolean; toString(): string; + toRawObject(): RawRules; + static toString(rules: SelectQueryRules): string; + static toRawObject(rules: SelectQueryRules): RawRules; + static fromRawObject(obj: RawRules): SelectQueryRules; } - class SelectQuery { + class CriteriaBuilder{ - private _rules: SelectQueryRules; - private _table: Table; - private _criteriaRawJsObject: any; - private _callback: (_results: T[]) => any; - private callback: (resolve?: (thenableOrResult?: T | Promise.Thenable) => void, reject?: (error?: any) => void) => void; + private rawCriteria: any; + private primaryTable: Table; + private parentBuilder: CriteriaBuilder; - constructor(table: Table, criteriaRawJsObject: any, callback?: (_results: T[]) => any); + constructor(primaryTable: Table); //to arxiko apo to Table.ts 9a benei + constructor(primaryTable: Table, tableName: string, parentBuilder: CriteriaBuilder);// auta 9a benoun apo to parent select query. + constructor(primaryTable: Table, tablePropertyName?: string, parentBuilder?: CriteriaBuilder); - orderBy(columnKey: string, descending?: boolean): SelectQuery; + except(...columns: string[]): CriteriaBuilder; + + /** + * Same as .except(...columns) + */ + exclude(...columns: string[]): CriteriaBuilder; - groupBy(columnKey: string): SelectQuery; + where(key: string, value: any): CriteriaBuilder; - limit(limitRowsOrStart: number, limitEnd?: number): SelectQuery; + private createRulesIfNotExists(): void; + + orderBy(column: string, desceding?: boolean): CriteriaBuilder; + + limit(start: number, end?: number): CriteriaBuilder; + + join(realTableName: string, foreignColumnName: string): CriteriaBuilder; + + joinAs(tableNameProperty: string, realTableName: string, foreignColumnName: string): CriteriaBuilder; + + at(tableNameProperty: string): CriteriaBuilder; + + parent(): CriteriaBuilder; + + original(): CriteriaBuilder; + + /** + * Auto kanei kuklous mexri na paei sto primary table kai ekei na epistrepsei to sunoliko raw criteria gia execute i kati allo. + */ + build(): any; + + static from(table: Table): CriteriaBuilder + + } + + class SelectQuery implements IQuery { // T for Table's result type. + + _table: Table + constructor(_table: Table); + + private parseQueryResult(result: any, criteria: ICriteriaParts): Promise; /** - * Executes the select and returns the Promise. - */ - promise(): Promise; - + * Executes the select and returns the Promise. + */ + promise(rawCriteria: any, callback?: (_results: T[]) => any): Promise; + /** * Exactly the same thing as promise(). * Executes the select and returns the Promise. - */ - execute(): Promise; - - then(onFulfill: (value: any[]) => any|Promise.Thenable): Promise; - then(onFulfill: (value: T[]) => U|Promise.Thenable, onReject: (error: any) => Promise.Thenable, onProgress?: (note: any) => any): Promise; - then(onFulfill: (value: T[]) => U|Promise.Thenable, onReject?: (error: any) => U, onProgress?: (note: any) => any): Promise; - + */ + execute(rawCriteria: any, callback?: (_results: T[]) => any): Promise; } + class SaveQuery implements IQuery { + + _table: Table + constructor(_table: Table); + + execute(criteriaRawJsObject: any, callback?: (_result: T | any) => any): Promise; + } + + class DeleteQuery implements IQuery{ + + _table: Table + constructor(_table: Table); + + execute(criteriaOrID: any | number | string, callback?: (_result: DeleteAnswer) => any): Promise; + } + + + class Connection extends EventEmitter { /** @@ -325,14 +438,17 @@ declare module "node-mysql-wrapper" { } class Table { - private _name; - private _connection; - private _columns; - private _primaryKey; - private _criteriaBuilder; - private _rules; + private _name: string; + private _connection: Connection; + private _columns: string[]; + private _primaryKey: string; + private _criteriaDivider: CriteriaDivider; + private _rules: SelectQueryRules; + private _selectQuery: SelectQuery + private _saveQuery: SaveQuery; + private _deleteQuery: DeleteQuery; constructor(tableName: string, connection: Connection); - + /** * An array of all columns' names inside this table. */ @@ -355,9 +471,23 @@ declare module "node-mysql-wrapper" { /** * Set of the query rules that will be applied after the 'where clause' on each select query executed by this table. + * @return {SelectQueryRules} */ rules: SelectQueryRules; + /** + * Returns this table's criteria divider class. + * @return {CriteriaDivider} + */ + criteriaDivider: CriteriaDivider; + + /** + * Returns new Criteria Builder each time. + * Helps you to make criteria raw js objects ready to use in find,remove and save methods. + * @return {CriteriaBuilder} + */ + criteria: CriteriaBuilder; + /** * Adds or turn on an event listener/watcher on a table for a 'database event'. * @param {string} evtType the event type you want to watch, one of these: ["INSERT", "UPDATE", "REMOVE", "SAVE"]. @@ -424,48 +554,31 @@ declare module "node-mysql-wrapper" { * @return {number | string} */ getPrimaryKeyValue(jsObject: any): number | string; - - parseQueryResult(result: any, criteria: ICriteria): Promise; /** * */ - find(criteriaRawJsObject: any): SelectQuery; // only criteria - find(criteriaRawJsObject: any, callback: ((_results: T[]) => any)): SelectQuery; // criteria and callback - find(criteriaRawJsObject: any, callback?: (_results: T[]) => any): SelectQuery; + find(criteriaRawJsObject: any): Promise; // only criteria + find(criteriaRawJsObject: any, callback: ((_results: T[]) => any)): Promise; // criteria and callback + find(criteriaRawJsObject: any, callback?: (_results: T[]) => any): Promise; + + findSingle(criteriaRawJsObject: any, callback?: (_result: T) => any): Promise; findById(id: number|string): Promise; // without callback findById(id: number | string, callback?: (result: T) => any): Promise; - findAll(): SelectQuery; // without callback - findAll(callback?: (_results: T[]) => any): SelectQuery; + findAll(): Promise; // only criteria and promise + findAll(tableRules: RawRules): Promise // only rules and promise + findAll(tableRules?: RawRules, callback?: (_results: T[]) => any): Promise; + save(criteriaRawJsObject: any): Promise; //without callback save(criteriaRawJsObject: any, callback?: (_result: any) => any): Promise; - safeRemove(id: number | string): Promise<{ - affectedRows: number; - table: string; - }>; //withoutcallback - safeRemove(id: number | string, callback?: (_result: { - affectedRows: number; - table: string; - }) => any): Promise<{ - affectedRows: number; - table: string; - }>; + remove(id: number | string): Promise; // ID without callback + remove(criteriaRawObject: any): Promise; // criteria obj without callback + remove(criteriaOrID: any | number | string, callback?: (_result: DeleteAnswer) => any): Promise; - remove(criteriaRawObject: any): Promise<{ - affectedRows: number; - table: string; - }>; // without callback - remove(criteriaRawJsObject: any, callback?: (_result: { - affectedRows: number; - table: string; - }) => any): Promise<{ - affectedRows: number; - table: string; - }>; } class Wrapper {