UNPKG

very-simple-orm

Version:

This is simple orm for typesript/javascript projects

323 lines (243 loc) 10.5 kB
import { FIELD, FIELD_NAME_VALUE_OPERATOR, JOIN, SQL_VALUES, SQL_VALUES_MANY, TABLE } from "../Iinterfaces"; import {stringType, numberType, enumType, dateType, booleanType, doubleType, textType, CURRENT_TIMESTAMP, NULL, AS_DEFINED, dateTimeType} from "../Iinterfaces/runtime" import { FIELD_NAME_VALUE, SQL_MASTER } from "../Iinterfaces"; import Delete from "./base_sql/Delete"; import Insert from "./base_sql/Insert"; import Select from "./base_sql/Select" import Update from "./base_sql/Update"; export default class Table implements TABLE, SQL_MASTER { /**name of the table */ readonly tableName!: string; readonly fields!: FIELD[]; private selectCls: Select; private updateCls: Update; private insertCls: Insert; private deleteCls: Delete; constructor(_name: string, _fields: FIELD[]) { this.tableName = _name; this.fields = _fields; this.selectCls = new Select(this.tableName) this.updateCls = new Update(this.tableName) this.insertCls = new Insert(this.tableName) this.deleteCls = new Delete(this.tableName) } /** * * @param _insertFields * @returns */ insert(_insertFields: FIELD_NAME_VALUE[]): SQL_VALUES { // write code for valdation of fileds here this.validateHandler(_insertFields) return this.insertCls.insert(_insertFields) } /** * * @param _insertFields two dimensional array filed and values * return sql string and two dimensiona array */ insertMany(_insertFields: FIELD_NAME_VALUE[][]): SQL_VALUES_MANY { _insertFields.forEach(el=>{ this.validateHandler(el); }) return this.insertCls.insertMany(_insertFields) } /** * * @param _field * @returns */ deleteById(_field: FIELD_NAME_VALUE): SQL_VALUES { return this.deleteCls.deleteById(_field) } /** * * @param _clauseField where clase uarguments * @returns SQL and values */ delete(_clauseField: FIELD_NAME_VALUE_OPERATOR[]): SQL_VALUES { return this.deleteCls.delete(_clauseField); } /** * * @param _idField id field * @param _selectedFields The field o fthe table to reurned * @param _orderBy by filed either ASC | DESC * @param _limit number of rows limited * @param _offset number of rows to be offset * @returns sql string and values array of the clause */ selectById(_idField:FIELD_NAME_VALUE, _selectedFields ?:string[], _orderBy?:{fields:string[], by:"ASC" | "DESC"}, _limit?:number, _offset?:number):SQL_VALUES { // write validation code here return this.selectCls.selectById(_idField, _selectedFields, { "fields" : _orderBy?.fields ? _orderBy.fields : [], "by" : _orderBy?.by ? _orderBy.by : "ASC" }, _limit ? _limit : 0, _offset ? _offset : 0) } /** * * @param _clauseFields These th fileds in the clause , use AND | OR | NONE opertaor NONE oprator is is to be used only at last element of array * @param _selectedFields The field o fthe table to reurned * @param _orderBy by filed either ASC | DESC * @param _limit number of rows limited * @param _offset number of rows to be offset * @returns sql string and values array of the clause */ select(_clauseFields?:FIELD_NAME_VALUE_OPERATOR[], _selectedFields ?:string[], _orderBy?:{fields:string[], by:"ASC" | "DESC"}, _limit?:number, _offset?:number, _join ?:JOIN[] ):SQL_VALUES { return this.selectCls.select(_clauseFields, _selectedFields, { "fields" : _orderBy?.fields ? _orderBy.fields : [], "by" : _orderBy?.by ? _orderBy.by : "ASC" }, _limit ? _limit : 0, _offset ? _offset : 0, _join ); } /** * * @param _field id file dof table * @param _updateFields update fileds * @returns sql string and values array of the clause */ updateById(_field: FIELD_NAME_VALUE, _updateFields: FIELD_NAME_VALUE[]): SQL_VALUES { this.validateHandler(_updateFields) return this.updateCls.updateById(_field, _updateFields); } /** * * @param _updateFields update fileds * @param _clauseFileds clause fileds * @returns sql string and values */ update(_updateFields:FIELD_NAME_VALUE[], _clauseFileds:FIELD_NAME_VALUE_OPERATOR[] ):SQL_VALUES { this.validateHandler(_updateFields) return this.updateCls.update(_updateFields, _clauseFileds); } /** * createTable */ public createTable(): string { let __fields: string = "" this.fields.forEach(curField => { // set name of field __fields = __fields + " " + curField.fieldName; // set type of field if (stringType(curField.type)) { __fields = __fields + " varchar" if (curField.type.size) { __fields = __fields + "(" + curField.type.size + ")"; } else { __fields = __fields + "(255)"; } } else if (numberType(curField.type)) { __fields = __fields + " int" if (curField.type.autoIncrement) { __fields = __fields + " AUTO_INCREMENT" } } else if (dateType(curField.type)) { __fields = __fields + " date" } else if(dateTimeType(curField.type)){ __fields = __fields + " datetime" } else if (textType(curField.type)) { __fields = __fields + " text" } else if (booleanType(curField.type)) { __fields = __fields + " tinyint(1)" } else if (doubleType(curField.type)) { __fields = __fields + " double"; } else if (enumType(curField.type)) { __fields = __fields + " enum"; let EnumArray: string = ""; curField.type.enumValues.forEach(el => { EnumArray = `${EnumArray}, "${el}"` }) EnumArray = EnumArray.trim().substring(1, EnumArray.trim().length) __fields = __fields + "(" + EnumArray + ")"; } // set null or not null if (curField.null) { __fields = __fields + " NULL" } else { __fields = __fields + " NOT NULL" } // default value if(curField.default !== undefined){ if (CURRENT_TIMESTAMP(curField.default)) { __fields = __fields + " DEFAULT CURRENT_TIMESTAMP" } else if (NULL(curField.default)) { __fields = __fields + " DEFAULT NULL" } else if (AS_DEFINED(curField.default)) { __fields =`${__fields} DEFAULT ${curField.default.value.toString()}` } } __fields = __fields + "," }) __fields = __fields.trim(); /** * set keys */ let __keys: string = "" this.fields.forEach(curField => { if (curField.PrimeryKey) { __keys = __keys + " PRIMARY KEY (" + curField.fieldName + ")," } if (curField.unique) { __keys = __keys + " UNIQUE KEY " + this.tableName + "_" + curField.fieldName + "(" + curField.fieldName + ")," } }) __keys = __keys.trim(); let __FiledKeys = __fields + __keys while ((__FiledKeys[__FiledKeys.trim().length - 1] == ",")) { __FiledKeys = __FiledKeys.substring(0, __FiledKeys.length - 1) } let __sql = `CREATE TABLE IF NOT EXISTS ${this.tableName} (${__FiledKeys})ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4` return __sql.trim() + ";"; } /** * This function creates relationship * @param thisTableFieldName FOREIGN KEY of this table * @param otherTable name of related table * @param otherTablefieldName REFERENCES of retated table\ * @onDelete "RESTRICT" | "CASCADE" * @onUpdate "RESTRICT" |"NO ACTION" | "CASCADE" | "SET NULL" | "SET DEFAULT" */ public relatetable(thisTableFieldName: string, otherTable: string, otherTablefieldName: string, onDelete: "RESTRICT" | "CASCADE" = "RESTRICT", onUpdate: "RESTRICT" | "NO ACTION" | "CASCADE" | "SET NULL" | "SET DEFAULT" = "RESTRICT"): string { let __sql = `ALTER TABLE ${this.tableName} ADD CONSTRAINT ${otherTable}_${this.tableName} FOREIGN KEY (${thisTableFieldName}) REFERENCES ${otherTable} (${otherTablefieldName}) ON DELETE ${onDelete} ON UPDATE ${onUpdate}`; return __sql.trim() + ";" } /** * This method retruns the contraint selct statement * @param constraint name of constraint * @returns reqturns sql_vales */ public getConstraint(constraint:string):SQL_VALUES { let sql = `SELECT CONSTRAINT_NAME FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = ?`; return{ "sql" :sql, "values" : [constraint] } } /** * This function throws error in case there is falire of validation * @param _sqlField this is array of field which destned to update or insert table in insert and update operations */ private validateHandler(_sqlField:FIELD_NAME_VALUE[]) { _sqlField.forEach(inF=>{ let curField = this.fields.find(f=>{ if(f.fieldName == inF.fieldName){ return f } }) if(curField?.validate){ let fieldCheck = curField.validate(inF.value) if(!fieldCheck){ throw new Error().message=`validation failure at field ${inF.fieldName} and for this value ${inF.value}` } } }) } }