├── .gitignore ├── validators ├── validate-like-percent.js ├── validate-parameters.js └── validate-operators.js ├── functions ├── config.js ├── end-connection.js └── start-connection.js ├── LICENSE ├── package.json ├── methods ├── begin-transaction.js ├── commit.js ├── rollback.js ├── select.js ├── insert.js ├── delete.js └── update.js ├── README.md └── lib └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | .env 3 | .eslintrc.json -------------------------------------------------------------------------------- /validators/validate-like-percent.js: -------------------------------------------------------------------------------- 1 | function ValidateLIKEPercent (_parameter, _paramNumber) 2 | { 3 | const parameter = { ..._parameter }; 4 | const percent = parameter.percent.toLowerCase(); 5 | 6 | if (percent === "start") 7 | { 8 | return `'%'||$${_paramNumber}`; 9 | } 10 | else if (percent === "end") 11 | { 12 | return `$${_paramNumber}||'%'`; 13 | } 14 | else if (percent === "both") 15 | { 16 | return `'%'||$${_paramNumber}||'%'`; 17 | } 18 | else 19 | { 20 | return undefined; 21 | } 22 | } 23 | 24 | module.exports = ValidateLIKEPercent; 25 | -------------------------------------------------------------------------------- /functions/config.js: -------------------------------------------------------------------------------- 1 | function Config (_config) 2 | { 3 | if (_config instanceof Object && !(_config instanceof Array)) 4 | { 5 | const config = { ..._config }; 6 | if (config.method) 7 | { 8 | const method = config.method.toLowerCase(); 9 | delete config.method; 10 | const configInfo = { 11 | ...config, 12 | }; 13 | 14 | return { 15 | method, 16 | config: configInfo 17 | }; 18 | } 19 | else 20 | { 21 | throw new Error("You must provide a method to connect to the database. Choose between 'pool' or 'client'"); 22 | } 23 | } 24 | else 25 | { 26 | throw new Error ("The config must be a JSON specifying how do you want to connect to the database, such as 'pool' or 'client'"); 27 | } 28 | } 29 | 30 | module.exports = Config; 31 | -------------------------------------------------------------------------------- /functions/end-connection.js: -------------------------------------------------------------------------------- 1 | function EndConnection (_connection) 2 | { 3 | const connectionStatus = { 4 | beginTransaction: { 5 | success: false, 6 | error: false, 7 | }, 8 | start: { 9 | success: false, 10 | error: false, 11 | }, 12 | end: { 13 | success: false, 14 | error: false, 15 | }, 16 | commit: { 17 | success: false, 18 | error: false, 19 | }, 20 | rollback: { 21 | success: false, 22 | error: false, 23 | }, 24 | }; 25 | 26 | const end = _connection.end() 27 | .then( () => 28 | { 29 | connectionStatus.end.success = true; 30 | 31 | return connectionStatus.end; 32 | }) 33 | .catch( (err) => 34 | { 35 | connectionStatus.end.error = err.message; 36 | 37 | return connectionStatus.end; 38 | }); 39 | 40 | return end; 41 | } 42 | 43 | module.exports = EndConnection; 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Ana Paula Oliveira de Lima 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "pg": "^8.7.1" 4 | }, 5 | "name": "query-tool", 6 | "description": "The QueryTool is a library that allows easier and faster connections with Postgres databases. Whit it, you can make insertions, selections, updates and deletions in the database in a simple and effective way.", 7 | "version": "2.0.1", 8 | "main": "./lib", 9 | "scripts": { 10 | "test": "echo \"Error: no test specified\" && exit 1" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/anapolima/Query-Tool.git" 15 | }, 16 | "keywords": [ 17 | "sql", 18 | "pg", 19 | "postgre", 20 | "postgres", 21 | "querytool", 22 | "database", 23 | "postgresql", 24 | "connection", 25 | "pool", 26 | "client", 27 | "query", 28 | "tool", 29 | "transaction" 30 | ], 31 | "author": "Ana Paula Oliveira de Lima ", 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/anapolima/Query-Tool/issues" 35 | }, 36 | "homepage": "https://github.com/anapolima/Query-Tool/wiki", 37 | "devDependencies": { 38 | "eslint": "^8.2.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /validators/validate-parameters.js: -------------------------------------------------------------------------------- 1 | function ValidateParameters (_param) 2 | { 3 | if (Array.isArray(_param.columns)) 4 | { 5 | const arrayColumns = _param.columns; 6 | const specialRegex = /[;|\s]?truncate$|[;|\s]?drop$|[;|\s]?update$|[;|\s]?insert$/i; 7 | const specialRegexCompound = /[;|\s]?truncate table$|[;|\s]?drop table$|[;|\s]?drop column$|[;|\s]?drop database$|[;|\s]?alter table$|[;|\s]?add column$|[;|\s]?create table$|[;|\s]?create database$|[;|\s]?create view$|[;|\s]?create index$|[;|\s]?update table$/i; 8 | 9 | if (specialRegex.test(JSON.stringify(arrayColumns)) || specialRegexCompound.test(JSON.stringify(arrayColumns))) 10 | { 11 | throw new Error ("It looks like you trying to modify the database."); 12 | } 13 | delete _param.columns; 14 | } 15 | 16 | const regex = /[;|\s]?truncate$|[;|\s]?drop$|[;|\s]?update$|[;|\s]?insert$|[;|\s]?select$/i; 17 | const regexCompound = /[;|\s]?truncate table$|[;|\s]?drop table$|[;|\s]?drop column$|[;|\s]?drop database$|[;|\s]?alter table$|[;|\s]?add column$|[;|\s]?create table$|[;|\s]?create database$|[;|\s]?create view$|[;|\s]?create index$|[;|\s]?update table$|[;|\s]?select [a-zA-ZÀ-ü\W]+ from$/i; 18 | 19 | if (regex.test(JSON.stringify(_param)) || regexCompound.test(JSON.stringify(_param))) 20 | { 21 | throw new Error ("It looks like you trying to modify the database."); 22 | } 23 | 24 | return true; 25 | } 26 | 27 | module.exports = ValidateParameters; 28 | -------------------------------------------------------------------------------- /methods/begin-transaction.js: -------------------------------------------------------------------------------- 1 | function BeginTransaction (_method, _connection) 2 | { 3 | const connectionStatus = { 4 | beginTransaction: { 5 | success: false, 6 | error: false, 7 | }, 8 | start: { 9 | success: false, 10 | error: false, 11 | }, 12 | end: { 13 | success: false, 14 | error: false, 15 | }, 16 | commit: { 17 | success: false, 18 | error: false, 19 | }, 20 | rollback: { 21 | success: false, 22 | error: false, 23 | }, 24 | }; 25 | 26 | if (_method === "client") 27 | { 28 | const beginTransaction = _connection 29 | .query("BEGIN;") 30 | .then( () => 31 | { 32 | connectionStatus.beginTransaction.success = true; 33 | 34 | return connectionStatus.beginTransaction; 35 | }) 36 | .catch( (err) => 37 | { 38 | connectionStatus.beginTransaction.error = err.message; 39 | 40 | return connectionStatus.beginTransaction; 41 | }); 42 | 43 | return beginTransaction; 44 | } 45 | else 46 | { 47 | const beginTransaction = _connection 48 | .query("BEGIN;") 49 | .then( () => 50 | { 51 | connectionStatus.beginTransaction.success = true; 52 | 53 | return connectionStatus.beginTransaction; 54 | }) 55 | .catch( (err) => 56 | { 57 | connectionStatus.beginTransaction.error = err.message; 58 | 59 | return connectionStatus.beginTransaction; 60 | }); 61 | 62 | return beginTransaction; 63 | } 64 | } 65 | 66 | module.exports = BeginTransaction; 67 | -------------------------------------------------------------------------------- /methods/commit.js: -------------------------------------------------------------------------------- 1 | async function Commit (_method, _connection) 2 | { 3 | const connectionStatus = { 4 | beginTransaction: { 5 | success: false, 6 | error: false, 7 | }, 8 | start: { 9 | success: false, 10 | error: false, 11 | }, 12 | end: { 13 | success: false, 14 | error: false, 15 | }, 16 | commit: { 17 | success: false, 18 | error: false, 19 | }, 20 | rollback: { 21 | success: false, 22 | error: false, 23 | }, 24 | }; 25 | 26 | if (_method === "client") 27 | { 28 | const commit = await _connection 29 | .query("COMMIT;") 30 | .then( () => 31 | { 32 | connectionStatus.commit.success = true; 33 | 34 | return connectionStatus.commit; 35 | }) 36 | .catch( (err) => 37 | { 38 | connectionStatus.commit.error = err.message; 39 | 40 | return connectionStatus.commit; 41 | }); 42 | 43 | return commit; 44 | } 45 | else 46 | { 47 | const commit = _connection 48 | .query("COMMIT;") 49 | .then( () => 50 | { 51 | connectionStatus.commit.success = true; 52 | 53 | return connectionStatus.commit; 54 | }) 55 | .catch( (err) => 56 | { 57 | connectionStatus.commit.error = err.message; 58 | 59 | return connectionStatus.commit; 60 | }) 61 | .finally( () => 62 | { 63 | try 64 | { 65 | _connection.release(); 66 | 67 | return connectionStatus.commit; 68 | } 69 | catch 70 | { 71 | return connectionStatus.commit; 72 | } 73 | }); 74 | 75 | return commit; 76 | } 77 | } 78 | 79 | module.exports = Commit; 80 | -------------------------------------------------------------------------------- /methods/rollback.js: -------------------------------------------------------------------------------- 1 | async function Rollback (_method, _connection) 2 | { 3 | const connectionStatus = { 4 | beginTransaction: { 5 | success: false, 6 | error: false, 7 | }, 8 | start: { 9 | success: false, 10 | error: false, 11 | }, 12 | end: { 13 | success: false, 14 | error: false, 15 | }, 16 | commit: { 17 | success: false, 18 | error: false, 19 | }, 20 | rollback: { 21 | success: false, 22 | error: false, 23 | }, 24 | }; 25 | 26 | if (_method === "client") 27 | { 28 | const rollback = _connection 29 | .query("ROLLBACK;") 30 | .then( () => 31 | { 32 | connectionStatus.rollback.success = true; 33 | 34 | return connectionStatus.rollback; 35 | }) 36 | .catch( (err) => 37 | { 38 | connectionStatus.rollback.error = err.message; 39 | 40 | return connectionStatus.rollback; 41 | }); 42 | 43 | return rollback; 44 | } 45 | else 46 | { 47 | const rollback = _connection 48 | .query("ROLLBACK;") 49 | .then( () => 50 | { 51 | connectionStatus.rollback.success = true; 52 | 53 | return connectionStatus.rollback; 54 | }) 55 | .catch( (err) => 56 | { 57 | connectionStatus.rollback.error = err.message; 58 | 59 | return connectionStatus.rollback; 60 | }) 61 | .finally( () => 62 | { 63 | try 64 | { 65 | _connection.release(); 66 | 67 | return connectionStatus.rollback; 68 | } 69 | catch 70 | { 71 | return connectionStatus.rollback; 72 | } 73 | }); 74 | 75 | return rollback; 76 | } 77 | } 78 | 79 | module.exports = Rollback; 80 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Query-Tool 2 | The QueryTool is a library that allows easier and faster connections with Postgres databases. Whit it, you can make insertions, selections, updates and deletions in the database in a simple and effective way. 3 | 4 | [Click here](https://github.com/anapolima/Query-Tool/wiki) to check our documentation. 5 | 6 | ## Installing 7 | You can install this package by running 8 | ``` 9 | $ npm i query-tool 10 | ``` 11 | 12 | ## What is new on version 2.0.0 13 | The 2.0.0 version was released to prevent possible compatibility issues. 14 | 15 | In version 2.0.0, all methods that used to be in PascalCase are now in camelCase. Since _delete_ is a JavaScript reserved word, the old _Delete_ method is now `deleteFrom`. Also, when using the `update` method, the `type` you must supply, which used to be _string_ or _integer_, is now _string_ or _number_. The _EndClient_ and _EndPool_ methods are now one, called `endConnection`. 16 | 17 | The documentation is up to date, you can check it. 18 | ## Support 19 | QueryTool is free software. If you encounter a bug with the library please open an issue on the GitHub repo. If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear and I will do my best to make it better! 20 | 21 | When you open an issue please provide: 22 | 23 | * version of Node 24 | * smallest possible snippet of code to reproduce the problem 25 | 26 | ## License 27 | MIT License 28 | 29 | Copyright (c) 2021 Ana Paula Oliveira de Lima 30 | 31 | Permission is hereby granted, free of charge, to any person obtaining a copy 32 | of this software and associated documentation files (the "Software"), to deal 33 | in the Software without restriction, including without limitation the rights 34 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 35 | copies of the Software, and to permit persons to whom the Software is 36 | furnished to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in all 39 | copies or substantial portions of the Software. 40 | 41 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 46 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 47 | SOFTWARE. 48 | -------------------------------------------------------------------------------- /functions/start-connection.js: -------------------------------------------------------------------------------- 1 | const pg = require("pg"); 2 | 3 | async function StartConnection (_method, _config) 4 | { 5 | const connectionStatus = { 6 | beginTransaction: { 7 | success: false, 8 | error: false, 9 | }, 10 | start: { 11 | success: false, 12 | error: false, 13 | }, 14 | end: { 15 | success: false, 16 | error: false, 17 | }, 18 | commit: { 19 | success: false, 20 | error: false, 21 | }, 22 | rollback: { 23 | success: false, 24 | error: false, 25 | }, 26 | }; 27 | 28 | let connection = undefined; 29 | let pool = undefined; 30 | let client = undefined; 31 | 32 | if (_method === "client") 33 | { 34 | const clientConnection = new pg.Client({ 35 | ..._config 36 | }); 37 | 38 | const connecting = clientConnection 39 | .connect() 40 | .then( () => 41 | { 42 | connectionStatus.start.success = true; 43 | client = clientConnection; 44 | 45 | return connectionStatus.start; 46 | }) 47 | .catch( (err) => 48 | { 49 | connectionStatus.start.error = err.message; 50 | 51 | return connectionStatus.start; 52 | }); 53 | 54 | return { 55 | connectionStatus: await connecting, 56 | connectionStarted: client 57 | }; 58 | } 59 | else if (_method === "pool") 60 | { 61 | const clientConnection = new pg.Pool({ 62 | ..._config 63 | }); 64 | 65 | const connecting = clientConnection 66 | .connect() 67 | .then( (connectionPool) => 68 | { 69 | connection = connectionPool; 70 | pool = clientConnection; 71 | connectionStatus.start.success = true; 72 | 73 | return connectionStatus.start; 74 | }) 75 | .catch( (err) => 76 | { 77 | connectionStatus.start.error = err.message; 78 | 79 | return connectionStatus.start; 80 | }); 81 | 82 | return { 83 | connectionStatus: await connecting, 84 | connectionStarted: pool, 85 | connection 86 | }; 87 | } 88 | else 89 | { 90 | throw new Error("Invalid connection method. Choose between Client or Pool"); 91 | } 92 | } 93 | 94 | module.exports = StartConnection; 95 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | const Config = require("../functions/config.js"); 2 | const StartConnection = require("../functions/start-connection.js"); 3 | 4 | const Select = require("../methods/select.js"); 5 | const Insert = require("../methods/insert.js"); 6 | const Update = require("../methods/update.js"); 7 | const Delete = require("../methods/delete.js"); 8 | 9 | const BeginTransaction = require("../methods/begin-transaction.js"); 10 | const Commit = require("../methods/commit.js"); 11 | const Rollback = require("../methods/rollback.js"); 12 | 13 | const EndConnection = require("../functions/end-connection.js"); 14 | 15 | function QueryTool () 16 | { 17 | let method = undefined; 18 | let configInfo = undefined; 19 | let connection = undefined; 20 | let connectionStarted = undefined; 21 | let connectionStatus = undefined; 22 | 23 | function config (_config) 24 | { 25 | const settings = Config(_config); 26 | 27 | method = settings.method; 28 | configInfo = settings.config; 29 | } 30 | 31 | async function startConnection () 32 | { 33 | const starting = await StartConnection(method, configInfo); 34 | 35 | connectionStatus = { 36 | ...starting.connectionStatus 37 | }; 38 | 39 | connectionStarted = starting.connectionStarted; 40 | connection = starting.connection; 41 | 42 | return connectionStatus; 43 | } 44 | 45 | async function select (_selectParam) 46 | { 47 | if (method === "client") 48 | { 49 | const result = await Select(_selectParam, method, connectionStarted); 50 | 51 | return result; 52 | } 53 | else 54 | { 55 | const result = await Select(_selectParam, method, connection); 56 | 57 | return result; 58 | } 59 | } 60 | 61 | async function insert (_insertParam) 62 | { 63 | if (method === "client") 64 | { 65 | const result = await Insert(_insertParam, method, connectionStarted); 66 | 67 | return result; 68 | } 69 | else 70 | { 71 | const result = await Insert(_insertParam, method, connection); 72 | 73 | return result; 74 | } 75 | } 76 | 77 | async function update (_updateParam) 78 | { 79 | if (method === "client") 80 | { 81 | const result = await Update(_updateParam, method, connectionStarted); 82 | 83 | return result; 84 | } 85 | else 86 | { 87 | const result = await Update(_updateParam, method, connection); 88 | 89 | return result; 90 | } 91 | } 92 | 93 | async function deleteFrom (_deleteParam) 94 | { 95 | if (method === "client") 96 | { 97 | const result = await Delete(_deleteParam, method, connectionStarted); 98 | 99 | return result; 100 | } 101 | else 102 | { 103 | const result = await Delete(_deleteParam, method, connection); 104 | 105 | return result; 106 | } 107 | } 108 | 109 | async function beginTransaction () 110 | { 111 | if (method === "client") 112 | { 113 | const result = await BeginTransaction(method, connectionStarted); 114 | 115 | return result; 116 | } 117 | else 118 | { 119 | const result = await BeginTransaction(method, connection); 120 | 121 | return result; 122 | } 123 | } 124 | 125 | async function commit () 126 | { 127 | if (method === "client") 128 | { 129 | const result = await Commit(method, connectionStarted); 130 | 131 | return result; 132 | } 133 | else 134 | { 135 | const result = await Commit(method, connection); 136 | 137 | return result; 138 | } 139 | } 140 | 141 | async function rollback () 142 | { 143 | if (method === "client") 144 | { 145 | const result = await Rollback(method, connectionStarted); 146 | 147 | return result; 148 | } 149 | else 150 | { 151 | const result = await Rollback(method, connection); 152 | 153 | return result; 154 | } 155 | } 156 | 157 | async function endConnection () 158 | { 159 | const result = await EndConnection(connectionStarted); 160 | 161 | return result; 162 | } 163 | 164 | return { 165 | config, 166 | startConnection, 167 | select, 168 | insert, 169 | update, 170 | deleteFrom, 171 | beginTransaction, 172 | commit, 173 | rollback, 174 | endConnection, 175 | }; 176 | } 177 | 178 | module.exports = QueryTool; 179 | -------------------------------------------------------------------------------- /validators/validate-operators.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-param-reassign */ 2 | const ValidateLIKEpercent = require("./validate-like-percent"); 3 | 4 | function ValidateOperators (_object, _objectKeys, _logicalOperators, _arrayParams, _arrayValues, _paramNumber, _errorsObject, _join) 5 | { 6 | _objectKeys.forEach( (_column, _index) => 7 | { 8 | const regexOperator = /[=]$|>$|<$|between$|like$|ilike$|is$|in$/i; 9 | const regexCompoundOperator = /!=$|>=$|<=$|not between$|not like$|not ilike$|is not$|not in$/i; 10 | 11 | const operator = _object[_column].operator.toLowerCase(); 12 | const value = _object[_column].value; 13 | 14 | let isValidOperator = false; 15 | 16 | if ( (operator.length === 2 || operator.split(" ").length > 1) && operator !== "in" && operator !== "is") 17 | { 18 | isValidOperator = regexCompoundOperator.test(operator); 19 | } 20 | else 21 | { 22 | isValidOperator = regexOperator.test(operator); 23 | } 24 | 25 | if (isValidOperator) 26 | { 27 | if (operator === "like" || operator === "not like" || 28 | operator === "ilike" || operator === "not ilike") 29 | { 30 | const percent = _object[_column].percent; 31 | if (percent) 32 | { 33 | const validPercent = ValidateLIKEpercent(_object[_column], _paramNumber); 34 | 35 | if (validPercent) 36 | { 37 | if (_join) 38 | { 39 | _arrayParams.push( 40 | `${_join}.${_column} ${operator.toUpperCase()} ${validPercent} 41 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 42 | ); 43 | _paramNumber++; 44 | _arrayValues.push(value); 45 | } 46 | else 47 | { 48 | _arrayParams.push( 49 | `${_column} ${operator.toUpperCase()} ${validPercent} 50 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 51 | ); 52 | _paramNumber++; 53 | _arrayValues.push(value); 54 | } 55 | } 56 | else 57 | { 58 | _errorsObject.error.params = "Invalid value for 'percent'. You must choose between 'start', 'end', and 'both'"; 59 | } 60 | } 61 | else 62 | { 63 | if (_join) 64 | { 65 | _arrayParams.push( 66 | `${_join}.${_column} ${operator.toUpperCase()} $${_paramNumber} 67 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 68 | ); 69 | _paramNumber++; 70 | _arrayValues.push(value); 71 | } 72 | else 73 | { 74 | _arrayParams.push( 75 | `${_column} ${operator.toUpperCase()} $${_paramNumber} 76 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 77 | ); 78 | _paramNumber++; 79 | _arrayValues.push(value); 80 | } 81 | } 82 | } 83 | else if (operator === "between" || operator === "not between") 84 | { 85 | if (_join) 86 | { 87 | _arrayParams.push( 88 | `${_join}.${_column} ${operator.toUpperCase()} $${_paramNumber} AND $${_paramNumber + 1} 89 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 90 | ); 91 | _paramNumber += 2; 92 | _arrayValues.push(value[0], value[1]); 93 | } 94 | else 95 | { 96 | _arrayParams.push( 97 | `${_column} ${operator.toUpperCase()} $${_paramNumber} AND $${_paramNumber + 1} 98 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 99 | ); 100 | _paramNumber += 2; 101 | _arrayValues.push(value[0], value[1]); 102 | } 103 | } 104 | else if (operator === "is" || operator === "is not") 105 | { 106 | if (_join) 107 | { 108 | _arrayParams.push( 109 | `${_join}.${_column} ${operator.toUpperCase()} ${value} 110 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 111 | ); 112 | } 113 | else 114 | { 115 | _arrayParams.push( 116 | `${_column} ${operator.toUpperCase()} ${value} 117 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 118 | ); 119 | } 120 | } 121 | else if (operator === "in" || operator === "not in") 122 | { 123 | let inValues = undefined; 124 | 125 | value.forEach( (_inValue, _inIndex) => 126 | { 127 | if (_inIndex === 0) 128 | { 129 | inValues = `($${_paramNumber}`; 130 | _paramNumber++; 131 | _arrayValues.push(value[_inIndex]); 132 | } 133 | else 134 | { 135 | inValues += `, $${_paramNumber})`; 136 | _paramNumber++; 137 | _arrayValues.push(value[_inIndex]); 138 | } 139 | 140 | if (_inIndex === value.length - 1) 141 | { 142 | inValues += ")"; 143 | } 144 | }); 145 | 146 | if (_join) 147 | { 148 | _arrayParams.push( 149 | `${_join}.${_column} ${operator.toUpperCase()} 150 | ${inValues} 151 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 152 | ); 153 | } 154 | else 155 | { 156 | _arrayParams.push( 157 | `${_column} ${operator.toUpperCase()} 158 | ${inValues} 159 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 160 | ); 161 | } 162 | } 163 | else 164 | { 165 | if (isNaN(value)) 166 | { 167 | if (_join) 168 | { 169 | _arrayParams.push( 170 | `${_join}.${_column} ${operator.toUpperCase()} ${value} 171 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 172 | ); 173 | } 174 | else 175 | { 176 | _arrayParams.push( 177 | `${_column} ${operator.toUpperCase()} ${value} 178 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 179 | ); 180 | } 181 | } 182 | else 183 | { 184 | if (_join) 185 | { 186 | _arrayParams.push( 187 | `${_join}.${_column} ${operator.toUpperCase()} $${_paramNumber} 188 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 189 | ); 190 | _paramNumber++; 191 | _arrayValues.push(value); 192 | } 193 | else 194 | { 195 | _arrayParams.push( 196 | `${_column} ${operator.toUpperCase()} $${_paramNumber} 197 | ${ _logicalOperators[_index] ? _logicalOperators[_index].toUpperCase() : "" }` 198 | ); 199 | _paramNumber++; 200 | _arrayValues.push(value); 201 | } 202 | } 203 | } 204 | } 205 | else 206 | { 207 | _errorsObject.error.params = "Invalid operator on WHERE params"; 208 | } 209 | }); 210 | 211 | if (_errorsObject.error.params) 212 | { 213 | return false; 214 | } 215 | else 216 | { 217 | return _paramNumber; 218 | } 219 | } 220 | 221 | module.exports = ValidateOperators; 222 | -------------------------------------------------------------------------------- /methods/select.js: -------------------------------------------------------------------------------- 1 | const ValidateParameters = require('../validators/validate-parameters.js'); 2 | const ValidateOperators = require('../validators/validate-operators.js'); 3 | 4 | function Select (_selectParam, _method, _connection) 5 | { 6 | let selectTable = undefined; 7 | let selectColumns = undefined; 8 | let selectJoin = undefined; 9 | let selectWhere = undefined; 10 | let selectGroupBy = undefined; 11 | let selectOrderBy = undefined; 12 | let selectHaving = undefined; 13 | 14 | const validParameters = ValidateParameters({ ..._selectParam }); 15 | 16 | if (validParameters) 17 | { 18 | const selectResult = { 19 | error: { 20 | transaction: false, 21 | params: false, 22 | }, 23 | data: false, 24 | }; 25 | 26 | const table = _selectParam.table; 27 | const columns = _selectParam.columns; 28 | const where = _selectParam.where; 29 | const logicalOperators = _selectParam.logicalOperators || []; 30 | const join = _selectParam.join; 31 | const groupBy = _selectParam.groupBy; 32 | const orderBy = _selectParam.orderBy; 33 | const having = _selectParam.having; 34 | 35 | if (typeof (table) !== "string") 36 | { 37 | throw new Error ("The 'table' must be a string"); 38 | } 39 | 40 | if ( !( Array.isArray(columns) )) 41 | { 42 | throw new Error ("The 'columns' must be an array"); 43 | } 44 | 45 | if ( where && !( where instanceof Object && !(where instanceof Array) )) 46 | { 47 | throw new Error ("The 'where' must be a JSON, each key must be the name of a column and also a JSON with the keys 'operator' and 'value'"); 48 | } 49 | 50 | if ( logicalOperators && !( Array.isArray(logicalOperators) )) 51 | { 52 | throw new Error ("The 'logical operators' must be an array"); 53 | } 54 | 55 | if ( join && !( join instanceof Object && !(join instanceof Array) )) 56 | { 57 | throw new Error ("The 'join' must be a JSON, each key must be the name of the table to join and also a JSON with the keys 'join', 'on', and 'logicalOperators'"); 58 | } 59 | 60 | if ( groupBy && !( Array.isArray(groupBy) )) 61 | { 62 | throw new Error ("The 'group by' must be an array"); 63 | } 64 | 65 | if ( orderBy && !( Array.isArray(orderBy) )) 66 | { 67 | throw new Error ("The 'order by' must be an array"); 68 | } 69 | 70 | if ( having && !( having instanceof Object && !(having instanceof Array) )) 71 | { 72 | throw new Error ("The 'having' must be a JSON, each key must be the name of a column and also a JSON with the keys 'operator' and 'value'"); 73 | } 74 | 75 | selectColumns = columns.join(", "); 76 | selectTable = table; 77 | 78 | const selectParams = []; 79 | const values = []; 80 | let param = 1; 81 | 82 | if (join) 83 | { 84 | const tables = Object.keys (join); 85 | const regexJoin = /join$/i; 86 | const regexCompoundJoin = /inner join$|left join$|right join$|full outer join$/i; 87 | const joinParams = []; 88 | 89 | tables.forEach( (_table) => 90 | { 91 | const tableJoin = join[_table].join; 92 | let isValidJoin = undefined; 93 | 94 | if (tableJoin.split(" ").length > 1) 95 | { 96 | isValidJoin = regexCompoundJoin.test(tableJoin); 97 | } 98 | else 99 | { 100 | isValidJoin = regexJoin.test(tableJoin); 101 | } 102 | 103 | if (isValidJoin) 104 | { 105 | const joinOn = { ...join[_table].on }; 106 | const joinOnColumns = Object.keys(joinOn); 107 | const joinLogicalOperators = join[_table].logicalOperators ? [ ...join[_table].logicalOperators ] : []; 108 | 109 | joinParams.push(` 110 | ${tableJoin.toUpperCase()} ${_table} ON 111 | `); 112 | 113 | const validOparators = ValidateOperators(joinOn, joinOnColumns, joinLogicalOperators, joinParams, values, param, selectResult, _table); 114 | if (validOparators) 115 | { 116 | param = validOparators; 117 | } 118 | } 119 | else 120 | { 121 | selectResult.error.params = "Invalid join type on JOIN params"; 122 | 123 | return selectResult; 124 | } 125 | }); 126 | 127 | if (joinParams.length > 0) 128 | { 129 | selectJoin = joinParams.join(" "); 130 | } 131 | else 132 | { 133 | return selectResult; 134 | } 135 | } 136 | 137 | if (where) 138 | { 139 | const whereColumns = Object.keys(where); 140 | 141 | if ( !logicalOperators) 142 | { 143 | throw new Error ("When using the WHERE clause, you must provide the logical operators"); 144 | } 145 | 146 | const validOperators = ValidateOperators(where, whereColumns, logicalOperators, selectParams, values, param, selectResult); 147 | 148 | if (validOperators) 149 | { 150 | selectWhere = selectParams.join (" "); 151 | param = validOperators; 152 | } 153 | else 154 | { 155 | return selectResult; 156 | } 157 | } 158 | 159 | if (groupBy) 160 | { 161 | selectGroupBy = groupBy.join(", "); 162 | } 163 | 164 | if (orderBy) 165 | { 166 | selectOrderBy = orderBy.join(", "); 167 | } 168 | 169 | if (having) 170 | { 171 | const havingColumns = Object.keys(having.columns); 172 | const havingParams = []; 173 | const havingLogicalOperators = having.logicalOperators ? [ ...having.logicalOperators ] : []; 174 | 175 | const validOperators = ValidateOperators(having.columns, havingColumns, havingLogicalOperators, havingParams, values, param, selectResult); 176 | 177 | if (validOperators) 178 | { 179 | selectHaving = havingParams.join (" "); 180 | param = validOperators; 181 | } 182 | else 183 | { 184 | return selectResult; 185 | } 186 | } 187 | 188 | if (_method === "client") 189 | { 190 | const result = _connection 191 | .query(` 192 | SELECT ${selectColumns} FROM ${selectTable} 193 | ${ join ? selectJoin : ""} 194 | ${ where ? `WHERE ${selectWhere} ` : ""} 195 | ${ groupBy ? `GROUP BY ${selectGroupBy}` : ""} 196 | ${ having ? `HAVING ${selectHaving}` : ""} 197 | ${ orderBy ? `ORDER BY ${selectOrderBy}` : ""} 198 | `, values) 199 | .then( (result) => 200 | { 201 | selectResult.data = result.rows; 202 | 203 | return selectResult; 204 | }) 205 | .catch( (err) => 206 | { 207 | selectResult.error.transaction = err.message; 208 | 209 | return selectResult; 210 | }) 211 | .finally( () => 212 | { 213 | selectTable = undefined; 214 | selectColumns = undefined; 215 | selectJoin = undefined; 216 | selectWhere = undefined; 217 | selectGroupBy = undefined; 218 | selectOrderBy = undefined; 219 | selectHaving = undefined; 220 | }); 221 | 222 | return result; 223 | } 224 | else 225 | { 226 | const result = _connection 227 | .query(` 228 | SELECT ${selectColumns} FROM ${selectTable} 229 | ${ join ? selectJoin : ""} 230 | ${ where ? `WHERE ${selectWhere} ` : ""} 231 | ${ groupBy ? `GROUP BY ${selectGroupBy}` : ""} 232 | ${ having ? `HAVING ${selectHaving}` : ""} 233 | ${ orderBy ? `ORDER BY ${selectOrderBy}` : ""} 234 | `, values) 235 | .then( (result) => 236 | { 237 | selectResult.data = result.rows; 238 | 239 | return selectResult; 240 | }) 241 | .catch( (err) => 242 | { 243 | selectResult.error.transaction = err.message; 244 | 245 | return selectResult; 246 | }) 247 | .finally( () => 248 | { 249 | try 250 | { 251 | _connection.release(); 252 | selectTable = undefined; 253 | selectColumns = undefined; 254 | selectJoin = undefined; 255 | selectWhere = undefined; 256 | selectGroupBy = undefined; 257 | selectOrderBy = undefined; 258 | selectHaving = undefined; 259 | } 260 | catch 261 | { 262 | selectTable = undefined; 263 | selectColumns = undefined; 264 | selectJoin = undefined; 265 | selectWhere = undefined; 266 | selectGroupBy = undefined; 267 | selectOrderBy = undefined; 268 | selectHaving = undefined; 269 | } 270 | }); 271 | 272 | return result; 273 | } 274 | } 275 | } 276 | 277 | module.exports = Select; 278 | -------------------------------------------------------------------------------- /methods/insert.js: -------------------------------------------------------------------------------- 1 | const ValidateParameters = require('../validators/validate-parameters.js'); 2 | 3 | async function Insert (_insertParam, _method, _connection) 4 | { 5 | const validParameters = ValidateParameters({ ..._insertParam }); 6 | 7 | let insertTable = undefined; 8 | let insertColumns = undefined; 9 | let insertReturning = undefined; 10 | let insertParams = undefined; 11 | 12 | if (validParameters) 13 | { 14 | const insertResult = { 15 | error: { 16 | transaction: false, 17 | commit: false, 18 | rollback: false, 19 | params: false, 20 | }, 21 | success: { 22 | commit: false, 23 | rollback: false, 24 | }, 25 | data: false, 26 | }; 27 | const table = _insertParam.table; 28 | const columns = _insertParam.columns; 29 | const returning = _insertParam.returning; 30 | const beginTransaction = _insertParam.beginTransaction; 31 | 32 | 33 | if ( typeof (table) !== "string" ) 34 | { 35 | throw new Error ("The table name must be a string"); 36 | } 37 | 38 | if ( !( columns instanceof Object && !(columns instanceof Array) )) 39 | { 40 | throw new Error ("Columns need to be a JSON. Each key must be the name of a column in the databese and its value must be the value to be inserted"); 41 | } 42 | 43 | if ( returning && !( Array.isArray(returning) ) ) 44 | { 45 | throw new Error ("The returning must be an array containing the name of the columns to be returned"); 46 | } 47 | 48 | if (typeof (beginTransaction) !== "boolean") 49 | { 50 | throw new Error ("The begin transaction must be a boolean"); 51 | } 52 | 53 | if (returning) 54 | { 55 | insertReturning = returning.join(", "); 56 | } 57 | 58 | insertTable = table; 59 | const columnsNames = Object.keys(columns); 60 | insertColumns = columnsNames; 61 | 62 | const params = []; 63 | const values = []; 64 | 65 | columnsNames.forEach( (_column, _index) => 66 | { 67 | params.push(`$${_index + 1}`); 68 | values.push(columns[_column]); 69 | }); 70 | 71 | insertParams = params.join(", "); 72 | 73 | if (_method === "client") 74 | { 75 | if (beginTransaction) 76 | { 77 | const result = _connection 78 | .query("BEGIN;") 79 | .then( () => _connection.query(` 80 | INSERT INTO ${insertTable} (${insertColumns}) 81 | VALUES (${insertParams}) 82 | ${insertReturning ? `RETURNING ${insertReturning}` : "" } 83 | `, values)) 84 | .then(async (result) => 85 | { 86 | insertResult.data = result.rows; 87 | 88 | await _connection 89 | .query("COMMIT;") 90 | .then( () => 91 | { 92 | insertResult.success.commit = true; 93 | }) 94 | .catch( (err) => 95 | { 96 | insertResult.error.commit = err.message; 97 | }); 98 | 99 | return insertResult; 100 | }) 101 | .catch(async (err) => 102 | { 103 | insertResult.error.transaction = err.message; 104 | 105 | await _connection 106 | .query("ROLLBACK;") 107 | .then( () => 108 | { 109 | insertResult.success.rollback = true; 110 | }) 111 | .catch( (err) => 112 | { 113 | insertResult.error.rollback = err.message; 114 | }); 115 | 116 | return insertResult; 117 | }) 118 | .finally( () => 119 | { 120 | insertTable = undefined; 121 | insertColumns = undefined; 122 | insertReturning = undefined; 123 | insertParams = undefined; 124 | }); 125 | 126 | return result; 127 | } 128 | else 129 | { 130 | const result = _connection 131 | .query(` 132 | INSERT INTO ${insertTable} (${insertColumns}) 133 | VALUES (${insertParams}) 134 | ${insertReturning ? `RETURNING ${insertReturning}` : "" } 135 | `, values) 136 | .then( (result) => 137 | { 138 | insertResult.data = result.rows; 139 | 140 | return insertResult; 141 | }) 142 | .catch( (err) => 143 | { 144 | insertResult.error.transaction = err.message; 145 | 146 | return insertResult; 147 | }) 148 | .finally( () => 149 | { 150 | insertTable = undefined; 151 | insertColumns = undefined; 152 | insertReturning = undefined; 153 | insertParams = undefined; 154 | }); 155 | 156 | return result; 157 | } 158 | } 159 | else 160 | { 161 | if (beginTransaction) 162 | { 163 | const result = _connection 164 | .query("BEGIN;") 165 | .then( () => _connection.query(` 166 | INSERT INTO ${insertTable} (${insertColumns}) 167 | VALUES (${insertParams}) 168 | ${insertReturning ? `RETURNING ${insertReturning}` : "" } 169 | `, values)) 170 | .then(async (result) => 171 | { 172 | insertResult.data = result.rows; 173 | 174 | await _connection 175 | .query("COMMIT;") 176 | .then( () => 177 | { 178 | insertResult.success.commit = true; 179 | }) 180 | .catch( (err) => 181 | { 182 | insertResult.error.commit = err.message; 183 | }); 184 | 185 | return insertResult; 186 | }) 187 | .catch(async (err) => 188 | { 189 | insertResult.error.transaction = err.message; 190 | 191 | await _connection 192 | .query("ROLLBACK;") 193 | .then( () => 194 | { 195 | insertResult.success.rollback = true; 196 | }) 197 | .catch( (err) => 198 | { 199 | insertResult.error.rollback = err.message; 200 | }); 201 | 202 | return insertResult; 203 | }) 204 | .finally( () => 205 | { 206 | try 207 | { 208 | _connection.release(); 209 | insertTable = undefined; 210 | insertColumns = undefined; 211 | insertReturning = undefined; 212 | insertParams = undefined; 213 | } 214 | catch 215 | { 216 | insertTable = undefined; 217 | insertColumns = undefined; 218 | insertReturning = undefined; 219 | insertParams = undefined; 220 | } 221 | }); 222 | 223 | return result; 224 | } 225 | else 226 | { 227 | const result = _connection 228 | .query(` 229 | INSERT INTO ${insertTable} (${insertColumns}) 230 | VALUES (${insertParams}) 231 | ${insertReturning ? `RETURNING ${insertReturning}` : "" } 232 | `, values) 233 | .then( (result) => 234 | { 235 | insertResult.data = result.rows; 236 | 237 | return insertResult; 238 | }) 239 | .catch( (err) => 240 | { 241 | insertResult.error.transaction = err.message; 242 | 243 | return insertResult; 244 | }) 245 | .finally( () => 246 | { 247 | try 248 | { 249 | _connection.release(); 250 | insertTable = undefined; 251 | insertColumns = undefined; 252 | insertReturning = undefined; 253 | insertParams = undefined; 254 | } 255 | catch 256 | { 257 | insertTable = undefined; 258 | insertColumns = undefined; 259 | insertReturning = undefined; 260 | insertParams = undefined; 261 | } 262 | }); 263 | 264 | return result; 265 | } 266 | } 267 | } 268 | } 269 | 270 | module.exports = Insert; 271 | -------------------------------------------------------------------------------- /methods/delete.js: -------------------------------------------------------------------------------- 1 | const ValidateParameters = require("../validators/validate-parameters.js"); 2 | const ValidateOperators = require("../validators/validate-operators.js"); 3 | 4 | async function Delete (_deleteParam, _method, _connection) 5 | { 6 | const validParameters = ValidateParameters({ ..._deleteParam }); 7 | 8 | let deleteTable = undefined; 9 | let deleteUsing = undefined; 10 | let deleteWhere = undefined; 11 | let deleteReturning = undefined; 12 | 13 | if (validParameters) 14 | { 15 | const deleteResult = { 16 | error: { 17 | transaction: false, 18 | commit: false, 19 | rollback: false, 20 | params: false, 21 | }, 22 | success: { 23 | commit: false, 24 | rollback: false, 25 | }, 26 | data: false, 27 | }; 28 | 29 | const beginTransaction = _deleteParam.beginTransaction; 30 | const table = _deleteParam.table; 31 | const using = _deleteParam.using; 32 | const where = _deleteParam.where; 33 | const logicalOperators = _deleteParam.logicalOperators || []; 34 | const returning = _deleteParam.returning; 35 | 36 | if (typeof (table) !== "string") 37 | { 38 | throw new Error ("The 'table' must be a string"); 39 | } 40 | 41 | if ( using && typeof (using) !== "string") 42 | { 43 | throw new Error ("The 'using' must be a string"); 44 | } 45 | 46 | if ( where && !( where instanceof Object && !(where instanceof Array) )) 47 | { 48 | throw new Error ("The 'where' must be a JSON, each key must be the name of a column and also a JSON with the keys 'operator' and 'value'"); 49 | } 50 | 51 | if ( logicalOperators && !( Array.isArray(logicalOperators) )) 52 | { 53 | throw new Error ("The 'logical operators' must be an array"); 54 | } 55 | 56 | if ( returning && !( Array.isArray(returning) ) ) 57 | { 58 | throw new Error ("The returning must be an array containing the name of the columns to be returned"); 59 | } 60 | 61 | if (typeof (beginTransaction) !== "boolean") 62 | { 63 | throw new Error ("The begin transaction must be a boolean"); 64 | } 65 | 66 | deleteTable = table; 67 | const values = []; 68 | let param = 1; 69 | 70 | if (using) 71 | { 72 | deleteUsing = using; 73 | } 74 | 75 | if (where) 76 | { 77 | const deleteWhereArray = []; 78 | const whereColumns = Object.keys(where); 79 | 80 | if ( !logicalOperators) 81 | { 82 | throw new Error ("When using the WHERE clause, you must provide the logical operators"); 83 | } 84 | 85 | const validOperators = ValidateOperators(where, whereColumns, logicalOperators, deleteWhereArray, values, param, deleteResult); 86 | 87 | if (validOperators) 88 | { 89 | deleteWhere = deleteWhereArray.join (" "); 90 | param = validOperators; 91 | } 92 | else 93 | { 94 | return deleteResult; 95 | } 96 | 97 | } 98 | 99 | if (returning) 100 | { 101 | deleteReturning = returning.join(", "); 102 | } 103 | 104 | if (_method === "client") 105 | { 106 | if (beginTransaction) 107 | { 108 | const result = _connection 109 | .query("BEGIN;") 110 | .then( () => _connection.query(` 111 | DELETE FROM ${deleteTable} 112 | ${deleteUsing ? `USING ${deleteUsing}` : ""} 113 | ${deleteWhere ? `WHERE ${deleteWhere}` : ""} 114 | ${deleteReturning ? `RETURNING ${deleteReturning}` : ""} 115 | `, values)) 116 | .then(async (result) => 117 | { 118 | deleteResult.data = result.rows; 119 | 120 | await _connection 121 | .query("COMMIT;") 122 | .then( () => 123 | { 124 | deleteResult.success.commit = true; 125 | }) 126 | .catch( (err) => 127 | { 128 | deleteResult.error.commit = err.message; 129 | }); 130 | 131 | return deleteResult; 132 | }) 133 | .catch(async (err) => 134 | { 135 | deleteResult.error.transaction = err.message; 136 | 137 | await _connection 138 | .query("ROLLBACK;") 139 | .then( () => 140 | { 141 | deleteResult.success.rollback = true; 142 | }) 143 | .catch( (err) => 144 | { 145 | deleteResult.error.rollback = err.message; 146 | }); 147 | 148 | return deleteResult; 149 | }) 150 | .finally( () => 151 | { 152 | deleteTable = undefined; 153 | deleteUsing = undefined; 154 | deleteWhere = undefined; 155 | deleteReturning = undefined; 156 | }); 157 | 158 | return result; 159 | } 160 | else 161 | { 162 | const result = _connection 163 | .query(` 164 | DELETE FROM ${deleteTable} 165 | ${deleteUsing ? `USING ${deleteUsing}` : ""} 166 | ${deleteWhere ? `WHERE ${deleteWhere}` : ""} 167 | ${deleteReturning ? `RETURNING ${deleteReturning}` : ""} 168 | `, values) 169 | .then( (result) => 170 | { 171 | deleteResult.data = result.rows; 172 | 173 | return deleteResult; 174 | }) 175 | .catch( (err) => 176 | { 177 | deleteResult.error.transaction = err.message; 178 | 179 | return deleteResult; 180 | }) 181 | .finally( () => 182 | { 183 | deleteTable = undefined; 184 | deleteUsing = undefined; 185 | deleteWhere = undefined; 186 | deleteReturning = undefined; 187 | }); 188 | 189 | return result; 190 | } 191 | } 192 | else 193 | { 194 | if (beginTransaction) 195 | { 196 | const result = _connection 197 | .query("BEGIN;") 198 | .then( () => _connection.query(` 199 | DELETE FROM ${deleteTable} 200 | ${deleteUsing ? `USING ${deleteUsing}` : ""} 201 | ${deleteWhere ? `WHERE ${deleteWhere}` : ""} 202 | ${deleteReturning ? `RETURNING ${deleteReturning}` : ""} 203 | `, values)) 204 | .then(async (result) => 205 | { 206 | deleteResult.data = result.rows; 207 | 208 | await _connection 209 | .query("COMMIT;") 210 | .then( () => 211 | { 212 | deleteResult.success.commit = true; 213 | }) 214 | .catch( (err) => 215 | { 216 | deleteResult.error.commit = err.message; 217 | }); 218 | 219 | return deleteResult; 220 | }) 221 | .catch(async (err) => 222 | { 223 | deleteResult.error.transaction = err.message; 224 | 225 | await _connection 226 | .query("ROLLBACK;") 227 | .then( () => 228 | { 229 | deleteResult.success.rollback = true; 230 | }) 231 | .catch( (err) => 232 | { 233 | deleteResult.error.rollback = err.message; 234 | }); 235 | 236 | return deleteResult; 237 | }) 238 | .finally( () => 239 | { 240 | try 241 | { 242 | _connection.release(); 243 | deleteTable = undefined; 244 | deleteUsing = undefined; 245 | deleteWhere = undefined; 246 | deleteReturning = undefined; 247 | } 248 | catch 249 | { 250 | deleteTable = undefined; 251 | deleteUsing = undefined; 252 | deleteWhere = undefined; 253 | deleteReturning = undefined; 254 | } 255 | }); 256 | 257 | return result; 258 | } 259 | else 260 | { 261 | const result = _connection 262 | .query(` 263 | DELETE FROM ${deleteTable} 264 | ${deleteUsing ? `USING ${deleteUsing}` : ""} 265 | ${deleteWhere ? `WHERE ${deleteWhere}` : ""} 266 | ${deleteReturning ? `RETURNING ${deleteReturning}` : ""} 267 | `, values) 268 | .then( (result) => 269 | { 270 | deleteResult.data = result.rows; 271 | 272 | return deleteResult; 273 | }) 274 | .catch( (err) => 275 | { 276 | deleteResult.error.transaction = err.message; 277 | 278 | return deleteResult; 279 | }) 280 | .finally( () => 281 | { 282 | try 283 | { 284 | _connection.release(); 285 | deleteTable = undefined; 286 | deleteUsing = undefined; 287 | deleteWhere = undefined; 288 | deleteReturning = undefined; 289 | } 290 | catch 291 | { 292 | deleteTable = undefined; 293 | deleteUsing = undefined; 294 | deleteWhere = undefined; 295 | deleteReturning = undefined; 296 | } 297 | }); 298 | 299 | return result; 300 | } 301 | } 302 | 303 | } 304 | } 305 | 306 | module.exports = Delete; 307 | -------------------------------------------------------------------------------- /methods/update.js: -------------------------------------------------------------------------------- 1 | const ValidateParameters = require("../validators/validate-parameters.js"); 2 | const ValidateOperators = require("../validators/validate-operators.js"); 3 | 4 | async function Update (_updateParam, _method, _connection) 5 | { 6 | const validParameters = ValidateParameters({ ..._updateParam }); 7 | 8 | let updateTable = undefined; 9 | let updateParams = undefined; 10 | let updateWhere = undefined; 11 | let updateReturning = undefined; 12 | 13 | if (validParameters) 14 | { 15 | const updateResult = { 16 | error: { 17 | transaction: false, 18 | commit: false, 19 | rollback: false, 20 | params: false, 21 | }, 22 | success: { 23 | commit: false, 24 | rollback: false, 25 | }, 26 | data: false, 27 | }; 28 | 29 | const beginTransaction = _updateParam.beginTransaction; 30 | const table = _updateParam.table; 31 | const columns = _updateParam.columns; 32 | const where = _updateParam.where; 33 | const logicalOperators = _updateParam.logicalOperators || []; 34 | const returning = _updateParam.returning; 35 | 36 | if (typeof (table) !== "string") 37 | { 38 | throw new Error ("The 'table' must be a string"); 39 | } 40 | 41 | if ( !( columns instanceof Object && !(columns instanceof Array) )) 42 | { 43 | throw new Error ("Columns need to be a JSON. Each key must be the name of a column in the databese and its value must be the value to be inserted"); 44 | } 45 | 46 | if ( where && !( where instanceof Object && !(where instanceof Array) )) 47 | { 48 | throw new Error ("The 'where' must be a JSON, each key must be the name of a column and also a JSON with the keys 'operator' and 'value'"); 49 | } 50 | 51 | if ( logicalOperators && !( Array.isArray(logicalOperators) )) 52 | { 53 | throw new Error ("The 'logical operators' must be an array"); 54 | } 55 | 56 | if ( returning && !( Array.isArray(returning) ) ) 57 | { 58 | throw new Error ("The returning must be an array containing the name of the columns to be returned"); 59 | } 60 | 61 | if (typeof (beginTransaction) !== "boolean") 62 | { 63 | throw new Error ("The begin transaction must be a boolean"); 64 | } 65 | 66 | updateTable = table; 67 | const columnsNames = Object.keys(columns); 68 | 69 | const updateParamsArray = []; 70 | const values = []; 71 | let param = 1; 72 | 73 | columnsNames.forEach( (_column) => 74 | { 75 | const value = columns[_column].value; 76 | const type = columns[_column].type; 77 | 78 | if (isNaN(value)) 79 | { 80 | if (type) 81 | { 82 | const regexType = /number$|string$/; 83 | 84 | if (regexType.test(type)) 85 | { 86 | if (type.toLowerCase() === "number") 87 | { 88 | updateParamsArray.push(`${_column} = ${value}`); 89 | } 90 | else 91 | { 92 | updateParamsArray.push(`${_column} = $${param}`); 93 | values.push(value); 94 | param++; 95 | } 96 | } 97 | else 98 | { 99 | updateResult.error.params = "Invalid type. Type must be 'number' or 'string'"; 100 | } 101 | } 102 | else 103 | { 104 | updateResult.error.params = "When providing values as a string you need to specify its type. You can do that by adding a key 'type' with a value of 'string' or 'integer'"; 105 | } 106 | } 107 | else 108 | { 109 | updateParamsArray.push(`${_column} = $${param}`); 110 | values.push(value); 111 | param++; 112 | } 113 | }); 114 | 115 | if (updateResult.error.params) 116 | { 117 | return updateResult; 118 | } 119 | 120 | updateParams = updateParamsArray.join(", "); 121 | 122 | if (where) 123 | { 124 | const updateWhereArray = []; 125 | const whereColumns = Object.keys(where); 126 | 127 | if ( !logicalOperators) 128 | { 129 | throw new Error ("When using the WHERE clause, you must provide the logical operators"); 130 | } 131 | 132 | const validOperators = ValidateOperators(where, whereColumns, logicalOperators, updateWhereArray, values, param, updateResult); 133 | 134 | if (validOperators) 135 | { 136 | updateWhere = updateWhereArray.join (" "); 137 | param = validOperators; 138 | } 139 | else 140 | { 141 | return updateResult; 142 | } 143 | } 144 | 145 | if (returning) 146 | { 147 | updateReturning = returning.join(", "); 148 | } 149 | 150 | if (_method === "client") 151 | { 152 | if (beginTransaction) 153 | { 154 | const result = _connection 155 | .query("BEGIN;") 156 | .then( () => _connection.query(` 157 | UPDATE ${updateTable} SET ${updateParams} 158 | ${updateWhere ? `WHERE ${updateWhere}` : ""} 159 | ${updateReturning ? `RETURNING ${updateReturning}` : "" } 160 | `, values)) 161 | .then(async (result) => 162 | { 163 | updateResult.data = result.rows; 164 | 165 | await _connection 166 | .query("COMMIT;") 167 | .then( () => 168 | { 169 | updateResult.success.commit = true; 170 | }) 171 | .catch( (err) => 172 | { 173 | updateResult.error.commit = err.message; 174 | }); 175 | 176 | return updateResult; 177 | }) 178 | .catch(async (err) => 179 | { 180 | updateResult.error.transaction = err.message; 181 | 182 | await _connection 183 | .query("ROLLBACK;") 184 | .then( () => 185 | { 186 | updateResult.success.rollback = true; 187 | }) 188 | .catch( (err) => 189 | { 190 | updateResult.error.rollback = err.message; 191 | }); 192 | 193 | return updateResult; 194 | }) 195 | .finally( () => 196 | { 197 | updateTable = undefined; 198 | updateParams = undefined; 199 | updateWhere = undefined; 200 | updateReturning = undefined; 201 | }); 202 | 203 | return result; 204 | } 205 | else 206 | { 207 | const result = _connection 208 | .query(` 209 | UPDATE ${updateTable} SET ${updateParams} 210 | ${updateWhere ? `WHERE ${updateWhere}` : ""} 211 | ${updateReturning ? `RETURNING ${updateReturning}` : "" } 212 | `, values) 213 | .then( (result) => 214 | { 215 | updateResult.data = result.rows; 216 | 217 | return updateResult; 218 | }) 219 | .catch( (err) => 220 | { 221 | updateResult.error.transaction = err.message; 222 | 223 | return updateResult; 224 | }) 225 | .finally( () => 226 | { 227 | updateTable = undefined; 228 | updateParams = undefined; 229 | updateWhere = undefined; 230 | updateReturning = undefined; 231 | }); 232 | 233 | return result; 234 | } 235 | } 236 | else 237 | { 238 | if (beginTransaction) 239 | { 240 | const result = _connection 241 | .query("BEGIN;") 242 | .then( () => _connection.query(` 243 | UPDATE ${updateTable} SET ${updateParams} 244 | ${updateWhere ? `WHERE ${updateWhere}` : ""} 245 | ${updateReturning ? `RETURNING ${updateReturning}` : "" } 246 | `, values)) 247 | .then(async (result) => 248 | { 249 | updateResult.data = result.rows; 250 | 251 | await _connection 252 | .query("COMMIT;") 253 | .then( () => 254 | { 255 | updateResult.success.commit = true; 256 | }) 257 | .catch( (err) => 258 | { 259 | updateResult.error.commit = err.message; 260 | }); 261 | 262 | return updateResult; 263 | }) 264 | .catch(async (err) => 265 | { 266 | updateResult.error.transaction = err.message; 267 | 268 | await _connection 269 | .query("ROLLBACK;") 270 | .then( () => 271 | { 272 | updateResult.success.rollback = true; 273 | }) 274 | .catch( (err) => 275 | { 276 | updateResult.error.rollback = err.message; 277 | }); 278 | 279 | return updateResult; 280 | }) 281 | .finally( () => 282 | { 283 | try 284 | { 285 | _connection.release(); 286 | updateTable = undefined; 287 | updateParams = undefined; 288 | updateWhere = undefined; 289 | updateReturning = undefined; 290 | } 291 | catch 292 | { 293 | updateTable = undefined; 294 | updateParams = undefined; 295 | updateWhere = undefined; 296 | updateReturning = undefined; 297 | } 298 | }); 299 | 300 | return result; 301 | } 302 | else 303 | { 304 | const result = _connection 305 | .query(` 306 | UPDATE ${updateTable} SET ${updateParams} 307 | ${updateWhere ? `WHERE ${updateWhere}` : ""} 308 | ${updateReturning ? `RETURNING ${updateReturning}` : "" } 309 | `, values) 310 | .then( (result) => 311 | { 312 | updateResult.data = result.rows; 313 | 314 | return updateResult; 315 | }) 316 | .catch( (err) => 317 | { 318 | updateResult.error.transaction = err.message; 319 | 320 | return updateResult; 321 | }) 322 | .finally( () => 323 | { 324 | try 325 | { 326 | _connection.release(); 327 | updateTable = undefined; 328 | updateParams = undefined; 329 | updateWhere = undefined; 330 | updateReturning = undefined; 331 | } 332 | catch 333 | { 334 | updateTable = undefined; 335 | updateParams = undefined; 336 | updateWhere = undefined; 337 | updateReturning = undefined; 338 | } 339 | }); 340 | 341 | return result; 342 | } 343 | } 344 | } 345 | } 346 | 347 | module.exports = Update; 348 | --------------------------------------------------------------------------------