diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 2e634605cf..0000000000 --- a/.eslintrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "parserOptions": { - "ecmaVersion": 6 - }, - "rules": { - "eol-last": "error", - "indent": ["error", 2, { "SwitchCase": 1 }], - "no-trailing-spaces": "error", - "no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }] - } -} \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000000..4cc5ba14b0 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,27 @@ +module.exports = { + extends: ["eslint-config-airbnb-base", "eslint-config-prettier"], + plugins: ["eslint-plugin-import", "eslint-plugin-prettier"], + parserOptions: { + ecmaFeatures: { + ecmaVersion: 6 + } + }, + env: { + es6: true, + node: true + }, + rules: { + "prettier/prettier": ["error", {}], + "max-len": ["error", { code: 2000, ignoreUrls: true }], + "linebreak-style": 0, + "no-use-before-define": ["error", { functions: false, classes: false }], + "no-plusplus": ["error", { allowForLoopAfterthoughts: true }], + "no-underscore-dangle": 0, + "import/no-amd": 0, + "import/no-dynamic-require": 0, + "no-console": 0, + "no-param-reassign": 0, + "no-unused-vars": ["error", { argsIgnorePattern: "next" }], + "comma-dangle": 0 + } +}; diff --git a/bin/index.js b/bin/index.js index cb81fc7c26..4b1c68d964 100755 --- a/bin/index.js +++ b/bin/index.js @@ -1,70 +1,71 @@ #! /usr/bin/env node -const morgan = require('morgan'); -const bodyParser = require('body-parser'); -const express = require('express'); -const sqlConfig = require('commander'); -const mysql = require('mysql'); -const cors = require('cors'); -const dataHelp = require('../lib/util/data.helper.js'); -const Xapi = require('../lib/xapi.js'); -const cmdargs = require('../lib/util/cmd.helper.js'); -const cluster = require('cluster'); -const numCPUs = require('os').cpus().length; - +const morgan = require("morgan"); +const bodyParser = require("body-parser"); +const express = require("express"); +const sqlConfig = require("commander"); +const mysql = require("mysql"); +const cors = require("cors"); +const dataHelp = require("../lib/util/data.helper.js"); +const Xapi = require("../lib/xapi.js"); +const cmdargs = require("../lib/util/cmd.helper.js"); +const cluster = require("cluster"); +const numCPUs = require("os").cpus().length; function startXmysql(sqlConfig) { - /**************** START : setup express ****************/ let app = express(); - app.use(morgan('tiny')); + app.use(morgan("tiny")); app.use(cors()); app.use(bodyParser.json()); - app.use(bodyParser.urlencoded({ - extended: true - })); + app.use( + bodyParser.urlencoded({ + extended: true + }) + ); /**************** END : setup express ****************/ - /**************** START : setup mysql ****************/ let mysqlPool = mysql.createPool(sqlConfig); /**************** END : setup mysql ****************/ - /**************** START : setup Xapi ****************/ - console.log(''); - console.log(''); - console.log(''); - console.log(' Generating REST APIs at the speed of your thought.. '); - console.log(''); + console.log(""); + console.log(""); + console.log(""); + console.log(" Generating REST APIs at the speed of your thought.. "); + console.log(""); let t = process.hrtime(); let moreApis = new Xapi(sqlConfig, mysqlPool, app); moreApis.init((err, results) => { - app.listen(sqlConfig.portNumber, sqlConfig.ipAddress); var t1 = process.hrtime(t); var t2 = t1[0] + t1[1] / 1000000000; - - console.log(" Xmysql took : %d seconds", dataHelp.round(t2, 1)); - console.log(" API's base URL : " + "localhost:" + sqlConfig.portNumber); - console.log(' '); - console.log(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '); - + console.log( + " Xmysql took : %d seconds", + dataHelp.round(t2, 1) + ); + console.log( + " API's base URL : " + + "localhost:" + + sqlConfig.portNumber + ); + console.log(" "); + console.log( + " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " + ); }); /**************** END : setup Xapi ****************/ - } function start(sqlConfig) { - //handle cmd line arguments cmdargs.handle(sqlConfig); if (cluster.isMaster && sqlConfig.useCpuCores > 1) { - console.log(`Master ${process.pid} is running`); for (let i = 0; i < numCPUs && i < sqlConfig.useCpuCores; i++) { @@ -72,23 +73,21 @@ function start(sqlConfig) { cluster.fork(); } - cluster.on('exit', function(worker, code, signal) { - console.log('Worker ' + worker.process.pid + ' died with code: ' - + code + ', and signal: ' + signal); - console.log('Starting a new worker'); + cluster.on("exit", function(worker, code, signal) { + console.log( + "Worker " + + worker.process.pid + + " died with code: " + + code + + ", and signal: " + + signal + ); + console.log("Starting a new worker"); cluster.fork(); }); - } else { - startXmysql(sqlConfig); - } } - start(sqlConfig); - - - - diff --git a/examples/aws-lambda/index.js b/examples/aws-lambda/index.js index 0b6ac515f9..14cb00d5e6 100644 --- a/examples/aws-lambda/index.js +++ b/examples/aws-lambda/index.js @@ -8,7 +8,7 @@ * ** You need to put your lambda in a VPC * ** The lambda role needs access to the VPC * ** The RDS server has to be inside the VPC as well -* + * * Performance: * * Requests to the API Gateway resolve in ~ 90ms * @@ -20,30 +20,32 @@ */ "use strict"; -Object.defineProperty(exports, "__esModule", {value: true}); +Object.defineProperty(exports, "__esModule", { value: true }); var bodyParser = require("body-parser"); var express = require("express"); -var serverless = require('serverless-http'); +var serverless = require("serverless-http"); var cors = require("cors"); -var mysql = require('mysql'); -var Xapi = require('./node_modules/xmysql/lib/xapi.js'); -var morgan = require('morgan'); +var mysql = require("mysql"); +var Xapi = require("./node_modules/xmysql/lib/xapi.js"); +var morgan = require("morgan"); var app = express(); -var onXapiInitialized = new Promise(function (resolve, reject) { +var onXapiInitialized = new Promise(function(resolve, reject) { try { // /**************** START : setup express ****************/ - app.use(morgan('tiny')); + app.use(morgan("tiny")); app.use(cors()); app.use(bodyParser.json()); - app.use(bodyParser.urlencoded({ - extended: true - })); + app.use( + bodyParser.urlencoded({ + extended: true + }) + ); // /**************** END : setup express ****************/ - app.use(function (req, res, next) { + app.use(function(req, res, next) { // You can add authentication here - console.log('Received request for: ' + req.url, req); + console.log("Received request for: " + req.url, req); next(); }); @@ -53,8 +55,8 @@ var onXapiInitialized = new Promise(function (resolve, reject) { database: config.mysql.database, user: config.mysql.user, password: config.mysql.password, - apiPrefix: '/', - ipAddress: 'localhost', + apiPrefix: "/", + ipAddress: "localhost", portNumber: 3000, ignoreTables: [], storageFolder: __dirname @@ -62,18 +64,17 @@ var onXapiInitialized = new Promise(function (resolve, reject) { var mysqlPool = mysql.createPool(mysqlConfig); var xapi = new Xapi(mysqlConfig, mysqlPool, app); - xapi.init(function (err, results) { + xapi.init(function(err, results) { app.listen(3000); resolve(); }); - } - catch (err) { + } catch (err) { reject(err); } }); function handler(event, context, callback) { - onXapiInitialized.then(function () { + onXapiInitialized.then(function() { serverless(app)(event, context, callback); }); } diff --git a/index.js b/index.js index 8e0a87c113..a5f69d4e80 100644 --- a/index.js +++ b/index.js @@ -1,71 +1,72 @@ #! /usr/bin/env node -const morgan = require('morgan'); -const bodyParser = require('body-parser'); -const express = require('express'); -const sqlConfig = require('commander'); -const mysql = require('mysql'); -const cors = require('cors'); -const dataHelp = require('./lib/util/data.helper.js'); -const Xapi = require('./lib/xapi.js'); -const cmdargs = require('./lib/util/cmd.helper.js'); -const cluster = require('cluster'); -const numCPUs = require('os').cpus().length; -const { version } = require('./package.json'); - - +const morgan = require("morgan"); +const bodyParser = require("body-parser"); +const express = require("express"); +const sqlConfig = require("commander"); +const mysql = require("mysql"); +const cors = require("cors"); +const dataHelp = require("./lib/util/data.helper.js"); +const Xapi = require("./lib/xapi.js"); +const cmdargs = require("./lib/util/cmd.helper.js"); +const cluster = require("cluster"); +const numCPUs = require("os").cpus().length; +const { version } = require("./package.json"); function startXmysql(sqlConfig) { /**************** START : setup express ****************/ let app = express(); - app.set('version', version); - app.use(morgan('tiny')); + app.set("version", version); + app.use(morgan("tiny")); app.use(cors()); app.use(bodyParser.json()); - app.use(bodyParser.urlencoded({ - extended: true - })); + app.use( + bodyParser.urlencoded({ + extended: true + }) + ); /**************** END : setup express ****************/ - /**************** START : setup mysql ****************/ let mysqlPool = mysql.createPool(sqlConfig); /**************** END : setup mysql ****************/ - /**************** START : setup Xapi ****************/ - console.log(''); - console.log(''); - console.log(''); - console.log(' Generating REST APIs at the speed of your thought.. '); - console.log(''); + console.log(""); + console.log(""); + console.log(""); + console.log(" Generating REST APIs at the speed of your thought.. "); + console.log(""); let t = process.hrtime(); let moreApis = new Xapi(sqlConfig, mysqlPool, app); moreApis.init((err, results) => { - app.listen(sqlConfig.portNumber, sqlConfig.ipAddress); var t1 = process.hrtime(t); var t2 = t1[0] + t1[1] / 1000000000; - - console.log(" Xmysql took : %d seconds", dataHelp.round(t2, 1)); - console.log(" API's base URL : " + "localhost:" + sqlConfig.portNumber); - console.log(' '); - console.log(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '); - + console.log( + " Xmysql took : %d seconds", + dataHelp.round(t2, 1) + ); + console.log( + " API's base URL : " + + "localhost:" + + sqlConfig.portNumber + ); + console.log(" "); + console.log( + " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " + ); }); /**************** END : setup Xapi ****************/ - } function start(sqlConfig) { - cmdargs.handle(sqlConfig); if (cluster.isMaster && sqlConfig.useCpuCores > 1) { - console.log(`Master ${process.pid} is running`); for (let i = 0; i < numCPUs && i < sqlConfig.useCpuCores; i++) { @@ -73,24 +74,21 @@ function start(sqlConfig) { cluster.fork(); } - cluster.on('exit', function(worker, code, signal) { - console.log('Worker ' + worker.process.pid + ' died with code: ' - + code + ', and signal: ' + signal); - console.log('Starting a new worker'); + cluster.on("exit", function(worker, code, signal) { + console.log( + "Worker " + + worker.process.pid + + " died with code: " + + code + + ", and signal: " + + signal + ); + console.log("Starting a new worker"); cluster.fork(); }); - - } else { - startXmysql(sqlConfig); - } } - start(sqlConfig); - - - - diff --git a/lib/util/cmd.helper.js b/lib/util/cmd.helper.js index 3e81f71741..b929eee27d 100644 --- a/lib/util/cmd.helper.js +++ b/lib/util/cmd.helper.js @@ -1,101 +1,107 @@ -'use strict'; -const program = require('commander'); -const colors = require('colors'); -const maxCpus = require('os').cpus().length; - - -program.on('--help', () => { - console.log('') - console.log(' Examples:'.blue) - console.log('') - console.log(' $ xmysql -u username -p password -d databaseSchema'.blue) - console.log('') -}) +"use strict"; +const program = require("commander"); +const colors = require("colors"); +const maxCpus = require("os").cpus().length; + +program.on("--help", () => { + console.log(""); + console.log(" Examples:".blue); + console.log(""); + console.log(" $ xmysql -u username -p password -d databaseSchema".blue); + console.log(""); +}); program .version(module.exports.version) - .option('-h, --host ', 'hostname of database / localhost by default') - .option('-u, --user ', 'username of database / root by default') - .option('-p, --password ', 'password of database / empty by default') - .option('-d, --database ', 'database schema name') - .option('-r, --ipAddress ', 'IP interface of your server / localhost by default') - .option('-n, --portNumber ', 'port number for app / 3000 by default') - .option('-o, --port ', 'port number for mysql / 3306 by default') - .option('-S, --socketPath ', 'unix socket path / not used by default') - .option('-s, --storageFolder ', 'storage folder / current working dir by default / available only with local') - .option('-i, --ignoreTables ', 'comma separated table names to ignore') - .option('-a, --apiPrefix ', 'api url prefix / "/api/" by default') - .option('-y, --readOnly', 'readonly apis / false by default') - .option('-c, --useCpuCores ', 'use number of CPU cores (using cluster) / 1 by default') - .parse(process.argv) - + .option("-h, --host ", "hostname of database / localhost by default") + .option("-u, --user ", "username of database / root by default") + .option("-p, --password ", "password of database / empty by default") + .option("-d, --database ", "database schema name") + .option( + "-r, --ipAddress ", + "IP interface of your server / localhost by default" + ) + .option("-n, --portNumber ", "port number for app / 3000 by default") + .option("-o, --port ", "port number for mysql / 3306 by default") + .option("-S, --socketPath ", "unix socket path / not used by default") + .option( + "-s, --storageFolder ", + "storage folder / current working dir by default / available only with local" + ) + .option("-i, --ignoreTables ", "comma separated table names to ignore") + .option("-a, --apiPrefix ", 'api url prefix / "/api/" by default') + .option("-y, --readOnly", "readonly apis / false by default") + .option( + "-c, --useCpuCores ", + "use number of CPU cores (using cluster) / 1 by default" + ) + .parse(process.argv); function paintHelp(txt) { - return colors.magenta(txt) //display the help text in a color + return colors.magenta(txt); //display the help text in a color } function processInvalidArguments(program) { - - - let err = ''; + let err = ""; if (!program.password) { - err += 'Error: password for database is missing\n'; + err += "Error: password for database is missing\n"; } if (!program.database) { - err += 'Error: database name is missing\n'; + err += "Error: database name is missing\n"; } - if (err !== '') { - program.outputHelp(paintHelp) - console.log(err.red) + if (err !== "") { + program.outputHelp(paintHelp); + console.log(err.red); } } exports.handle = program => { - /**************** START : default values ****************/ - program.ipAddress = program.ipAddress || 'localhost'; + program.ipAddress = program.ipAddress || "localhost"; program.portNumber = program.portNumber || 3000; program.port = program.port || 3306; - program.user = program.user || 'root'; - program.password = program.password || ''; - program.host = program.host || 'localhost'; - program.socketPath = program.socketPath || ''; - program.storageFolder = program.storageFolder || process.cwd() - program.apiPrefix = program.apiPrefix || '/api/' + program.user = program.user || "root"; + program.password = program.password || ""; + program.host = program.host || "localhost"; + program.socketPath = program.socketPath || ""; + program.storageFolder = program.storageFolder || process.cwd(); + program.apiPrefix = program.apiPrefix || "/api/"; program.readOnly = program.readOnly || false; program.useCpuCores = program.useCpuCores || 1; - if(program.useCpuCores === '0') { + if (program.useCpuCores === "0") { program.useCpuCores = maxCpus; } if (program.ignoreTables) { - let ignoreTables = program.ignoreTables.split(',') - program.ignoreTables = {} + let ignoreTables = program.ignoreTables.split(","); + program.ignoreTables = {}; for (var i = 0; i < ignoreTables.length; ++i) { program.ignoreTables[ignoreTables[i]] = ignoreTables[i]; } } else { - program.ignoreTables = {} + program.ignoreTables = {}; } program.connectionLimit = 10; - if (program.host === 'localhost' || program.host === '127.0.0.1' || program.host === '::1') { - program.dynamic = 1 + if ( + program.host === "localhost" || + program.host === "127.0.0.1" || + program.host === "::1" + ) { + program.dynamic = 1; } // console.log(program); /**************** END : default values ****************/ - if (program.database && program.host && program.user) { //console.log('Starting server at:', 'http://' + program.host + ':' + program.portNumber) } else { - processInvalidArguments(program) - process.exit(1) + processInvalidArguments(program); + process.exit(1); } - }; diff --git a/lib/util/data.helper.js b/lib/util/data.helper.js index d0fb251c20..d95b0ee2fa 100644 --- a/lib/util/data.helper.js +++ b/lib/util/data.helper.js @@ -1,8 +1,6 @@ -'use strict'; - +"use strict"; exports.findOrInsertObjectArrayByKey = (obj, key, array) => { - let found = 0; let i = 0; @@ -16,15 +14,13 @@ exports.findOrInsertObjectArrayByKey = (obj, key, array) => { } if (!found) { - array.push(obj) + array.push(obj); } return array[i]; }; - exports.findObjectInArrayByKey = (key, value, objArray) => { - for (let i = 0; i < objArray.length; ++i) { if (objArray[i][key] === value) { return objArray[i]; @@ -34,24 +30,21 @@ exports.findObjectInArrayByKey = (key, value, objArray) => { return null; }; - -exports.round = function (number, precision) { +exports.round = function(number, precision) { var factor = Math.pow(10, precision); var tempNumber = number * factor; var roundedTempNumber = Math.round(tempNumber); return roundedTempNumber / factor; }; - exports.numberRound = (number, precision) => { var factor = Math.pow(10, precision); var tempNumber = number * factor; var roundedTempNumber = Math.round(tempNumber); return roundedTempNumber / factor; -} - -exports.numberGetLength = (number) => { +}; +exports.numberGetLength = number => { var n = number; if (number < 0) { @@ -59,109 +52,103 @@ exports.numberGetLength = (number) => { } return n.toString().length; -} +}; -exports.numberGetFixed = (number) => { +exports.numberGetFixed = number => { //console.log(number, typeof number); - return parseInt(number.toFixed()) -} - -exports.getStepArraySimple = function (min, max, step) { + return parseInt(number.toFixed()); +}; - var arr = [] +exports.getStepArraySimple = function(min, max, step) { + var arr = []; for (var i = min; i <= max; i = i + step) { - arr.push(i) + arr.push(i); } return arr; - }; exports.getStepArray = (min, max, stddev) => { - // console.log(' = = = = = = = '); //console.log('original numbers', min, max, stddev); - min = this.numberGetFixed(min) - max = this.numberGetFixed(max) - stddev = this.numberGetFixed(stddev) + min = this.numberGetFixed(min); + max = this.numberGetFixed(max); + stddev = this.numberGetFixed(stddev); // console.log('fixed numbers', min, max, stddev); - let minMinusHalf = min - stddev / 2 - let maxMinusHalf = max + stddev / 2 + let minMinusHalf = min - stddev / 2; + let maxMinusHalf = max + stddev / 2; - minMinusHalf = this.numberGetFixed(minMinusHalf) - maxMinusHalf = this.numberGetFixed(maxMinusHalf) + minMinusHalf = this.numberGetFixed(minMinusHalf); + maxMinusHalf = this.numberGetFixed(maxMinusHalf); // console.log('fixed numbers + (min,max)', min, max, stddev, '(', minMinusHalf, ',', maxMinusHalf, ')'); // console.log('numbers length', 'min', numberGetLength(min), 'max', numberGetLength(max), 'stddev', numberGetLength(stddev)); - let minLen = this.numberGetLength(minMinusHalf) - let maxLen = this.numberGetLength(maxMinusHalf) - let stddevLen = this.numberGetLength(stddev) + let minLen = this.numberGetLength(minMinusHalf); + let maxLen = this.numberGetLength(maxMinusHalf); + let stddevLen = this.numberGetLength(stddev); // // console.log('- - - -'); // console.log('Range', 'min', numberRound(minMinusHalf, -1)); // console.log('Range', 'max', numberRound(maxMinusHalf, -1)); // console.log('Range', 'stddev', numberRound(stddev, -1)); - if (minLen > 1) - minMinusHalf = this.numberRound(minMinusHalf, -1) - - if (maxLen > 2) - maxMinusHalf = this.numberRound(maxMinusHalf, -1) + if (minLen > 1) minMinusHalf = this.numberRound(minMinusHalf, -1); - if (stddevLen !== 1) - stddev = this.numberRound(stddev, -1) + if (maxLen > 2) maxMinusHalf = this.numberRound(maxMinusHalf, -1); + if (stddevLen !== 1) stddev = this.numberRound(stddev, -1); - var arr = [] + var arr = []; for (var step = minMinusHalf; step < maxMinusHalf; step = step + stddev) { - arr.push(step) + arr.push(step); } - arr.push(maxMinusHalf) + arr.push(maxMinusHalf); // console.log(arr); return arr; -} - - -exports.getSchemaQuery = function () { - return 'select c.table_name, c.column_name, c.ordinal_position,c.column_key,c.is_nullable, c.data_type, c.column_type,c.extra,c.privileges, ' + - 'c.column_comment,c.column_default,c.data_type,c.character_maximum_length, ' + - 'k.constraint_name, k.referenced_table_name, k.referenced_column_name, ' + - 's.index_name,s.seq_in_index, ' + - 'v.table_name as isView ' + - 'from ' + - 'information_schema.columns as c ' + - 'left join ' + - 'information_schema.key_column_usage as k ' + - 'on ' + - 'c.column_name=k.column_name and ' + - 'c.table_schema = k.referenced_table_schema and ' + - 'c.table_name = k.table_name ' + - 'left join ' + - 'information_schema.statistics as s ' + - 'on ' + - 'c.column_name = s.column_name and ' + - 'c.table_schema = s.index_schema and ' + - 'c.table_name = s.table_name ' + - 'LEFT JOIN ' + - 'information_schema.VIEWS as v ' + - 'ON ' + - 'c.table_schema = v.table_schema and ' + - 'c.table_name = v.table_name ' + - 'where ' + - 'c.table_schema=? ' + - 'order by ' + - 'c.table_name, c.ordinal_position'; }; -exports.getChartQuery = function () { - return 'select ? as ??, count(*) as _count from ?? where ?? between ? and ? ' -} +exports.getSchemaQuery = function() { + return ( + "select c.table_name, c.column_name, c.ordinal_position,c.column_key,c.is_nullable, c.data_type, c.column_type,c.extra,c.privileges, " + + "c.column_comment,c.column_default,c.data_type,c.character_maximum_length, " + + "k.constraint_name, k.referenced_table_name, k.referenced_column_name, " + + "s.index_name,s.seq_in_index, " + + "v.table_name as isView " + + "from " + + "information_schema.columns as c " + + "left join " + + "information_schema.key_column_usage as k " + + "on " + + "c.column_name=k.column_name and " + + "c.table_schema = k.referenced_table_schema and " + + "c.table_name = k.table_name " + + "left join " + + "information_schema.statistics as s " + + "on " + + "c.column_name = s.column_name and " + + "c.table_schema = s.index_schema and " + + "c.table_name = s.table_name " + + "LEFT JOIN " + + "information_schema.VIEWS as v " + + "ON " + + "c.table_schema = v.table_schema and " + + "c.table_name = v.table_name " + + "where " + + "c.table_schema=? " + + "order by " + + "c.table_name, c.ordinal_position" + ); +}; + +exports.getChartQuery = function() { + return "select ? as ??, count(*) as _count from ?? where ?? between ? and ? "; +}; exports.getDataType = function(colType, typesArr) { // console.log(colType,typesArr); @@ -171,29 +158,40 @@ exports.getDataType = function(colType, typesArr) { } } return 0; -} - -exports.getColumnType = function (column) { +}; - let strTypes = ['varchar', 'text', 'char', 'tinytext', 'mediumtext', 'longtext', 'blob', 'mediumblob', 'longblob', 'tinyblob', 'binary', 'varbinary']; - let intTypes = ['int', 'long', 'smallint', 'mediumint', 'bigint', 'tinyint']; - let flatTypes = ['float', 'double', 'decimal']; - let dateTypes = ['date', 'datetime', 'timestamp', 'time', 'year']; +exports.getColumnType = function(column) { + let strTypes = [ + "varchar", + "text", + "char", + "tinytext", + "mediumtext", + "longtext", + "blob", + "mediumblob", + "longblob", + "tinyblob", + "binary", + "varbinary" + ]; + let intTypes = ["int", "long", "smallint", "mediumint", "bigint", "tinyint"]; + let flatTypes = ["float", "double", "decimal"]; + let dateTypes = ["date", "datetime", "timestamp", "time", "year"]; //console.log(column); - if (this.getDataType(column['data_type'], strTypes)) { - return "string" - } else if (this.getDataType(column['data_type'], intTypes)) { - return "int" - } else if (this.getDataType(column['data_type'], flatTypes)) { - return "float" - } else if (this.getDataType(column['data_type'], dateTypes)) { - return "date" + if (this.getDataType(column["data_type"], strTypes)) { + return "string"; + } else if (this.getDataType(column["data_type"], intTypes)) { + return "int"; + } else if (this.getDataType(column["data_type"], flatTypes)) { + return "float"; + } else if (this.getDataType(column["data_type"], dateTypes)) { + return "date"; } else { - return "string" + return "string"; } - -} +}; exports.getType = function(colType, typesArr) { for (let i = 0; i < typesArr.length; ++i) { @@ -206,6 +204,4 @@ exports.getType = function(colType, typesArr) { } } return 0; -} - - +}; diff --git a/lib/util/whereClause.helper.js b/lib/util/whereClause.helper.js index 292dc544fe..6823a8f2a9 100644 --- a/lib/util/whereClause.helper.js +++ b/lib/util/whereClause.helper.js @@ -1,4 +1,4 @@ -'use strict'; +"use strict"; /** * @@ -6,70 +6,62 @@ * @returns obj.query = (?,?,?,?) obj.params = [1,2,3,4] */ function prepareInClauseParams(input) { - - let inElems = input.split(',') - let obj = {} - obj.whereQuery = '' - obj.whereParams = [] + let inElems = input.split(","); + let obj = {}; + obj.whereQuery = ""; + obj.whereParams = []; for (var j = 0; j < inElems.length; ++j) { - if (j === 0) { //enclose with open parenthesis - obj.whereQuery += '(' + obj.whereQuery += "("; } if (j) { - obj.whereQuery += ',' + obj.whereQuery += ","; } // add q mark and push the variable - obj.whereQuery += '?' - obj.whereParams.push(inElems[j]) + obj.whereQuery += "?"; + obj.whereParams.push(inElems[j]); if (j === inElems.length - 1) { //enclose with closing parenthesis - obj.whereQuery += ')' + obj.whereQuery += ")"; } } //console.log(obj); - return obj - + return obj; } function prepareLikeValue(value) { - //return value.replace("~", "%"); - return value.replace(/~/g, '%'); - + return value.replace(/~/g, "%"); } function prepareIsValue(value) { - //return value.replace("~", "%"); - if (value === 'null') { + if (value === "null") { return null; - } else if (value === 'true') { + } else if (value === "true") { return true; - } else if (value === 'false') { + } else if (value === "false") { return false; } else { - return null + return null; } - } function prepareBetweenValue(value) { - - let values = value.split(',') - let obj = {} - obj.whereQuery = '' - obj.whereParams = [] + let values = value.split(","); + let obj = {}; + obj.whereQuery = ""; + obj.whereParams = []; if (values.length === 2) { - obj.whereQuery = ' ? and ? ' - obj.whereParams.push(values[0]) - obj.whereParams.push(values[1]) + obj.whereQuery = " ? and ? "; + obj.whereParams.push(values[0]); + obj.whereParams.push(values[1]); } //console.log('prepareBetweenValue', obj); @@ -77,75 +69,78 @@ function prepareBetweenValue(value) { return obj; } - -function replaceWhereParamsToQMarks(openParentheses, str, comparisonOperator, condType) { - - let converted = '' +function replaceWhereParamsToQMarks( + openParentheses, + str, + comparisonOperator, + condType +) { + let converted = ""; if (openParentheses) { for (var i = 0; i < str.length; ++i) { - if (str[i] === '(') { - converted += '(' + if (str[i] === "(") { + converted += "("; } else { - converted += '??' + converted += "??"; break; } } } else { - - if (comparisonOperator !== ' in ' && comparisonOperator !== ' between ' && condType !== ' on ') { - converted = '?' - } else if (condType === ' on ') { - converted = '??' + if ( + comparisonOperator !== " in " && + comparisonOperator !== " between " && + condType !== " on " + ) { + converted = "?"; + } else if (condType === " on ") { + converted = "??"; } for (var i = str.length - 1; i >= 0; --i) { - if (str[i] === ')') { - converted += ')' + if (str[i] === ")") { + converted += ")"; } else { break; } } - } return converted; } function getComparisonOperator(operator) { - switch (operator) { - - case 'eq': - return '=' + case "eq": + return "="; break; - case 'ne': - return '!=' + case "ne": + return "!="; break; - case 'lt': - return '<' + case "lt": + return "<"; break; - case 'lte': - return '<=' + case "lte": + return "<="; break; - case 'gt': - return '>' + case "gt": + return ">"; break; - case 'gte': - return '>=' + case "gte": + return ">="; break; - case 'is': - return ' is ' + case "is": + return " is "; break; - case 'isnot': - return ' is not ' + case "isnot": + return " is not "; break; // case 'isnull': @@ -156,89 +151,90 @@ function getComparisonOperator(operator) { // return ' is not NULL ' // break; - case 'like': - return ' like ' + case "like": + return " like "; break; - case 'nlike': - return ' not like ' + case "nlike": + return " not like "; break; - case 'in': - return ' in ' + case "in": + return " in "; break; - case 'bw': - return ' between ' + case "bw": + return " between "; break; default: - return null + return null; break; - } - } - function getLogicalOperator(operator) { - switch (operator) { - - case '~or': - return 'or' + case "~or": + return "or"; break; - case '~and': - return 'and' + case "~and": + return "and"; break; // case '~not': // return 'not' // break; - case '~xor': - return 'xor' + case "~xor": + return "xor"; break; default: - return null + return null; break; } - } - -exports.getConditionClause = function (whereInQueryParams, condType = 'where') { - - let whereQuery = ''; +exports.getConditionClause = function(whereInQueryParams, condType = "where") { + let whereQuery = ""; let whereParams = []; let grammarErr = 0; let numOfConditions = whereInQueryParams.split(/~or|~and|~not|~xor/); - let logicalOperatorsInClause = whereInQueryParams.match(/(~or|~and|~not|~xor)/g) - - if (numOfConditions && logicalOperatorsInClause && numOfConditions.length !== logicalOperatorsInClause.length + 1) { - console.log('conditions and logical operators mismatch', numOfConditions.length, logicalOperatorsInClause.length); + let logicalOperatorsInClause = whereInQueryParams.match( + /(~or|~and|~not|~xor)/g + ); + + if ( + numOfConditions && + logicalOperatorsInClause && + numOfConditions.length !== logicalOperatorsInClause.length + 1 + ) { + console.log( + "conditions and logical operators mismatch", + numOfConditions.length, + logicalOperatorsInClause.length + ); } else { //console.log('numOfConditions',numOfConditions,whereInQueryParams); //console.log('logicalOperatorsInClause',logicalOperatorsInClause); for (var i = 0; i < numOfConditions.length; ++i) { - - let variable = '' - let comparisonOperator = '' - let logicalOperator = '' - let variableValue = '' - let temp = '' + let variable = ""; + let comparisonOperator = ""; + let logicalOperator = ""; + let variableValue = ""; + let temp = ""; // split on commas - var arr = numOfConditions[i].split(','); + var arr = numOfConditions[i].split(","); // consider first two splits only var result = arr.splice(0, 2); // join to make only 3 array elements - result.push(arr.join(',')); + result.push(arr.join(",")); // variable, operator, variablevalue if (result.length !== 3) { @@ -258,81 +254,86 @@ exports.getConditionClause = function (whereInQueryParams, condType = 'where') { } // get the variableName and push - whereParams.push(variable[1]) + whereParams.push(variable[1]); // then replace the variable name with ?? - temp = replaceWhereParamsToQMarks(true, result[0], ' ignore ', condType) + temp = replaceWhereParamsToQMarks(true, result[0], " ignore ", condType); if (!temp) { grammarErr = 1; break; } - whereQuery += temp + whereQuery += temp; /**************** END : variable ****************/ - /**************** START : operator and value ****************/ - comparisonOperator = getComparisonOperator(result[1]) + comparisonOperator = getComparisonOperator(result[1]); if (!comparisonOperator) { grammarErr = 1; break; } - whereQuery += comparisonOperator + whereQuery += comparisonOperator; // get the variableValue and push to params - variableValue = result[2].match(/(.*?)\)/) + variableValue = result[2].match(/(.*?)\)/); if (!variableValue || variableValue.length !== 2) { grammarErr = 1; break; } - if (comparisonOperator === ' in ') { - let obj = prepareInClauseParams(variableValue[1]) - whereQuery += obj.whereQuery - whereParams = whereParams.concat(obj.whereParams) - } else if (comparisonOperator === ' like ' || comparisonOperator === ' not like ') { - whereParams.push(prepareLikeValue(variableValue[1])) - } else if (comparisonOperator === ' is ') { - whereParams.push(prepareIsValue(variableValue[1])) - } else if (comparisonOperator === ' between ') { - let obj = prepareBetweenValue(variableValue[1]) - whereQuery += obj.whereQuery - whereParams = whereParams.concat(obj.whereParams) + if (comparisonOperator === " in ") { + let obj = prepareInClauseParams(variableValue[1]); + whereQuery += obj.whereQuery; + whereParams = whereParams.concat(obj.whereParams); + } else if ( + comparisonOperator === " like " || + comparisonOperator === " not like " + ) { + whereParams.push(prepareLikeValue(variableValue[1])); + } else if (comparisonOperator === " is ") { + whereParams.push(prepareIsValue(variableValue[1])); + } else if (comparisonOperator === " between ") { + let obj = prepareBetweenValue(variableValue[1]); + whereQuery += obj.whereQuery; + whereParams = whereParams.concat(obj.whereParams); //console.log(whereQuery, whereParams); } else { - whereParams.push(variableValue[1]) + whereParams.push(variableValue[1]); } // then replace the variableValue with ? - temp = replaceWhereParamsToQMarks(false, result[2], comparisonOperator, condType) + temp = replaceWhereParamsToQMarks( + false, + result[2], + comparisonOperator, + condType + ); if (!temp) { grammarErr = 1; break; } - whereQuery += temp + whereQuery += temp; if (numOfConditions.length !== -1 && i !== numOfConditions.length - 1) { //console.log('finding logical operator for',logicalOperatorsInClause[i]); - logicalOperator = getLogicalOperator(logicalOperatorsInClause[i]) + logicalOperator = getLogicalOperator(logicalOperatorsInClause[i]); if (!logicalOperator) { grammarErr = 1; break; } - whereQuery += getLogicalOperator(logicalOperatorsInClause[i]) + whereQuery += getLogicalOperator(logicalOperatorsInClause[i]); } /**************** END : operator ****************/ - - } } - let obj = {} + let obj = {}; - obj['query'] = '' - obj['params'] = [] - obj['err'] = grammarErr + obj["query"] = ""; + obj["params"] = []; + obj["err"] = grammarErr; // console.log(whereInQueryParams); // console.log(whereQuery); @@ -341,10 +342,9 @@ exports.getConditionClause = function (whereInQueryParams, condType = 'where') { // console.log('= = = = = = = = ='); if (!grammarErr) { - obj['query'] = whereQuery - obj['params'] = whereParams + obj["query"] = whereQuery; + obj["params"] = whereParams; } - return obj - -} + return obj; +}; diff --git a/lib/xapi.js b/lib/xapi.js index c6b6d8fc47..7cfe5cd7ba 100644 --- a/lib/xapi.js +++ b/lib/xapi.js @@ -1,380 +1,424 @@ -'use strict'; +"use strict"; -var Xsql = require('./xsql.js'); -var Xctrl = require('./xctrl.js'); -var multer = require('multer'); -const path = require('path'); +var Xsql = require("./xsql.js"); +var Xctrl = require("./xctrl.js"); +var multer = require("multer"); +const path = require("path"); -const v8 = require('v8'), - os = require('os'); +const v8 = require("v8"), + os = require("os"); //define class class Xapi { - constructor(args, mysqlPool, app) { - this.config = args; - this.mysql = new Xsql(args, mysqlPool) + this.mysql = new Xsql(args, mysqlPool); this.app = app; this.ctrls = []; /**************** START : multer ****************/ this.storage = multer.diskStorage({ - destination: function (req, file, cb) { - cb(null, process.cwd()) + destination: function(req, file, cb) { + cb(null, process.cwd()); }, - filename: function (req, file, cb) { + filename: function(req, file, cb) { console.log(file); - cb(null, Date.now() + '-' + file.originalname) + cb(null, Date.now() + "-" + file.originalname); } - }) + }); - this.upload = multer({storage: this.storage}) + this.upload = multer({ storage: this.storage }); /**************** END : multer ****************/ - - } - init(cbk) { - this.mysql.init((err, results) => { - - this.app.use(this.urlMiddleware.bind(this)) - let stat = this.setupRoutes() - this.app.use(this.errorMiddleware.bind(this)) - cbk(err, stat) - - }) - + this.app.use(this.urlMiddleware.bind(this)); + let stat = this.setupRoutes(); + this.app.use(this.errorMiddleware.bind(this)); + cbk(err, stat); + }); } - urlMiddleware(req, res, next) { - // get only request url from originalUrl - let justUrl = req.originalUrl.split('?')[0] - let pathSplit = [] + let justUrl = req.originalUrl.split("?")[0]; + let pathSplit = []; // split by apiPrefix - let apiSuffix = justUrl.split(this.config.apiPrefix) + let apiSuffix = justUrl.split(this.config.apiPrefix); if (apiSuffix.length === 2) { // split by / - pathSplit = apiSuffix[1].split('/') + pathSplit = apiSuffix[1].split("/"); if (pathSplit.length) { if (pathSplit.length >= 3) { // handle for relational routes - req.app.locals._parentTable = pathSplit[0] - req.app.locals._childTable = pathSplit[2] + req.app.locals._parentTable = pathSplit[0]; + req.app.locals._childTable = pathSplit[2]; } else { // handles rest of routes - req.app.locals._tableName = pathSplit[0] + req.app.locals._tableName = pathSplit[0]; } - } } next(); - } - errorMiddleware(err, req, res, next) { - - if (err && err.code) - res.status(400).json({error: err}); + if (err && err.code) res.status(400).json({ error: err }); else if (err && err.message) - res.status(500).json({error: 'Internal server error : ' + err.message}); - else - res.status(500).json({error: 'Internal server error : ' + err}); + res.status(500).json({ error: "Internal server error : " + err.message }); + else res.status(500).json({ error: "Internal server error : " + err }); next(err); - } asyncMiddleware(fn) { return (req, res, next) => { - Promise.resolve(fn(req, res, next)) - .catch((err) => { - next(err); - }); - } + Promise.resolve(fn(req, res, next)).catch(err => { + next(err); + }); + }; } root(req, res) { - let routes = []; - routes = this.mysql.getSchemaRoutes(false, req.protocol + '://' + req.get('host') + this.config.apiPrefix); - routes = routes.concat(this.mysql.globalRoutesPrint(req.protocol + '://' + req.get('host') + this.config.apiPrefix)) - res.json(routes) - + routes = this.mysql.getSchemaRoutes( + false, + req.protocol + "://" + req.get("host") + this.config.apiPrefix + ); + routes = routes.concat( + this.mysql.globalRoutesPrint( + req.protocol + "://" + req.get("host") + this.config.apiPrefix + ) + ); + res.json(routes); } setupRoutes() { - - let stat = {} - stat.tables = 0 - stat.apis = 0 + let stat = {}; + stat.tables = 0; + stat.apis = 0; // console.log('this.config while setting up routes', this.config); // show routes for database schema - this.app.get('/', this.asyncMiddleware(this.root.bind(this))) + this.app.get("/", this.asyncMiddleware(this.root.bind(this))); // show all resouces - this.app.route(this.config.apiPrefix + 'tables') + this.app + .route(this.config.apiPrefix + "tables") .get(this.asyncMiddleware(this.tables.bind(this))); - this.app.route(this.config.apiPrefix + 'xjoin') + this.app + .route(this.config.apiPrefix + "xjoin") .get(this.asyncMiddleware(this.xjoin.bind(this))); stat.apis += 3; - /**************** START : setup routes for each table ****************/ let resources = []; resources = this.mysql.getSchemaRoutes(true, this.config.apiPrefix); - stat.tables += resources.length + stat.tables += resources.length; // iterate over each resource for (var j = 0; j < resources.length; ++j) { - - - let resourceCtrl = new Xctrl(this.app, this.mysql) + let resourceCtrl = new Xctrl(this.app, this.mysql); this.ctrls.push(resourceCtrl); - let routes = resources[j]['routes']; + let routes = resources[j]["routes"]; - stat.apis += resources[j]['routes'].length + stat.apis += resources[j]["routes"].length; // iterate over each routes in resource and map function for (var i = 0; i < routes.length; ++i) { - - switch (routes[i]['routeType']) { - - case 'list': - this.app.route(routes[i]['routeUrl']) + switch (routes[i]["routeType"]) { + case "list": + this.app + .route(routes[i]["routeUrl"]) .get(this.asyncMiddleware(resourceCtrl.list.bind(resourceCtrl))); break; - case 'findOne': - this.app.route(routes[i]['routeUrl']) - .get(this.asyncMiddleware(resourceCtrl.findOne.bind(resourceCtrl))); + case "findOne": + this.app + .route(routes[i]["routeUrl"]) + .get( + this.asyncMiddleware(resourceCtrl.findOne.bind(resourceCtrl)) + ); break; - case 'create': + case "create": if (!this.config.readOnly) - this.app.route(routes[i]['routeUrl']) - .post(this.asyncMiddleware(resourceCtrl.create.bind(resourceCtrl))); + this.app + .route(routes[i]["routeUrl"]) + .post( + this.asyncMiddleware(resourceCtrl.create.bind(resourceCtrl)) + ); break; - case 'read': - this.app.route(routes[i]['routeUrl']) + case "read": + this.app + .route(routes[i]["routeUrl"]) .get(this.asyncMiddleware(resourceCtrl.read.bind(resourceCtrl))); break; - case 'bulkInsert': + case "bulkInsert": if (!this.config.readOnly) { - this.app.route(routes[i]['routeUrl']) - .post(this.asyncMiddleware(resourceCtrl.bulkInsert.bind(resourceCtrl))); + this.app + .route(routes[i]["routeUrl"]) + .post( + this.asyncMiddleware( + resourceCtrl.bulkInsert.bind(resourceCtrl) + ) + ); } break; - case 'bulkRead': - if (!this.config.readOnly){ - this.app.route(routes[i]['routeUrl']) - .get(this.asyncMiddleware(resourceCtrl.bulkRead.bind(resourceCtrl))); + case "bulkRead": + if (!this.config.readOnly) { + this.app + .route(routes[i]["routeUrl"]) + .get( + this.asyncMiddleware(resourceCtrl.bulkRead.bind(resourceCtrl)) + ); } else { stat.apis--; } break; - case 'bulkDelete': - if (!this.config.readOnly){ - this.app.route(routes[i]['routeUrl']) - .delete(this.asyncMiddleware(resourceCtrl.bulkDelete.bind(resourceCtrl))); + case "bulkDelete": + if (!this.config.readOnly) { + this.app + .route(routes[i]["routeUrl"]) + .delete( + this.asyncMiddleware( + resourceCtrl.bulkDelete.bind(resourceCtrl) + ) + ); } else { stat.apis--; } break; - case 'patch': - if (!this.config.readOnly){ - this.app.route(routes[i]['routeUrl']) - .patch(this.asyncMiddleware(resourceCtrl.patch.bind(resourceCtrl))); + case "patch": + if (!this.config.readOnly) { + this.app + .route(routes[i]["routeUrl"]) + .patch( + this.asyncMiddleware(resourceCtrl.patch.bind(resourceCtrl)) + ); } else { stat.apis--; } break; - case 'update': - if (!this.config.readOnly){ - this.app.route(routes[i]['routeUrl']) - .put(this.asyncMiddleware(resourceCtrl.update.bind(resourceCtrl))); + case "update": + if (!this.config.readOnly) { + this.app + .route(routes[i]["routeUrl"]) + .put( + this.asyncMiddleware(resourceCtrl.update.bind(resourceCtrl)) + ); } else { stat.apis--; } break; - case 'delete': - if (!this.config.readOnly){ - this.app.route(routes[i]['routeUrl']) - .delete(this.asyncMiddleware(resourceCtrl.delete.bind(resourceCtrl))); + case "delete": + if (!this.config.readOnly) { + this.app + .route(routes[i]["routeUrl"]) + .delete( + this.asyncMiddleware(resourceCtrl.delete.bind(resourceCtrl)) + ); } else { stat.apis--; } break; - case 'exists': - this.app.route(routes[i]['routeUrl']) - .get(this.asyncMiddleware(resourceCtrl.exists.bind(resourceCtrl))); + case "exists": + this.app + .route(routes[i]["routeUrl"]) + .get( + this.asyncMiddleware(resourceCtrl.exists.bind(resourceCtrl)) + ); break; - case 'count': - this.app.route(routes[i]['routeUrl']) + case "count": + this.app + .route(routes[i]["routeUrl"]) .get(this.asyncMiddleware(resourceCtrl.count.bind(resourceCtrl))); break; - case 'distinct': - this.app.route(routes[i]['routeUrl']) - .get(this.asyncMiddleware(resourceCtrl.distinct.bind(resourceCtrl))); + case "distinct": + this.app + .route(routes[i]["routeUrl"]) + .get( + this.asyncMiddleware(resourceCtrl.distinct.bind(resourceCtrl)) + ); break; - case 'describe': - this.app.route(routes[i]['routeUrl']) + case "describe": + this.app + .route(routes[i]["routeUrl"]) .get(this.asyncMiddleware(this.tableDescribe.bind(this))); break; - case 'relational': - this.app.route(routes[i]['routeUrl']) - .get(this.asyncMiddleware(resourceCtrl.nestedList.bind(resourceCtrl))); + case "relational": + this.app + .route(routes[i]["routeUrl"]) + .get( + this.asyncMiddleware(resourceCtrl.nestedList.bind(resourceCtrl)) + ); break; - case 'groupby': - this.app.route(routes[i]['routeUrl']) - .get(this.asyncMiddleware(resourceCtrl.groupBy.bind(resourceCtrl))); + case "groupby": + this.app + .route(routes[i]["routeUrl"]) + .get( + this.asyncMiddleware(resourceCtrl.groupBy.bind(resourceCtrl)) + ); break; - case 'ugroupby': - this.app.route(routes[i]['routeUrl']) - .get(this.asyncMiddleware(resourceCtrl.ugroupby.bind(resourceCtrl))); + case "ugroupby": + this.app + .route(routes[i]["routeUrl"]) + .get( + this.asyncMiddleware(resourceCtrl.ugroupby.bind(resourceCtrl)) + ); break; - case 'chart': - this.app.route(routes[i]['routeUrl']) + case "chart": + this.app + .route(routes[i]["routeUrl"]) .get(this.asyncMiddleware(resourceCtrl.chart.bind(resourceCtrl))); break; - case 'autoChart': - this.app.route(routes[i]['routeUrl']) - .get(this.asyncMiddleware(resourceCtrl.autoChart.bind(resourceCtrl))); + case "autoChart": + this.app + .route(routes[i]["routeUrl"]) + .get( + this.asyncMiddleware(resourceCtrl.autoChart.bind(resourceCtrl)) + ); break; - case 'aggregate': - this.app.route(routes[i]['routeUrl']) - .get(this.asyncMiddleware(resourceCtrl.aggregate.bind(resourceCtrl))); + case "aggregate": + this.app + .route(routes[i]["routeUrl"]) + .get( + this.asyncMiddleware(resourceCtrl.aggregate.bind(resourceCtrl)) + ); break; - } } } /**************** END : setup routes for each table ****************/ - if (this.config.dynamic === 1 && !this.config.readOnly) { - - this.app.route('/dynamic*') + this.app + .route("/dynamic*") .post(this.asyncMiddleware(this.runQuery.bind(this))); /**************** START : multer routes ****************/ - this.app.post('/upload', this.upload.single('file'), this.uploadFile.bind(this)); - this.app.post('/uploads', this.upload.array('files', 10), this.uploadFiles.bind(this)); - this.app.get('/download', this.downloadFile.bind(this)); + this.app.post( + "/upload", + this.upload.single("file"), + this.uploadFile.bind(this) + ); + this.app.post( + "/uploads", + this.upload.array("files", 10), + this.uploadFiles.bind(this) + ); + this.app.get("/download", this.downloadFile.bind(this)); /**************** END : multer routes ****************/ stat.apis += 4; - } /**************** START : health and version ****************/ - this.app.get('/_health', this.asyncMiddleware(this.health.bind(this))); - this.app.get('/_version', this.asyncMiddleware(this.version.bind(this))); + this.app.get("/_health", this.asyncMiddleware(this.health.bind(this))); + this.app.get("/_version", this.asyncMiddleware(this.version.bind(this))); stat.apis += 2; /**************** END : health and version ****************/ - - let statStr = ' Generated: ' + stat.apis + ' REST APIs for ' + stat.tables + ' tables ' - - console.log(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '); - console.log(' '); - console.log(' Database : %s', this.config.database); - console.log(' Number of Tables : %s', stat.tables); - console.log(' '); - console.log(' REST APIs Generated : %s'.green.bold, stat.apis); - console.log(' '); - - return stat - + let statStr = + " Generated: " + + stat.apis + + " REST APIs for " + + stat.tables + + " tables "; + + console.log( + " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " + ); + console.log(" "); + console.log( + " Database : %s", + this.config.database + ); + console.log(" Number of Tables : %s", stat.tables); + console.log(" "); + console.log( + " REST APIs Generated : %s".green.bold, + stat.apis + ); + console.log(" "); + + return stat; } async xjoin(req, res) { + let obj = {}; - let obj = {} - - obj.query = ''; + obj.query = ""; obj.params = []; - this.mysql.prepareJoinQuery(req, res, obj) + this.mysql.prepareJoinQuery(req, res, obj); //console.log(obj); if (obj.query.length) { - let results = await this.mysql.exec(obj.query, obj.params) - res.status(200).json(results) + let results = await this.mysql.exec(obj.query, obj.params); + res.status(200).json(results); } else { - res.status(400).json({err: 'Invalid Xjoin request'}); + res.status(400).json({ err: "Invalid Xjoin request" }); } - } async tableDescribe(req, res) { - - let query = 'describe ??'; + let query = "describe ??"; let params = [req.app.locals._tableName]; let results = await this.mysql.exec(query, params); res.status(200).json(results); - } async tables(req, res) { - - let query = 'SELECT table_name AS resource FROM information_schema.tables WHERE table_schema = ? '; + let query = + "SELECT table_name AS resource FROM information_schema.tables WHERE table_schema = ? "; let params = [this.config.database]; if (Object.keys(this.config.ignoreTables).length > 0) { - query += 'and table_name not in (?)' - params.push(Object.keys(this.config.ignoreTables)) + query += "and table_name not in (?)"; + params.push(Object.keys(this.config.ignoreTables)); } - let results = await this.mysql.exec(query, params) + let results = await this.mysql.exec(query, params); - res.status(200).json(results) + res.status(200).json(results); } async runQuery(req, res) { - let query = req.body.query; let params = req.body.params; let results = await this.mysql.exec(query, params); res.status(200).json(results); - - } - /**************** START : files related ****************/ downloadFile(req, res) { let file = path.join(process.cwd(), req.query.name); @@ -382,19 +426,17 @@ class Xapi { } uploadFile(req, res) { - if (req.file) { console.log(req.file.path); res.end(req.file.path); } else { - res.end('upload failed'); + res.end("upload failed"); } } uploadFiles(req, res) { - if (!req.files || req.files.length === 0) { - res.end('upload failed') + res.end("upload failed"); } else { let files = []; for (let i = 0; i < req.files.length; ++i) { @@ -403,58 +445,49 @@ class Xapi { res.end(files.toString()); } - } /**************** END : files related ****************/ - /**************** START : health and version ****************/ async getMysqlUptime() { - let v = await this.mysql.exec('SHOW GLOBAL STATUS LIKE \'Uptime\';', []); - return v[0]['Value']; + let v = await this.mysql.exec("SHOW GLOBAL STATUS LIKE 'Uptime';", []); + return v[0]["Value"]; } async getMysqlHealth() { - let v = await this.mysql.exec('select version() as version', []); - return v[0]['version']; + let v = await this.mysql.exec("select version() as version", []); + return v[0]["version"]; } async health(req, res) { - let status = {}; - status['process_uptime'] = process.uptime(); - status['mysql_uptime'] = await this.getMysqlUptime(); + status["process_uptime"] = process.uptime(); + status["mysql_uptime"] = await this.getMysqlUptime(); if (Object.keys(req.query).length) { - status['process_memory_usage'] = process.memoryUsage(); - status['os_total_memory'] = os.totalmem(); - status['os_free_memory'] = os.freemem(); - status['os_load_average'] = os.loadavg(); - status['v8_heap_statistics'] = v8.getHeapStatistics(); + status["process_memory_usage"] = process.memoryUsage(); + status["os_total_memory"] = os.totalmem(); + status["os_free_memory"] = os.freemem(); + status["os_load_average"] = os.loadavg(); + status["v8_heap_statistics"] = v8.getHeapStatistics(); } res.json(status); - } async version(req, res) { - let version = {}; - version['Xmysql'] = this.app.get('version'); - version['mysql'] = await this.getMysqlHealth(); - version['node'] = process.versions.node; + version["Xmysql"] = this.app.get("version"); + version["mysql"] = await this.getMysqlHealth(); + version["node"] = process.versions.node; res.json(version); - } /**************** END : health and version ****************/ - } - //expose class module.exports = Xapi; - diff --git a/lib/xctrl.js b/lib/xctrl.js index 50f6120072..86c8fb3705 100644 --- a/lib/xctrl.js +++ b/lib/xctrl.js @@ -1,16 +1,12 @@ //define class class xctrl { - - constructor(app,mysql) { - + constructor(app, mysql) { this.app = app; this.mysql = mysql; - } async create(req, res) { - - let query = 'INSERT INTO ?? SET ?'; + let query = "INSERT INTO ?? SET ?"; let params = []; params.push(req.app.locals._tableName); @@ -18,105 +14,102 @@ class xctrl { var results = await this.mysql.exec(query, params); res.status(200).json(results); - } - async list(req, res) { - - let queryParamsObj = {} - queryParamsObj.query = '' - queryParamsObj.params = [] + let queryParamsObj = {}; + queryParamsObj.query = ""; + queryParamsObj.params = []; this.mysql.prepareListQuery(req, res, queryParamsObj, 0); - let results = await this.mysql.exec(queryParamsObj.query, queryParamsObj.params); + let results = await this.mysql.exec( + queryParamsObj.query, + queryParamsObj.params + ); res.status(200).json(results); - } - async nestedList(req, res) { - - let queryParamsObj = {} - queryParamsObj.query = ''; + let queryParamsObj = {}; + queryParamsObj.query = ""; queryParamsObj.params = []; - this.mysql.prepareListQuery(req, res, queryParamsObj, 1) + this.mysql.prepareListQuery(req, res, queryParamsObj, 1); - let results = await this.mysql.exec(queryParamsObj.query, queryParamsObj.params); + let results = await this.mysql.exec( + queryParamsObj.query, + queryParamsObj.params + ); res.status(200).json(results); - } async findOne(req, res) { - - let queryParamsObj = {} - queryParamsObj.query = '' - queryParamsObj.params = [] + let queryParamsObj = {}; + queryParamsObj.query = ""; + queryParamsObj.params = []; this.mysql.prepareListQuery(req, res, queryParamsObj, 2); - let results = await this.mysql.exec(queryParamsObj.query, queryParamsObj.params); + let results = await this.mysql.exec( + queryParamsObj.query, + queryParamsObj.params + ); res.status(200).json(results); - } async read(req, res) { - - let query = 'select * from ?? where '; + let query = "select * from ?? where "; let params = []; params.push(req.app.locals._tableName); - let clause = this.mysql.getPrimaryKeyWhereClause(req.app.locals._tableName, - req.params.id.split('___')); - + let clause = this.mysql.getPrimaryKeyWhereClause( + req.app.locals._tableName, + req.params.id.split("___") + ); if (!clause) { return res.status(400).send({ - error: "Table is made of composite primary keys - all keys were not in input" + error: + "Table is made of composite primary keys - all keys were not in input" }); } query += clause; - query += ' LIMIT 1' + query += " LIMIT 1"; let results = await this.mysql.exec(query, params); res.status(200).json(results); - - } async exists(req, res) { - - let query = 'select * from ?? where '; + let query = "select * from ?? where "; let params = []; params.push(req.app.locals._tableName); - let clause = this.mysql.getPrimaryKeyWhereClause(req.app.locals._tableName, - req.params.id.split('___')); + let clause = this.mysql.getPrimaryKeyWhereClause( + req.app.locals._tableName, + req.params.id.split("___") + ); if (!clause) { return res.status(400).send({ - error: "Table is made of composite primary keys - all keys were not in input" - }) + error: + "Table is made of composite primary keys - all keys were not in input" + }); } query += clause; - query += ' LIMIT 1' + query += " LIMIT 1"; let results = await this.mysql.exec(query, params); res.status(200).json(results); - - } - async update(req, res) { - - let query = 'REPLACE INTO ?? SET ?'; + let query = "REPLACE INTO ?? SET ?"; let params = []; params.push(req.app.locals._tableName); @@ -124,31 +117,31 @@ class xctrl { var results = await this.mysql.exec(query, params); res.status(200).json(results); - } async patch(req, res) { - - let query = 'UPDATE ?? SET '; + let query = "UPDATE ?? SET "; let keys = Object.keys(req.body); // SET clause - let updateKeys = ''; + let updateKeys = ""; for (let i = 0; i < keys.length; ++i) { - updateKeys += keys[i] + ' = ? ' - if (i !== keys.length - 1) - updateKeys += ', ' + updateKeys += keys[i] + " = ? "; + if (i !== keys.length - 1) updateKeys += ", "; } // where clause - query += updateKeys + ' where ' - let clause = this.mysql.getPrimaryKeyWhereClause(req.app.locals._tableName, - req.params.id.split('___')); + query += updateKeys + " where "; + let clause = this.mysql.getPrimaryKeyWhereClause( + req.app.locals._tableName, + req.params.id.split("___") + ); if (!clause) { return res.status(400).send({ - error: "Table is made of composite primary keys - all keys were not in input" - }) + error: + "Table is made of composite primary keys - all keys were not in input" + }); } query += clause; @@ -160,23 +153,23 @@ class xctrl { let results = await this.mysql.exec(query, params); res.status(200).json(results); - - } async delete(req, res) { - - let query = 'DELETE FROM ?? WHERE '; + let query = "DELETE FROM ?? WHERE "; let params = []; params.push(req.app.locals._tableName); - let clause = this.mysql.getPrimaryKeyWhereClause(req.app.locals._tableName, - req.params.id.split('___')); + let clause = this.mysql.getPrimaryKeyWhereClause( + req.app.locals._tableName, + req.params.id.split("___") + ); if (!clause) { return res.status(400).send({ - error: "Table is made of composite primary keys - all keys were not in input" + error: + "Table is made of composite primary keys - all keys were not in input" }); } @@ -184,278 +177,306 @@ class xctrl { let results = await this.mysql.exec(query, params); res.status(200).json(results); - - } async bulkInsert(req, res) { - - let queryParamsObj = {} - queryParamsObj.query = '' - queryParamsObj.params = [] - let results = [] + let queryParamsObj = {}; + queryParamsObj.query = ""; + queryParamsObj.params = []; + let results = []; //console.log(req.app.locals._tableName, req.body); - this.mysql.prepareBulkInsert(req.app.locals._tableName, req.body, queryParamsObj) + this.mysql.prepareBulkInsert( + req.app.locals._tableName, + req.body, + queryParamsObj + ); - results = await this.mysql.exec(queryParamsObj.query, queryParamsObj.params); + results = await this.mysql.exec( + queryParamsObj.query, + queryParamsObj.params + ); res.status(200).json(results); - } async bulkDelete(req, res) { - - let query = 'delete from ?? where ?? in '; + let query = "delete from ?? where ?? in "; let params = []; params.push(req.app.locals._tableName); params.push(this.mysql.getPrimaryKeyName(req.app.locals._tableName)); - query += '(' + query += "("; if (req.query && req.query._ids) { - let ids = req.query._ids.split(',') + let ids = req.query._ids.split(","); for (var i = 0; i < ids.length; ++i) { if (i) { - query += ',' + query += ","; } - query += '?' - params.push(ids[i]) + query += "?"; + params.push(ids[i]); } } - query += ')' + query += ")"; //console.log(query, params); var results = await this.mysql.exec(query, params); res.status(200).json(results); - } async bulkRead(req, res) { - - let queryParamsObj = {} - queryParamsObj.query = '' - queryParamsObj.params = [] + let queryParamsObj = {}; + queryParamsObj.query = ""; + queryParamsObj.params = []; this.mysql.prepareListQuery(req, res, queryParamsObj, 3); //console.log(queryParamsObj.query, queryParamsObj.params); - let results = await this.mysql.exec(queryParamsObj.query, queryParamsObj.params); + let results = await this.mysql.exec( + queryParamsObj.query, + queryParamsObj.params + ); res.status(200).json(results); - } - async count(req, res) { + let queryParams = {}; - let queryParams = {} - - queryParams.query = 'select count(1) as no_of_rows from ?? '; + queryParams.query = "select count(1) as no_of_rows from ?? "; queryParams.params = []; queryParams.params.push(req.app.locals._tableName); - this.mysql.getWhereClause(req.query._where, req.app.locals._tableName, queryParams, ' where ') + this.mysql.getWhereClause( + req.query._where, + req.app.locals._tableName, + queryParams, + " where " + ); let results = await this.mysql.exec(queryParams.query, queryParams.params); res.status(200).json(results); - } async distinct(req, res) { - - let queryParamsObj = {} - queryParamsObj.query = '' - queryParamsObj.params = [] + let queryParamsObj = {}; + queryParamsObj.query = ""; + queryParamsObj.params = []; this.mysql.prepareListQuery(req, res, queryParamsObj, 4); - let results = await this.mysql.exec(queryParamsObj.query, queryParamsObj.params); + let results = await this.mysql.exec( + queryParamsObj.query, + queryParamsObj.params + ); res.status(200).json(results); - } - async groupBy(req, res) { - if (req.query && req.query._fields) { - - let queryParamsObj = {} - queryParamsObj.query = 'select '; + let queryParamsObj = {}; + queryParamsObj.query = "select "; queryParamsObj.params = []; /**************** add columns and group by columns ****************/ - this.mysql.getColumnsForSelectStmt(req.app.locals._tableName, req.query, queryParamsObj) + this.mysql.getColumnsForSelectStmt( + req.app.locals._tableName, + req.query, + queryParamsObj + ); - queryParamsObj.query += ',count(*) as _count from ?? group by '; + queryParamsObj.query += ",count(*) as _count from ?? group by "; let tableName = req.app.locals._tableName; queryParamsObj.params.push(tableName); - this.mysql.getColumnsForSelectStmt(req.app.locals._tableName, req.query, queryParamsObj) + this.mysql.getColumnsForSelectStmt( + req.app.locals._tableName, + req.query, + queryParamsObj + ); if (!req.query._sort) { - req.query._sort = {} - req.query._sort = '-_count' + req.query._sort = {}; + req.query._sort = "-_count"; } /**************** add having clause ****************/ - this.mysql.getHavingClause(req.query._having, req.app.locals._tableName, queryParamsObj, ' having '); + this.mysql.getHavingClause( + req.query._having, + req.app.locals._tableName, + queryParamsObj, + " having " + ); /**************** add orderby clause ****************/ this.mysql.getOrderByClause(req.query, tableName, queryParamsObj); //console.log(queryParamsObj.query, queryParamsObj.params); - var results = await this.mysql.exec(queryParamsObj.query, queryParamsObj.params); + var results = await this.mysql.exec( + queryParamsObj.query, + queryParamsObj.params + ); res.status(200).json(results); - } else { - res.status(400).json({message: 'Missing _fields query params eg: /api/tableName/groupby?_fields=column1'}) + res + .status(400) + .json({ + message: + "Missing _fields query params eg: /api/tableName/groupby?_fields=column1" + }); } - } async ugroupby(req, res) { - if (req.query && req.query._fields) { - - let queryParamsObj = {} - queryParamsObj.query = ''; + let queryParamsObj = {}; + queryParamsObj.query = ""; queryParamsObj.params = []; - let uGrpByResults = {} + let uGrpByResults = {}; /**************** add fields with count(*) *****************/ - let fields = req.query._fields.split(',') + let fields = req.query._fields.split(","); for (var i = 0; i < fields.length; ++i) { - - uGrpByResults[fields[i]] = [] + uGrpByResults[fields[i]] = []; if (i) { - queryParamsObj.query += ' UNION ' + queryParamsObj.query += " UNION "; } - queryParamsObj.query += ' SELECT IFNULL(CONCAT(?,?,??),?) as ugroupby, count(*) as _count from ?? GROUP BY ?? ' - queryParamsObj.params.push(fields[i]) - queryParamsObj.params.push('~') - queryParamsObj.params.push(fields[i]) - queryParamsObj.params.push(fields[i] + '~') - queryParamsObj.params.push(req.app.locals._tableName) - queryParamsObj.params.push(fields[i]) + queryParamsObj.query += + " SELECT IFNULL(CONCAT(?,?,??),?) as ugroupby, count(*) as _count from ?? GROUP BY ?? "; + queryParamsObj.params.push(fields[i]); + queryParamsObj.params.push("~"); + queryParamsObj.params.push(fields[i]); + queryParamsObj.params.push(fields[i] + "~"); + queryParamsObj.params.push(req.app.locals._tableName); + queryParamsObj.params.push(fields[i]); } //console.log(queryParamsObj.query, queryParamsObj.params); - var results = await this.mysql.exec(queryParamsObj.query, queryParamsObj.params); + var results = await this.mysql.exec( + queryParamsObj.query, + queryParamsObj.params + ); for (var i = 0; i < results.length; ++i) { + let grpByColName = results[i]["ugroupby"].split("~")[0]; + let grpByColValue = results[i]["ugroupby"].split("~")[1]; - let grpByColName = results[i]['ugroupby'].split('~')[0] - let grpByColValue = results[i]['ugroupby'].split('~')[1] - - let obj = {} - obj[grpByColValue] = results[i]['_count']; - - uGrpByResults[grpByColName].push(obj) + let obj = {}; + obj[grpByColValue] = results[i]["_count"]; + uGrpByResults[grpByColName].push(obj); } res.status(200).json(uGrpByResults); - } else { - res.status(400).json({message: 'Missing _fields query params eg: /api/tableName/ugroupby?_fields=column1,column2'}) + res + .status(400) + .json({ + message: + "Missing _fields query params eg: /api/tableName/ugroupby?_fields=column1,column2" + }); } } - async aggregate(req, res) { - - if (req.query && req.query._fields) { let tableName = req.app.locals._tableName; - let query = 'select ' - let params = [] - let fields = req.query._fields.split(','); + let query = "select "; + let params = []; + let fields = req.query._fields.split(","); for (var i = 0; i < fields.length; ++i) { if (i) { - query = query + ',' + query = query + ","; } - query = query + ' min(??) as ?,max(??) as ?,avg(??) as ?,sum(??) as ?,stddev(??) as ?,variance(??) as ? ' + query = + query + + " min(??) as ?,max(??) as ?,avg(??) as ?,sum(??) as ?,stddev(??) as ?,variance(??) as ? "; params.push(fields[i]); - params.push('min_of_' + fields[i]); + params.push("min_of_" + fields[i]); params.push(fields[i]); - params.push('max_of_' + fields[i]); + params.push("max_of_" + fields[i]); params.push(fields[i]); - params.push('avg_of_' + fields[i]); + params.push("avg_of_" + fields[i]); params.push(fields[i]); - params.push('sum_of_' + fields[i]); + params.push("sum_of_" + fields[i]); params.push(fields[i]); - params.push('stddev_of_' + fields[i]); + params.push("stddev_of_" + fields[i]); params.push(fields[i]); - params.push('variance_of_' + fields[i]); + params.push("variance_of_" + fields[i]); } - query = query + ' from ??' - params.push(tableName) + query = query + " from ??"; + params.push(tableName); var results = await this.mysql.exec(query, params); res.status(200).json(results); } else { - res.status(400).json({message: 'Missing _fields in query params eg: /api/tableName/aggregate?_fields=numericColumn1'}); + res + .status(400) + .json({ + message: + "Missing _fields in query params eg: /api/tableName/aggregate?_fields=numericColumn1" + }); } - } - async chart(req, res) { - - let query = '' - let params = [] - let obj = {} - + let query = ""; + let params = []; + let obj = {}; if (req.query) { - - let isRange = false + let isRange = false; if (req.query.range) { - isRange = true + isRange = true; } if (req.query && req.query.min && req.query.max && req.query.step) { - //console.log(req.params.min, req.params.max, req.params.step); - obj = this.mysql.getChartQueryAndParamsFromMinMaxStep(req.app.locals._tableName, + obj = this.mysql.getChartQueryAndParamsFromMinMaxStep( + req.app.locals._tableName, req.query._fields, parseInt(req.query.min), parseInt(req.query.max), parseInt(req.query.step), - isRange) - - - } else if (req.query && req.query.steparray && req.query.steparray.length > 1) { - - obj = this.mysql.getChartQueryAndParamsFromStepArray(req.app.locals._tableName, + isRange + ); + } else if ( + req.query && + req.query.steparray && + req.query.steparray.length > 1 + ) { + obj = this.mysql.getChartQueryAndParamsFromStepArray( + req.app.locals._tableName, req.query._fields, - (req.query.steparray.split(',')).map(Number), - isRange) - - - } else if (req.query && req.query.steppair && req.query.steppair.length > 1) { - - obj = this.mysql.getChartQueryAndParamsFromStepPair(req.app.locals._tableName, + req.query.steparray.split(",").map(Number), + isRange + ); + } else if ( + req.query && + req.query.steppair && + req.query.steppair.length > 1 + ) { + obj = this.mysql.getChartQueryAndParamsFromStepPair( + req.app.locals._tableName, req.query._fields, - (req.query.steppair.split(',')).map(Number), - false) - - + req.query.steppair.split(",").map(Number), + false + ); } else { - - query = 'select min(??) as min,max(??) as max,stddev(??) as stddev,avg(??) as avg from ??'; + query = + "select min(??) as min,max(??) as max,stddev(??) as stddev,avg(??) as avg from ??"; params = []; params.push(req.query._fields); @@ -466,66 +487,70 @@ class xctrl { let _this = this; - let results = await - _this.mysql.exec(query, params); + let results = await _this.mysql.exec(query, params); //console.log(results, results['max'], req.params); - obj = _this.mysql.getChartQueryAndParamsFromMinMaxStddev(req.app.locals._tableName, + obj = _this.mysql.getChartQueryAndParamsFromMinMaxStddev( + req.app.locals._tableName, req.query._fields, - results[0]['min'], - results[0]['max'], - results[0]['stddev'], + results[0]["min"], + results[0]["max"], + results[0]["stddev"], isRange - ) - + ); } - this.mysql.getWhereClause(req.query._where, req.app.locals._tableName, obj, ' where ') + this.mysql.getWhereClause( + req.query._where, + req.app.locals._tableName, + obj, + " where " + ); - let results = await - this.mysql.exec(obj.query, obj.params); + let results = await this.mysql.exec(obj.query, obj.params); res.status(200).json(results); - } else { - res.status(400).json({message: 'Missing _fields in query params eg: /api/tableName/chart?_fields=numericColumn1'}); + res + .status(400) + .json({ + message: + "Missing _fields in query params eg: /api/tableName/chart?_fields=numericColumn1" + }); } - - } - async autoChart(req, res) { + let query = "describe ??"; + let params = [req.app.locals._tableName]; + let obj = {}; + let results = []; - let query = 'describe ??' - let params = [req.app.locals._tableName] - let obj = {} - let results = [] - - let isRange = false + let isRange = false; if (req.query.range) { - isRange = true + isRange = true; } - - let describeResults = await this.mysql.exec(query, params) + let describeResults = await this.mysql.exec(query, params); //console.log(describeResults); for (var i = 0; i < describeResults.length; ++i) { - //console.log('is this numeric column', describeResults[i]['Type']); - if (describeResults[i]['Key'] !== 'PRI' && this.mysql.isTypeOfColumnNumber(describeResults[i]['Type'])) { - - query = 'select min(??) as min,max(??) as max,stddev(??) as stddev,avg(??) as avg from ??'; + if ( + describeResults[i]["Key"] !== "PRI" && + this.mysql.isTypeOfColumnNumber(describeResults[i]["Type"]) + ) { + query = + "select min(??) as min,max(??) as max,stddev(??) as stddev,avg(??) as avg from ??"; params = []; - params.push(describeResults[i]['Field']); - params.push(describeResults[i]['Field']); - params.push(describeResults[i]['Field']); - params.push(describeResults[i]['Field']); + params.push(describeResults[i]["Field"]); + params.push(describeResults[i]["Field"]); + params.push(describeResults[i]["Field"]); + params.push(describeResults[i]["Field"]); params.push(req.app.locals._tableName); let _this = this; @@ -534,33 +559,31 @@ class xctrl { //console.log(minMaxResults, minMaxResults['max'], req.params); - query = '' - params = [] + query = ""; + params = []; - obj = _this.mysql.getChartQueryAndParamsFromMinMaxStddev(req.app.locals._tableName, - describeResults[i]['Field'], - minMaxResults[0]['min'], - minMaxResults[0]['max'], - minMaxResults[0]['stddev'], + obj = _this.mysql.getChartQueryAndParamsFromMinMaxStddev( + req.app.locals._tableName, + describeResults[i]["Field"], + minMaxResults[0]["min"], + minMaxResults[0]["max"], + minMaxResults[0]["stddev"], isRange - ) + ); let r = await this.mysql.exec(obj.query, obj.params); - let resultObj = {} - resultObj['column'] = describeResults[i]['Field'] - resultObj['chart'] = r + let resultObj = {}; + resultObj["column"] = describeResults[i]["Field"]; + resultObj["chart"] = r; results.push(resultObj); - } } res.status(200).json(results); } - - } //expose class -module.exports = xctrl; \ No newline at end of file +module.exports = xctrl; diff --git a/lib/xsql.js b/lib/xsql.js index a33e8722b9..63ace86efa 100644 --- a/lib/xsql.js +++ b/lib/xsql.js @@ -1,153 +1,146 @@ -'use strict'; - -const mysql = require('mysql'); -const dataHelp = require('./util/data.helper.js'); -const whereHelp = require('./util/whereClause.helper.js'); -const assert = require('assert') +"use strict"; +const mysql = require("mysql"); +const dataHelp = require("./util/data.helper.js"); +const whereHelp = require("./util/whereClause.helper.js"); +const assert = require("assert"); //define class§ class Xsql { - constructor(sqlConfig, pool) { - //define this variables - this.sqlConfig = {} - this.pool = {} + this.sqlConfig = {}; + this.pool = {}; this.metaDb = {}; this.metaDb.tables = {}; this.sqlConfig = sqlConfig; this.pool = pool; - } - /**************** START : Cache functions ****************/ init(cbk) { this.dbCacheInitAsync((err, results) => { - cbk(err, results) - }) + cbk(err, results); + }); } - dbCacheInitAsync(cbk) { - let self = this; - self.pool.query(dataHelp.getSchemaQuery(), [this.sqlConfig.database], (err, results) => { - - if (err) { - console.log('Cache init failed during database reading') - console.log(err, results) - cbk(err, results) - } else { - - for (var i = 0; i < results.length; ++i) { - - let keys = Object.keys(results[i]) - - for (var j = 0; j < keys.length; ++j) { + self.pool.query( + dataHelp.getSchemaQuery(), + [this.sqlConfig.database], + (err, results) => { + if (err) { + console.log("Cache init failed during database reading"); + console.log(err, results); + cbk(err, results); + } else { + for (var i = 0; i < results.length; ++i) { + let keys = Object.keys(results[i]); - let value = results[i][keys[j]]; + for (var j = 0; j < keys.length; ++j) { + let value = results[i][keys[j]]; - results[i][keys[j].toLowerCase()] = value; + results[i][keys[j].toLowerCase()] = value; - //console.log(value); + //console.log(value); + } } - } - self.iterateToCacheTables(results) - self.iterateToCacheTablePks(results) - self.iterateToCacheTableColumns(results) - self.iterateToCacheTableFks(results) + self.iterateToCacheTables(results); + self.iterateToCacheTablePks(results); + self.iterateToCacheTableColumns(results); + self.iterateToCacheTableFks(results); - // osx mysql server has limitations related to open_tables - self.pool.query('FLUSH TABLES', [], (err, results) => { - cbk(null, null) - }) + // osx mysql server has limitations related to open_tables + self.pool.query("FLUSH TABLES", [], (err, results) => { + cbk(null, null); + }); + } } - }) - + ); } - iterateToCacheTables(schemaResults) { - for (let i = 0; i < schemaResults.length; ++i) { - let schemaRow = schemaResults[i]; - let tableName = schemaRow['table_name']; + let tableName = schemaRow["table_name"]; if (!(tableName in this.metaDb.tables)) { - this.metaDb.tables[tableName] = {} - this.metaDb.tables[tableName]['primaryKeys'] = [] - this.metaDb.tables[tableName]['foreignKeys'] = [] - this.metaDb.tables[tableName]['columns'] = [] - this.metaDb.tables[tableName]['indicies'] = [] - this.metaDb.tables[tableName]['isView'] = schemaRow['isView'] + this.metaDb.tables[tableName] = {}; + this.metaDb.tables[tableName]["primaryKeys"] = []; + this.metaDb.tables[tableName]["foreignKeys"] = []; + this.metaDb.tables[tableName]["columns"] = []; + this.metaDb.tables[tableName]["indicies"] = []; + this.metaDb.tables[tableName]["isView"] = schemaRow["isView"]; } } } iterateToCacheTableColumns(schemaResults) { - for (let i = 0; i < schemaResults.length; ++i) { let schemaRow = schemaResults[i]; - let tableName = schemaRow['table_name']; + let tableName = schemaRow["table_name"]; let col = {}; - col['column_name'] = schemaRow['column_name'] - col['ordinal_position'] = schemaRow['ordinal_position'] - col['column_key'] = schemaRow['column_key'] - col['data_type'] = schemaRow['data_type'] - col['column_type'] = schemaRow['column_type'] - - dataHelp.findOrInsertObjectArrayByKey(col, 'column_name', this.metaDb.tables[tableName]['columns']) - + col["column_name"] = schemaRow["column_name"]; + col["ordinal_position"] = schemaRow["ordinal_position"]; + col["column_key"] = schemaRow["column_key"]; + col["data_type"] = schemaRow["data_type"]; + col["column_type"] = schemaRow["column_type"]; + + dataHelp.findOrInsertObjectArrayByKey( + col, + "column_name", + this.metaDb.tables[tableName]["columns"] + ); } } iterateToCacheTablePks(schemaResults) { - for (let i = 0; i < schemaResults.length; ++i) { let schemaRow = schemaResults[i]; - let tableName = schemaRow['table_name']; - - if (schemaRow['column_key'] === 'PRI') { + let tableName = schemaRow["table_name"]; + if (schemaRow["column_key"] === "PRI") { let pk = {}; - pk['column_name'] = schemaRow['column_name'] - pk['ordinal_position'] = schemaRow['ordinal_position'] - pk['column_key'] = schemaRow['column_key'] - pk['data_type'] = schemaRow['data_type'] - pk['column_type'] = schemaRow['column_type'] - - dataHelp.findOrInsertObjectArrayByKey(pk, 'column_name', this.metaDb.tables[tableName]['primaryKeys']) - + pk["column_name"] = schemaRow["column_name"]; + pk["ordinal_position"] = schemaRow["ordinal_position"]; + pk["column_key"] = schemaRow["column_key"]; + pk["data_type"] = schemaRow["data_type"]; + pk["column_type"] = schemaRow["column_type"]; + + dataHelp.findOrInsertObjectArrayByKey( + pk, + "column_name", + this.metaDb.tables[tableName]["primaryKeys"] + ); } } } iterateToCacheTableFks(schemaResults) { - for (let i = 0; i < schemaResults.length; ++i) { - let schemaRow = schemaResults[i]; - let tableName = schemaRow['table_name']; - - if (schemaRow['referenced_table_name']) { + let tableName = schemaRow["table_name"]; + if (schemaRow["referenced_table_name"]) { let fk = {}; - fk['column_name'] = schemaRow['column_name'] - fk['table_name'] = schemaRow['table_name'] - fk['referenced_table_name'] = schemaRow['referenced_table_name'] - fk['referenced_column_name'] = schemaRow['referenced_column_name'] - fk['data_type'] = schemaRow['data_type'] - fk['column_type'] = schemaRow['column_type'] + fk["column_name"] = schemaRow["column_name"]; + fk["table_name"] = schemaRow["table_name"]; + fk["referenced_table_name"] = schemaRow["referenced_table_name"]; + fk["referenced_column_name"] = schemaRow["referenced_column_name"]; + fk["data_type"] = schemaRow["data_type"]; + fk["column_type"] = schemaRow["column_type"]; - dataHelp.findOrInsertObjectArrayByKey(fk, 'column_name', this.metaDb.tables[tableName]['foreignKeys']) + dataHelp.findOrInsertObjectArrayByKey( + fk, + "column_name", + this.metaDb.tables[tableName]["foreignKeys"] + ); //console.log(fk['referenced_table_name'],fk['referenced_column_name'],tableName, schemaRow['column_name'], this.metaDb.tables[tableName]['foreignKeys'].length) } @@ -156,671 +149,814 @@ class Xsql { /**************** END : Cache functions ****************/ - exec(query, params) { - let _this = this; - return new Promise(function (resolve, reject) { + return new Promise(function(resolve, reject) { //console.log('mysql>', query, params); - _this.pool.query(query, params, function (error, rows, _fields) { + _this.pool.query(query, params, function(error, rows, _fields) { if (error) { - console.log('mysql> ', error); + console.log("mysql> ", error); return reject(error); } return resolve(rows); }); }); - } typeOfColumn(Type) { - //TODO: Im sure there are more types to handle here - const strTypes = ['varchar', 'text', 'char', 'tinytext', 'mediumtext', 'longtext', 'blob', 'mediumblob', 'longblob']; - const intTypes = ['int', 'long', 'smallint', 'mediumint', 'bigint', 'tinyint']; - const flatTypes = ['float', 'double', 'decimal']; - const dateTypes = ['date', 'datetime', 'timestamp', 'time', 'year']; + const strTypes = [ + "varchar", + "text", + "char", + "tinytext", + "mediumtext", + "longtext", + "blob", + "mediumblob", + "longblob" + ]; + const intTypes = [ + "int", + "long", + "smallint", + "mediumint", + "bigint", + "tinyint" + ]; + const flatTypes = ["float", "double", "decimal"]; + const dateTypes = ["date", "datetime", "timestamp", "time", "year"]; if (dataHelp.getType(Type, strTypes)) { - return "string" + return "string"; } else if (dataHelp.getType(Type, intTypes)) { - return "int" + return "int"; } else if (dataHelp.getType(Type, flatTypes)) { - return "float" + return "float"; } else if (dataHelp.getType(Type, dateTypes)) { - return "date" + return "date"; } else { - return "unknown" + return "unknown"; } - } isTypeOfColumnNumber(Type) { - //console.log(Type, this.typeOfColumn(Type)); - return ('int' === this.typeOfColumn(Type) || 'float' === this.typeOfColumn(Type)) + return ( + "int" === this.typeOfColumn(Type) || "float" === this.typeOfColumn(Type) + ); } getLimitClause(reqParams) { - //defaults reqParams._index = 0; reqParams._len = 20; - if('_size' in reqParams) { + if ("_size" in reqParams) { if (parseInt(reqParams._size) > 0 && parseInt(reqParams._size) <= 100) { - reqParams._len = parseInt(reqParams._size) + reqParams._len = parseInt(reqParams._size); } else if (parseInt(reqParams._size) > 100) { - reqParams._len = 100 + reqParams._len = 100; } } - - if ('_p' in reqParams && parseInt(reqParams._p) > 0) { + if ("_p" in reqParams && parseInt(reqParams._p) > 0) { reqParams._index = parseInt(reqParams._p) * reqParams._len; } //console.log(reqParams._index, reqParams._len); - return [reqParams._index, reqParams._len] - + return [reqParams._index, reqParams._len]; } prepareBulkInsert(tableName, objectArray, queryParamsObj) { - if (tableName in this.metaDb.tables && objectArray) { - let insObj = objectArray[0]; // goal => insert into ?? (?,?..?) values ? [tablName, col1,col2...coln,[[ObjValues_1],[ObjValues_2],...[ObjValues_N]] - queryParamsObj.query = ' INSERT INTO ?? ( ' - queryParamsObj.params.push(tableName) + queryParamsObj.query = " INSERT INTO ?? ( "; + queryParamsObj.params.push(tableName); let cols = []; let colPresent = false; /**************** START : prepare column names to be inserted ****************/ // iterate over all column in table and have only ones existing in objects to be inserted - for (var i = 0; i < this.metaDb.tables[tableName]['columns'].length; ++i) { - - let colName = this.metaDb.tables[tableName]['columns'][i]['column_name'] - + for ( + var i = 0; + i < this.metaDb.tables[tableName]["columns"].length; + ++i + ) { + let colName = this.metaDb.tables[tableName]["columns"][i][ + "column_name" + ]; if (colName in insObj) { - if (colPresent) { - queryParamsObj.query += ',' + queryParamsObj.query += ","; } - queryParamsObj.query += colName + queryParamsObj.query += colName; colPresent = true; - } - cols.push(colName) + cols.push(colName); //console.log('> > ', queryParamsObj.query); - } - queryParamsObj.query += ' ) values ?' + queryParamsObj.query += " ) values ?"; /**************** END : prepare column names to be inserted ****************/ - /**************** START : prepare value object in prepared statement ****************/ // iterate over sent object array - let arrOfArr = [] + let arrOfArr = []; for (var i = 0; i < objectArray.length; ++i) { - let arrValues = [] + let arrValues = []; for (var j = 0; j < cols.length; ++j) { if (cols[j] in objectArray[i]) - arrValues.push(objectArray[i][cols[j]]) + arrValues.push(objectArray[i][cols[j]]); } arrOfArr.push(arrValues); } - queryParamsObj.params.push(arrOfArr) + queryParamsObj.params.push(arrOfArr); /**************** END : prepare value object in prepared statement ****************/ } } - getGroupByClause(_groupby, tableName, queryParamsObj) { - if (_groupby) { - queryParamsObj.query += ' group by ' + _groupby + ' ' - return _groupby + queryParamsObj.query += " group by " + _groupby + " "; + return _groupby; } - } getHavingClause(_having, tableName, queryParamsObj) { - if (_having) { - - let whereClauseObj = whereHelp.getConditionClause(_having, 'having') + let whereClauseObj = whereHelp.getConditionClause(_having, "having"); if (whereClauseObj.err === 0) { - queryParamsObj.query = queryParamsObj.query + ' having ' + whereClauseObj.query; - queryParamsObj.params = queryParamsObj.params.concat(whereClauseObj.params) + queryParamsObj.query = + queryParamsObj.query + " having " + whereClauseObj.query; + queryParamsObj.params = queryParamsObj.params.concat( + whereClauseObj.params + ); } //console.log('> > > after where clause filling up:', queryParamsObj.query, queryParamsObj.params); } - } getWhereClause(queryparams, tableName, queryParamsObj, appendToWhere) { - if (queryparams) { - - let whereClauseObj = whereHelp.getConditionClause(queryparams) + let whereClauseObj = whereHelp.getConditionClause(queryparams); if (whereClauseObj.err === 0) { - queryParamsObj.query = queryParamsObj.query + appendToWhere + whereClauseObj.query; - queryParamsObj.params = queryParamsObj.params.concat(whereClauseObj.params) + queryParamsObj.query = + queryParamsObj.query + appendToWhere + whereClauseObj.query; + queryParamsObj.params = queryParamsObj.params.concat( + whereClauseObj.params + ); } - } - } - getOrderByClause(queryparams, tableName, queryParamsObj) { - if (queryparams._sort) { + queryParamsObj.query += " ORDER BY "; - queryParamsObj.query += ' ORDER BY ' - - let orderByCols = queryparams._sort.split(',') + let orderByCols = queryparams._sort.split(","); for (let i = 0; i < orderByCols.length; ++i) { if (i) { - queryParamsObj.query += ', ' + queryParamsObj.query += ", "; } - if (orderByCols[i][0] === '-') { + if (orderByCols[i][0] === "-") { let len = orderByCols[i].length; - queryParamsObj.query += ' ?? DESC' - queryParamsObj.params.push(orderByCols[i].substring(1, len)) + queryParamsObj.query += " ?? DESC"; + queryParamsObj.params.push(orderByCols[i].substring(1, len)); } else { - queryParamsObj.query += ' ?? ASC' - queryParamsObj.params.push(orderByCols[i]) + queryParamsObj.query += " ?? ASC"; + queryParamsObj.params.push(orderByCols[i]); } } } - } getColumnsForSelectStmtWithGrpBy(reqQueryParams, tableName, queryParamsObj) { - - let grpByCols = reqQueryParams._groupby.split(','); + let grpByCols = reqQueryParams._groupby.split(","); for (var i = 0; i < grpByCols.length; ++i) { if (i) { - queryParamsObj.query += ',' + queryParamsObj.query += ","; } - queryParamsObj.query += ' ??' - queryParamsObj.params.push(grpByCols[i]) + queryParamsObj.query += " ??"; + queryParamsObj.params.push(grpByCols[i]); } - queryParamsObj.query += ',count(1) as _count ' - + queryParamsObj.query += ",count(1) as _count "; } getColumnsForSelectStmt(tableName, reqQueryParams, queryParamsObj) { - let table = this.metaDb.tables[tableName]; let cols = []; let _fieldsInQuery = []; let removeFieldsObj = {}; // populate _fields array from query params - if ('_fields' in reqQueryParams) { - _fieldsInQuery = reqQueryParams['_fields'].split(',') + if ("_fields" in reqQueryParams) { + _fieldsInQuery = reqQueryParams["_fields"].split(","); } else { - queryParamsObj.query += ' * ' + queryParamsObj.query += " * "; return " * "; } - // get column name in _fields and mark column name which start with '-' for (let i = 0; i < _fieldsInQuery.length; ++i) { - if (_fieldsInQuery[i][0] === '-') { - removeFieldsObj[_fieldsInQuery[i].substring(1, _fieldsInQuery[i].length)] = 1; + if (_fieldsInQuery[i][0] === "-") { + removeFieldsObj[ + _fieldsInQuery[i].substring(1, _fieldsInQuery[i].length) + ] = 1; } else { - cols.push(_fieldsInQuery[i]) + cols.push(_fieldsInQuery[i]); } } if (!cols.length) { // for each column in table - add only which are not in removeFieldsObj - for (let i = 0; i < table['columns'].length; ++i) { - if (!(table['columns'][i]['column_name'] in removeFieldsObj)) { - cols.push(table['columns'][i]['column_name']) + for (let i = 0; i < table["columns"].length; ++i) { + if (!(table["columns"][i]["column_name"] in removeFieldsObj)) { + cols.push(table["columns"][i]["column_name"]); } } } else { - - cols = this.removeUnknownColumns(cols, tableName) - + cols = this.removeUnknownColumns(cols, tableName); } for (var i = 0; i < cols.length; ++i) { if (i) { - queryParamsObj.query += ',' + queryParamsObj.query += ","; } - queryParamsObj.query += '??' - queryParamsObj.params.push(cols[i]) + queryParamsObj.query += "??"; + queryParamsObj.params.push(cols[i]); } - return cols.join(',') - + return cols.join(","); } - removeUnknownColumns(inputColumns, tableName) { - let cols = inputColumns; - let unknown_cols_in_input = [] + let unknown_cols_in_input = []; let shadowCols = []; - let tableColumns = this.metaDb.tables[tableName]['columns'] + let tableColumns = this.metaDb.tables[tableName]["columns"]; // find unknown fields if any for (var j = 0; j < cols.length; ++j) { - let found = 0; for (var i = 0; i < tableColumns.length; ++i) { - if (tableColumns[i]['column_name'] === cols[j]) { + if (tableColumns[i]["column_name"] === cols[j]) { found = 1; break; } } if (!found) { - unknown_cols_in_input.push(j) + unknown_cols_in_input.push(j); } - } // if there are unknown fields - remove and ignore 'em if (unknown_cols_in_input.length) { - for (var i = 0; i < cols.length; ++i) { if (unknown_cols_in_input.indexOf(i) === -1) { - shadowCols.push(cols[i]) + shadowCols.push(cols[i]); } } cols = []; cols = shadowCols; - } return cols; - } getPrimaryKeyName(tableName) { - let pk = null + let pk = null; if (tableName in this.metaDb.tables) { - pk = this.metaDb.tables[tableName].primaryKeys[0]['column_name'] + pk = this.metaDb.tables[tableName].primaryKeys[0]["column_name"]; } - return pk + return pk; } getPrimaryKeyWhereClause(tableName, pksValues) { - - let whereClause = ''; - let whereCol = ''; - let whereValue = ''; - let pks = [] + let whereClause = ""; + let whereCol = ""; + let whereValue = ""; + let pks = []; if (tableName in this.metaDb.tables) { pks = this.metaDb.tables[tableName].primaryKeys; } else { - return null + return null; } // number of primary keys in table and one sent should be same if (pksValues.length !== pks.length) { - return null + return null; } // get a where clause out of the above columnNames and their values for (let i = 0; i < pks.length; ++i) { - let type = dataHelp.getColumnType(pks[i]); - whereCol = pks[i]['column_name'] + whereCol = pks[i]["column_name"]; - if (type === 'string') { - whereValue = mysql.escape(pksValues[i]) - } else if (type === 'int') { - whereValue = parseInt(pksValues[i]) - } else if (type === 'float') { - whereValue = parseFloat(pksValues[i]) - } else if (type === 'date') { - whereValue = Date(pksValues[i]) + if (type === "string") { + whereValue = mysql.escape(pksValues[i]); + } else if (type === "int") { + whereValue = parseInt(pksValues[i]); + } else if (type === "float") { + whereValue = parseFloat(pksValues[i]); + } else if (type === "date") { + whereValue = Date(pksValues[i]); } else { - console.error(pks[i]) - assert(false, 'Unhandled type of primary key') + console.error(pks[i]); + assert(false, "Unhandled type of primary key"); } if (i) { - whereClause += ' and ' + whereClause += " and "; } - whereClause += whereCol + ' = ' + whereValue; - + whereClause += whereCol + " = " + whereValue; } return whereClause; - } getForeignKeyWhereClause(parentTable, parentId, childTable) { - - let whereValue = ''; + let whereValue = ""; //get all foreign keys of child table let fks = this.metaDb.tables[childTable].foreignKeys; - let fk = dataHelp.findObjectInArrayByKey('referenced_table_name', parentTable, fks); - let whereCol = fk['column_name'] + let fk = dataHelp.findObjectInArrayByKey( + "referenced_table_name", + parentTable, + fks + ); + let whereCol = fk["column_name"]; let colType = dataHelp.getColumnType(fk); - if (colType === 'string') { - whereValue = mysql.escape(parentId) - } else if (colType === 'int') { - whereValue = mysql.escape(parseInt(parentId)) - } else if (colType === 'float') { - whereValue = mysql.escape(parseFloat(parentId)) - } else if (colType === 'date') { - whereValue = mysql.escape(Date(parentId)) + if (colType === "string") { + whereValue = mysql.escape(parentId); + } else if (colType === "int") { + whereValue = mysql.escape(parseInt(parentId)); + } else if (colType === "float") { + whereValue = mysql.escape(parseFloat(parentId)); + } else if (colType === "date") { + whereValue = mysql.escape(Date(parentId)); } else { - console.error(pks[i]) - assert(false, 'Unhandled column type in foreign key handling') + console.error(pks[i]); + assert(false, "Unhandled column type in foreign key handling"); } - return whereCol + ' = ' + whereValue; - + return whereCol + " = " + whereValue; } prepareRoute(internal, httpType, apiPrefix, urlRoute, routeType) { - let route = {}; - route['httpType'] = httpType; - route['routeUrl'] = apiPrefix + urlRoute; + route["httpType"] = httpType; + route["routeUrl"] = apiPrefix + urlRoute; if (internal) { - route['routeType'] = routeType; + route["routeType"] = routeType; } return route; - } - getSchemaRoutes(internal, apiPrefix) { - let schemaRoutes = []; for (var tableName in this.metaDb.tables) { - if (tableName in this.sqlConfig.ignoreTables) { //console.log('ignore table', tableName); } else { - - let routes = [] - let tableObj = {} + let routes = []; + let tableObj = {}; let table = this.metaDb.tables[tableName]; - let isView = this.metaDb.tables[tableName]['isView']; + let isView = this.metaDb.tables[tableName]["isView"]; - tableObj['resource'] = tableName; + tableObj["resource"] = tableName; // order of routes is important for express routing - DO NOT CHANGE ORDER - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/describe', 'describe')) - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/count', 'count')) - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/groupby', 'groupby')) - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/distinct', 'distinct')) - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/ugroupby', 'ugroupby')) - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/chart', 'chart')) - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/aggregate', 'aggregate')) - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/findOne', 'findOne')) - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/autoChart', 'autoChart')) + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/describe", + "describe" + ) + ); + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/count", + "count" + ) + ); + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/groupby", + "groupby" + ) + ); + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/distinct", + "distinct" + ) + ); + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/ugroupby", + "ugroupby" + ) + ); + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/chart", + "chart" + ) + ); + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/aggregate", + "aggregate" + ) + ); + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/findOne", + "findOne" + ) + ); + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/autoChart", + "autoChart" + ) + ); if (!isView && !this.sqlConfig.readOnly) { - routes.push(this.prepareRoute(internal, 'post', apiPrefix, tableName, 'create')) + routes.push( + this.prepareRoute(internal, "post", apiPrefix, tableName, "create") + ); } - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName, 'list')) + routes.push( + this.prepareRoute(internal, "get", apiPrefix, tableName, "list") + ); if (!isView && !this.sqlConfig.readOnly) { - routes.push(this.prepareRoute(internal, 'post', apiPrefix, tableName + '/bulk', 'bulkInsert')) - routes.push(this.prepareRoute(internal, 'delete', apiPrefix, tableName + '/bulk', 'bulkDelete')) + routes.push( + this.prepareRoute( + internal, + "post", + apiPrefix, + tableName + "/bulk", + "bulkInsert" + ) + ); + routes.push( + this.prepareRoute( + internal, + "delete", + apiPrefix, + tableName + "/bulk", + "bulkDelete" + ) + ); } - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/bulk', 'bulkRead')) + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/bulk", + "bulkRead" + ) + ); if (!isView && !this.sqlConfig.readOnly) { - routes.push(this.prepareRoute(internal, 'put', apiPrefix, tableName, 'update')) - routes.push(this.prepareRoute(internal, 'patch', apiPrefix, tableName + '/:id', 'patch')) - routes.push(this.prepareRoute(internal, 'delete', apiPrefix, tableName + '/:id', 'delete')) + routes.push( + this.prepareRoute(internal, "put", apiPrefix, tableName, "update") + ); + routes.push( + this.prepareRoute( + internal, + "patch", + apiPrefix, + tableName + "/:id", + "patch" + ) + ); + routes.push( + this.prepareRoute( + internal, + "delete", + apiPrefix, + tableName + "/:id", + "delete" + ) + ); } - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/:id', 'read')) - routes.push(this.prepareRoute(internal, 'get', apiPrefix, tableName + '/:id/exists', 'exists')) - - for (var j = 0; j < table['foreignKeys'].length; ++j) { - let fk = table['foreignKeys'][j] - - if (fk['referenced_table_name'] in this.sqlConfig.ignoreTables) { + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/:id", + "read" + ) + ); + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + tableName + "/:id/exists", + "exists" + ) + ); + + for (var j = 0; j < table["foreignKeys"].length; ++j) { + let fk = table["foreignKeys"][j]; + + if (fk["referenced_table_name"] in this.sqlConfig.ignoreTables) { //console.log('ignore table',fk['referenced_table_name']); } else { - routes.push(this.prepareRoute(internal, 'get', apiPrefix, fk['referenced_table_name'] + '/:id/' + fk['table_name'], 'relational')) + routes.push( + this.prepareRoute( + internal, + "get", + apiPrefix, + fk["referenced_table_name"] + "/:id/" + fk["table_name"], + "relational" + ) + ); } - } - tableObj['routes'] = routes; + tableObj["routes"] = routes; schemaRoutes.push(tableObj); - } } return schemaRoutes; - } getJoinType(joinInQueryParams) { - //console.log('joinInQueryParams',joinInQueryParams); switch (joinInQueryParams) { - - case '_lj': - return ' left join ' + case "_lj": + return " left join "; break; - case '_rj': - return ' right join ' + case "_rj": + return " right join "; break; // case '_fj': // return ' full join ' // break; - case '_ij': - return ' inner join ' + case "_ij": + return " inner join "; break; - case '_j': - return ' join ' + case "_j": + return " join "; break; - } - return ' join ' - + return " join "; } - globalRoutesPrint(apiPrefix) { + let r = []; - let r = [] - - r.push(apiPrefix + "tables") - r.push(apiPrefix + "xjoin") + r.push(apiPrefix + "tables"); + r.push(apiPrefix + "xjoin"); if (this.sqlConfig.dynamic) { - r.push(apiPrefix + "dynamic") - r.push("/upload") - r.push("/uploads") - r.push("/download") + r.push(apiPrefix + "dynamic"); + r.push("/upload"); + r.push("/uploads"); + r.push("/download"); } - return r; - } - getChartQueryAndParamsFromStepPair(tableName, columnName, stepArray, isRange = false) { + getChartQueryAndParamsFromStepPair( + tableName, + columnName, + stepArray, + isRange = false + ) { + let obj = {}; - let obj = {} - - obj.query = '' - obj.params = [] + obj.query = ""; + obj.params = []; //console.log('getChartQueryAndParamsFromStepArray',isRange); //select ? as ??, count(*) as _count from ?? where ?? between ? and ? - if (stepArray.length && stepArray.length >= 2 && stepArray.length % 2 === 0) { - - for (let i = 0; i < stepArray.length && stepArray.length >= 2; i = i + 2) { - + if ( + stepArray.length && + stepArray.length >= 2 && + stepArray.length % 2 === 0 + ) { + for ( + let i = 0; + i < stepArray.length && stepArray.length >= 2; + i = i + 2 + ) { obj.query = obj.query + dataHelp.getChartQuery(); if (i + 2 < stepArray.length) { - obj.query = obj.query + ' union ' + obj.query = obj.query + " union "; } - obj.params.push((stepArray[i]) + ' to ' + stepArray[i + 1]) - obj.params.push(columnName) - obj.params.push(tableName) - obj.params.push(columnName) - obj.params.push(stepArray[i]) - obj.params.push(stepArray[i + 1]) - + obj.params.push(stepArray[i] + " to " + stepArray[i + 1]); + obj.params.push(columnName); + obj.params.push(tableName); + obj.params.push(columnName); + obj.params.push(stepArray[i]); + obj.params.push(stepArray[i + 1]); } - } //console.log('step spread query', obj); return obj; - } + getChartQueryAndParamsFromStepArray( + tableName, + columnName, + stepArray, + isRange = false + ) { + let obj = {}; - getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray, isRange = false) { - - let obj = {} - - obj.query = '' - obj.params = [] + obj.query = ""; + obj.params = []; //console.log('getChartQueryAndParamsFromStepArray',isRange); if (stepArray.length && stepArray.length >= 2) { - for (let i = 0; i < stepArray.length - 1; i = i + 1) { - obj.query = obj.query + dataHelp.getChartQuery(); if (i + 2 < stepArray.length) { - obj.query = obj.query + ' union ' + obj.query = obj.query + " union "; } if (i && isRange === false) { - stepArray[i] = stepArray[i] + 1 + stepArray[i] = stepArray[i] + 1; } if (isRange === false) { - obj.params.push((stepArray[i]) + ' to ' + stepArray[i + 1]) + obj.params.push(stepArray[i] + " to " + stepArray[i + 1]); } else { - obj.params.push((stepArray[0]) + ' to ' + stepArray[i + 1]) + obj.params.push(stepArray[0] + " to " + stepArray[i + 1]); } - obj.params.push(columnName) - obj.params.push(tableName) - obj.params.push(columnName) + obj.params.push(columnName); + obj.params.push(tableName); + obj.params.push(columnName); if (isRange === false) { - obj.params.push(stepArray[i]) - obj.params.push(stepArray[i + 1]) + obj.params.push(stepArray[i]); + obj.params.push(stepArray[i + 1]); } else { - obj.params.push(stepArray[0]) - obj.params.push(stepArray[i + 1]) + obj.params.push(stepArray[0]); + obj.params.push(stepArray[i + 1]); } - } - } //console.log('step spread query', obj); return obj; - } - - getChartQueryAndParamsFromMinMaxStddev(tableName, columnName, min, max, stddev, isRange = false) { - - let stepArray = dataHelp.getStepArray(min, max, stddev) + getChartQueryAndParamsFromMinMaxStddev( + tableName, + columnName, + min, + max, + stddev, + isRange = false + ) { + let stepArray = dataHelp.getStepArray(min, max, stddev); //console.log('steparray', stepArray); - let obj = this.getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray, isRange) + let obj = this.getChartQueryAndParamsFromStepArray( + tableName, + columnName, + stepArray, + isRange + ); //console.log('steparray', obj); - return obj - + return obj; } - getChartQueryAndParamsFromMinMaxStep(tableName, columnName, min, max, step, isRange = false) { - - let stepArray = dataHelp.getStepArraySimple(min, max, step) + getChartQueryAndParamsFromMinMaxStep( + tableName, + columnName, + min, + max, + step, + isRange = false + ) { + let stepArray = dataHelp.getStepArraySimple(min, max, step); //console.log('steparray', stepArray); - let obj = this.getChartQueryAndParamsFromStepArray(tableName, columnName, stepArray, isRange) + let obj = this.getChartQueryAndParamsFromStepArray( + tableName, + columnName, + stepArray, + isRange + ); //console.log('steparray', obj); - return obj - + return obj; } _getGrpByHavingOrderBy(req, tableName, queryParamsObj, listType) { - /**************** add group by ****************/ - this.getGroupByClause(req.query._groupby, req.app.locals._tableName, queryParamsObj); + this.getGroupByClause( + req.query._groupby, + req.app.locals._tableName, + queryParamsObj + ); /**************** add having ****************/ - this.getHavingClause(req.query._having, req.app.locals._tableName, queryParamsObj); + this.getHavingClause( + req.query._having, + req.app.locals._tableName, + queryParamsObj + ); /**************** add order clause ****************/ this.getOrderByClause(req.query, req.app.locals._tableName, queryParamsObj); /**************** add limit clause ****************/ - if (listType === 2) { //nested - queryParamsObj.query += ' limit 1 ' + if (listType === 2) { + //nested + queryParamsObj.query += " limit 1 "; } else { - queryParamsObj.query += ' limit ?,? ' - queryParamsObj.params = queryParamsObj.params.concat(this.getLimitClause(req.query)); + queryParamsObj.query += " limit ?,? "; + queryParamsObj.params = queryParamsObj.params.concat( + this.getLimitClause(req.query) + ); } - } - /** * * @param req @@ -831,88 +967,110 @@ class Xsql { * Updates query, params for query of type listType */ prepareListQuery(req, res, queryParamsObj, listType = 0) { - - queryParamsObj.query = 'select '; + queryParamsObj.query = "select "; queryParamsObj.params = []; - if (listType === 4) { //list type distinct - queryParamsObj.query += ' distinct ' + if (listType === 4) { + //list type distinct + queryParamsObj.query += " distinct "; } /**************** select columns ****************/ if (req.query._groupby) { - this.getColumnsForSelectStmtWithGrpBy(req.query, req.app.locals._tableName, queryParamsObj); + this.getColumnsForSelectStmtWithGrpBy( + req.query, + req.app.locals._tableName, + queryParamsObj + ); } else { - this.getColumnsForSelectStmt(req.app.locals._tableName, req.query, queryParamsObj); + this.getColumnsForSelectStmt( + req.app.locals._tableName, + req.query, + queryParamsObj + ); } /**************** add tableName ****************/ - queryParamsObj.query += ' from ?? '; + queryParamsObj.query += " from ?? "; - if (listType === 1) { //nested list + if (listType === 1) { + //nested list req.app.locals._tableName = req.app.locals._childTable; queryParamsObj.params.push(req.app.locals._childTable); - queryParamsObj.query += ' where '; + queryParamsObj.query += " where "; /**************** add where foreign key ****************/ - let whereClause = this.getForeignKeyWhereClause(req.app.locals._parentTable, + let whereClause = this.getForeignKeyWhereClause( + req.app.locals._parentTable, req.params.id, - req.app.locals._childTable); + req.app.locals._childTable + ); if (!whereClause) { return res.status(400).send({ - error: "Table is made of composite primary keys - all keys were not in input" - }) + error: + "Table is made of composite primary keys - all keys were not in input" + }); } queryParamsObj.query += whereClause; - this.getWhereClause(req.query._where, req.app.locals._tableName, queryParamsObj, ' and '); - - } else if (listType === 3) { //bulkRead + this.getWhereClause( + req.query._where, + req.app.locals._tableName, + queryParamsObj, + " and " + ); + } else if (listType === 3) { + //bulkRead // select * from table where pk in (ids) and whereConditions queryParamsObj.params.push(req.app.locals._tableName); - queryParamsObj.query += ' where ?? in '; - queryParamsObj.params.push(this.getPrimaryKeyName(req.app.locals._tableName)); + queryParamsObj.query += " where ?? in "; + queryParamsObj.params.push( + this.getPrimaryKeyName(req.app.locals._tableName) + ); - queryParamsObj.query += '(' + queryParamsObj.query += "("; if (req.query && req.query._ids) { - let ids = req.query._ids.split(',') + let ids = req.query._ids.split(","); for (var i = 0; i < ids.length; ++i) { if (i) { - queryParamsObj.query += ',' + queryParamsObj.query += ","; } - queryParamsObj.query += '?' - queryParamsObj.params.push(ids[i]) + queryParamsObj.query += "?"; + queryParamsObj.params.push(ids[i]); } } - queryParamsObj.query += ') ' - this.getWhereClause(req.query._where, req.app.locals._tableName, queryParamsObj, ' and '); - + queryParamsObj.query += ") "; + this.getWhereClause( + req.query._where, + req.app.locals._tableName, + queryParamsObj, + " and " + ); } else { - queryParamsObj.params.push(req.app.locals._tableName); /**************** add where clause ****************/ - this.getWhereClause(req.query._where, req.app.locals._tableName, queryParamsObj, ' where '); - + this.getWhereClause( + req.query._where, + req.app.locals._tableName, + queryParamsObj, + " where " + ); } - this._getGrpByHavingOrderBy(req, req.app.locals._tableName, queryParamsObj) - + this._getGrpByHavingOrderBy(req, req.app.locals._tableName, queryParamsObj); //console.log(queryParamsObj.query, queryParamsObj.params); } - _joinTableNames(isSecondJoin, joinTables, index, queryParamsObj) { - if (isSecondJoin) { - /** * in second join - there will be ONE table and an ON condition * if clause deals with this @@ -920,79 +1078,81 @@ class Xsql { */ // add : join / left join / right join / full join / inner join - queryParamsObj.query += this.getJoinType(joinTables[index]) - queryParamsObj.query += ' ?? as ?? ' + queryParamsObj.query += this.getJoinType(joinTables[index]); + queryParamsObj.query += " ?? as ?? "; // eg: tbl.tableName - let tableNameAndAs = joinTables[index + 1].split('.') - - if (tableNameAndAs.length === 2 && !(tableNameAndAs[1] in this.sqlConfig.ignoreTables)) { - queryParamsObj.params.push(tableNameAndAs[1]) - queryParamsObj.params.push(tableNameAndAs[0]) + let tableNameAndAs = joinTables[index + 1].split("."); + + if ( + tableNameAndAs.length === 2 && + !(tableNameAndAs[1] in this.sqlConfig.ignoreTables) + ) { + queryParamsObj.params.push(tableNameAndAs[1]); + queryParamsObj.params.push(tableNameAndAs[0]); } else { - queryParamsObj.grammarErr = 1 - console.log('there was no dot for tableName ', joinTables[index + 1]); + queryParamsObj.grammarErr = 1; + console.log("there was no dot for tableName ", joinTables[index + 1]); } - } else { - /** * in first join - there will be TWO tables and an ON condition * else clause deals with this */ - // first table - queryParamsObj.query += ' ?? as ?? ' + queryParamsObj.query += " ?? as ?? "; // add : join / left join / right join / full join / inner join - queryParamsObj.query += this.getJoinType(joinTables[index + 1]) + queryParamsObj.query += this.getJoinType(joinTables[index + 1]); // second table - queryParamsObj.query += ' ?? as ?? ' - - let tableNameAndAs = joinTables[index].split('.') - if (tableNameAndAs.length === 2 && !(tableNameAndAs[1] in this.sqlConfig.ignoreTables)) { - queryParamsObj.params.push(tableNameAndAs[1]) - queryParamsObj.params.push(tableNameAndAs[0]) + queryParamsObj.query += " ?? as ?? "; + + let tableNameAndAs = joinTables[index].split("."); + if ( + tableNameAndAs.length === 2 && + !(tableNameAndAs[1] in this.sqlConfig.ignoreTables) + ) { + queryParamsObj.params.push(tableNameAndAs[1]); + queryParamsObj.params.push(tableNameAndAs[0]); } else { - queryParamsObj.grammarErr = 1 - console.log('there was no dot for tableName ', joinTables[index]); + queryParamsObj.grammarErr = 1; + console.log("there was no dot for tableName ", joinTables[index]); } - tableNameAndAs = [] - tableNameAndAs = joinTables[index + 2].split('.') - if (tableNameAndAs.length === 2 && !(tableNameAndAs[1] in this.sqlConfig.ignoreTables)) { - queryParamsObj.params.push(tableNameAndAs[1]) - queryParamsObj.params.push(tableNameAndAs[0]) + tableNameAndAs = []; + tableNameAndAs = joinTables[index + 2].split("."); + if ( + tableNameAndAs.length === 2 && + !(tableNameAndAs[1] in this.sqlConfig.ignoreTables) + ) { + queryParamsObj.params.push(tableNameAndAs[1]); + queryParamsObj.params.push(tableNameAndAs[0]); } else { - queryParamsObj.grammarErr = 1 - console.log('there was no dot for tableName ', joinTables[index]); + queryParamsObj.grammarErr = 1; + console.log("there was no dot for tableName ", joinTables[index]); } } - } prepareJoinQuery(req, res, queryParamsObj) { - - queryParamsObj.query = 'SELECT ' + queryParamsObj.query = "SELECT "; queryParamsObj.grammarErr = 0; while (1) { - /**************** START : get fields ****************/ if (req.query._fields) { - - let fields = req.query._fields.split(',') + let fields = req.query._fields.split(","); // from _fields to - ??, ??, ?? [col1,col2,col3] - for (var i = 0; i < fields.length && (!queryParamsObj.grammarErr); ++i) { + for (var i = 0; i < fields.length && !queryParamsObj.grammarErr; ++i) { if (i) { - queryParamsObj.query += ',' + queryParamsObj.query += ","; } - queryParamsObj.query += ' ?? ' - queryParamsObj.params.push(fields[i]) - let aliases = fields[i].split('.'); + queryParamsObj.query += " ?? "; + queryParamsObj.params.push(fields[i]); + let aliases = fields[i].split("."); if (aliases.length === 2) { - queryParamsObj.query += 'as ' + aliases[0] + '_' + aliases[1]; + queryParamsObj.query += "as " + aliases[0] + "_" + aliases[1]; //console.log(queryParamsObj.query); } else { queryParamsObj.grammarErr = 1; @@ -1002,17 +1162,16 @@ class Xsql { queryParamsObj.grammarErr = 1; } - queryParamsObj.query += ' from ' + queryParamsObj.query += " from "; - if(queryParamsObj.grammarErr){ + if (queryParamsObj.grammarErr) { break; } /**************** END : get fields ****************/ - /**************** START : get join + on ****************/ - let joinTables = req.query._join.split(',') + let joinTables = req.query._join.split(","); if (joinTables.length < 3) { //console.log('grammar error ', joinTables.length); queryParamsObj.grammarErr = 1; @@ -1023,27 +1182,32 @@ class Xsql { let onCondnCount = 0; - for (let i = 0; i < joinTables.length - 1 && queryParamsObj.grammarErr === 0; i = i + 2) { - + for ( + let i = 0; + i < joinTables.length - 1 && queryParamsObj.grammarErr === 0; + i = i + 2 + ) { onCondnCount++; - this._joinTableNames(i, joinTables, i, queryParamsObj) + this._joinTableNames(i, joinTables, i, queryParamsObj); if (queryParamsObj.grammarErr) { - console.log('failed at _joinTableNames', queryParamsObj); + console.log("failed at _joinTableNames", queryParamsObj); break; } //console.log('after join tables', queryParamsObj); - let onCondn = '_on' + (onCondnCount) - let onCondnObj = {} + let onCondn = "_on" + onCondnCount; + let onCondnObj = {}; if (onCondn in req.query) { //console.log(onCondn, req.query[onCondn]); - onCondnObj = whereHelp.getConditionClause(req.query[onCondn], ' on ') + onCondnObj = whereHelp.getConditionClause(req.query[onCondn], " on "); //console.log('onCondnObj', onCondnObj); - queryParamsObj.query += ' on ' + onCondnObj.query - queryParamsObj.params = queryParamsObj.params.concat(onCondnObj.params) + queryParamsObj.query += " on " + onCondnObj.query; + queryParamsObj.params = queryParamsObj.params.concat( + onCondnObj.params + ); } else { queryParamsObj.grammarErr = 1; //console.log('No on condition: ', onCondn); @@ -1051,38 +1215,35 @@ class Xsql { } if (i === 0) { - i = i + 1 + i = i + 1; } } /**************** END : get join + on ****************/ - if(queryParamsObj.grammarErr){ + if (queryParamsObj.grammarErr) { break; } else { - this.getWhereClause(req.query._where, ' ignore ', queryParamsObj, ' where '); - this._getGrpByHavingOrderBy(req, 'ignore', queryParamsObj, 5) + this.getWhereClause( + req.query._where, + " ignore ", + queryParamsObj, + " where " + ); + this._getGrpByHavingOrderBy(req, "ignore", queryParamsObj, 5); //console.log('after where',queryParamsObj); } break; - } - if (queryParamsObj.grammarErr) { - queryParamsObj.query = '' - queryParamsObj.params = [] + queryParamsObj.query = ""; + queryParamsObj.params = []; } - return queryParamsObj; } - - } - //expose class module.exports = Xsql; - - diff --git a/package-lock.json b/package-lock.json index e0721dd658..7f537a03a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -176,6 +176,12 @@ "typedarray": "^0.0.6" } }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, "content-disposition": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", @@ -231,6 +237,15 @@ "ms": "2.0.0" } }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -285,6 +300,16 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -295,6 +320,40 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -306,6 +365,85 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "eslint-config-airbnb-base": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz", + "integrity": "sha512-XWwQtf3U3zIoKO1BbHh6aUhJZQweOwSt4c2JrPDg9FP3Ltv3+YfEv7jIDB8275tVnO/qOHbfuYg3kzw6Je7uWw==", + "dev": true, + "requires": { + "eslint-restricted-globals": "^0.1.1", + "object.assign": "^4.1.0", + "object.entries": "^1.0.4" + } + }, + "eslint-config-prettier": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-4.1.0.tgz", + "integrity": "sha512-zILwX9/Ocz4SV2vX7ox85AsrAgXV3f2o2gpIicdMIOra48WYqgUnWNH/cR/iHtmD2Vb3dLSC3LiEJnS05Gkw7w==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + } + }, + "eslint-module-utils": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz", + "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^2.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", + "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", + "dev": true, + "requires": { + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.3.0", + "has": "^1.0.3", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "read-pkg-up": "^2.0.0", + "resolve": "^1.9.0" + } + }, + "eslint-plugin-prettier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz", + "integrity": "sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-restricted-globals": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", + "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -354,6 +492,12 @@ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "finalhandler": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", @@ -368,6 +512,15 @@ "unpipe": "~1.0.0" } }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, "form-data": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", @@ -401,6 +554,18 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -415,24 +580,51 @@ "path-is-absolute": "^1.0.0" } }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, "http-errors": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", @@ -476,11 +668,75 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, "log": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/log/-/log-1.4.0.tgz", @@ -631,11 +887,53 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, "object-assign": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" }, + "object-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", + "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -658,22 +956,100 @@ "wrappy": "1" } }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -709,6 +1085,27 @@ "unpipe": "1.0.0" } }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", @@ -723,11 +1120,26 @@ "util-deprecate": "~1.0.1" } }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + }, "send": { "version": "0.16.1", "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", @@ -827,6 +1239,38 @@ "nan": ">=2.5.1" } }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", + "dev": true + }, "sqlstring": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.0.tgz", @@ -850,6 +1294,12 @@ "safe-buffer": "~5.1.0" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "superagent": { "version": "3.6.3", "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.6.3.tgz", @@ -942,6 +1392,16 @@ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index 234a90f7cd..47a06d2844 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,10 @@ "mysql": "^2.15.0" }, "devDependencies": { + "eslint-config-airbnb-base": "^13.1.0", + "eslint-config-prettier": "^4.1.0", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-prettier": "^3.0.1", "mocha": "^5.2.0", "should": "^13.1.2", "sleep": "^5.1.1", diff --git a/tests/tests.js b/tests/tests.js index 997f511bdc..75a7343da3 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -1,81 +1,78 @@ -'use strict'; - -var bodyParser = require('body-parser') -var express = require('express') -var mysql = require('mysql') -var Xapi = require('../lib/xapi.js') -var whereClause = require('../lib/util/whereClause.helper.js') -var should = require('should'); -var request = require('supertest') -const cmdargs = require('../lib/util/cmd.helper.js'); -const { version } = require('../package.json'); - -var args = {} -var app = {} -var agent = {} -var api = {} -var apiPrefix = '/apj/v1/' -var mysqlPool = {} - +"use strict"; + +var bodyParser = require("body-parser"); +var express = require("express"); +var mysql = require("mysql"); +var Xapi = require("../lib/xapi.js"); +var whereClause = require("../lib/util/whereClause.helper.js"); +var should = require("should"); +var request = require("supertest"); +const cmdargs = require("../lib/util/cmd.helper.js"); +const { version } = require("../package.json"); + +var args = {}; +var app = {}; +var agent = {}; +var api = {}; +var apiPrefix = "/apj/v1/"; +var mysqlPool = {}; //desribe group of tests done -describe('xmysql : tests', function () { - - before(function (done) { - - args['host'] = process.env.DATABASE_HOST || 'localhost' - args['user'] = process.env.DATABASE_USER || 'root' - args['password'] = process.env.DATABASE_PASSWORD || '' - args['database'] = process.env.DATABASE_NAME || 'classicmodels' - args['apiPrefix'] = apiPrefix - - cmdargs.handle(args) - - mysqlPool = mysql.createPool(args) - - app = express() - app.set('version', version) - app.use(bodyParser.json()) - app.use(bodyParser.urlencoded({ - extended: true - })) +describe("xmysql : tests", function() { + before(function(done) { + args["host"] = process.env.DATABASE_HOST || "localhost"; + args["user"] = process.env.DATABASE_USER || "root"; + args["password"] = process.env.DATABASE_PASSWORD || ""; + args["database"] = process.env.DATABASE_NAME || "classicmodels"; + args["apiPrefix"] = apiPrefix; + + cmdargs.handle(args); + + mysqlPool = mysql.createPool(args); + + app = express(); + app.set("version", version); + app.use(bodyParser.json()); + app.use( + bodyParser.urlencoded({ + extended: true + }) + ); agent = request.agent(app); - api = new Xapi(args, mysqlPool, app) - api.init(function (err, results) { + api = new Xapi(args, mysqlPool, app); + api.init(function(err, results) { if (err) { - process.exit(1) + process.exit(1); } - app.listen(3000) + app.listen(3000); done(); - }) + }); }); - after(function (done) { - - mysqlPool.end(function (err) { + after(function(done) { + mysqlPool.end(function(err) { done(); - }) - + }); }); - beforeEach(function (done) { + beforeEach(function(done) { //init common variables for each test done(); }); - afterEach(function (done) { + afterEach(function(done) { //term common variables for each test done(); }); - it('GET ' + apiPrefix + 'tables should PASS', function (done) { - + it("GET " + apiPrefix + "tables should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'tables') // api url + agent + .get(apiPrefix + "tables") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/tables error if (err) { return done(err); @@ -85,58 +82,54 @@ describe('xmysql : tests', function () { res.body.length.should.be.equal(8); return done(); - }); - }); - - it('GET ' + apiPrefix + 'payments/count should PASS', function (done) { - + it("GET " + apiPrefix + "payments/count should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'payments/count') // api url + agent + .get(apiPrefix + "payments/count") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/tables error if (err) { return done(err); } //validate response - res.body[0]['no_of_rows'].should.be.equal(273); + res.body[0]["no_of_rows"].should.be.equal(273); return done(); - }); - }); - it('GET ' + apiPrefix + 'offices/distinct?_fields=country should PASS', function (done) { - - //http get an url - agent.get(apiPrefix + 'offices/distinct?_fields=country') // api url - .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { - // Handle /api/tables error - if (err) { - return done(err); - } - - //validate response - res.body.length.should.be.equal(5); - - return done(); - - }); + it( + "GET " + apiPrefix + "offices/distinct?_fields=country should PASS", + function(done) { + //http get an url + agent + .get(apiPrefix + "offices/distinct?_fields=country") // api url + .expect(200) // 2xx for success and 4xx for failure + .end(function(err, res) { + // Handle /api/tables error + if (err) { + return done(err); + } - }); + //validate response + res.body.length.should.be.equal(5); - it('GET ' + apiPrefix + 'customers/describe should PASS', function (done) { + return done(); + }); + } + ); + it("GET " + apiPrefix + "customers/describe should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'customers/describe') // api url + agent + .get(apiPrefix + "customers/describe") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/tables error if (err) { return done(err); @@ -146,19 +139,17 @@ describe('xmysql : tests', function () { res.body.length.should.be.equal(13); return done(); - }); - }); - - it('GET ' + apiPrefix + 'payments/103___JM555205 should PASS', function (done) { - + it("GET " + apiPrefix + "payments/103___JM555205 should PASS", function( + done + ) { //http get an url - agent.get(apiPrefix + 'payments/103___JM555205')// api url + agent + .get(apiPrefix + "payments/103___JM555205") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { - + .end(function(err, res) { // Handle /api/tables error if (err) { return done(err); @@ -166,88 +157,77 @@ describe('xmysql : tests', function () { //validate response - max value here is 14571.44 res.body.length.should.be.equal(1); - res.body[0]['amount'].should.be.greaterThan(14570); + res.body[0]["amount"].should.be.greaterThan(14570); return done(); - }); - }); - - it('GET ' + apiPrefix + 'customers should PASS', function (done) { + it("GET " + apiPrefix + "customers should PASS", function(done) { //testcase //http get an url - agent.get(apiPrefix + 'customers') // api url + agent + .get(apiPrefix + "customers") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/customers error if (err) { return done(err); } - res.body.should.be.instanceOf(Array) + res.body.should.be.instanceOf(Array); res.body.length.should.be.greaterThan(0); //validate response return done(); }); - - }); - it('GET ' + apiPrefix + 'customers/103 should PASS', function (done) { - + it("GET " + apiPrefix + "customers/103 should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'customers/103') // api url + agent + .get(apiPrefix + "customers/103") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/customers/103 error if (err) { return done(err); } //validate response - res.body.should.be.instanceOf(Object) - res.body[0]['customerNumber'].should.be.equal(103) + res.body.should.be.instanceOf(Object); + res.body[0]["customerNumber"].should.be.equal(103); return done(); - }); - }); - it('GET ' + apiPrefix + 'payments?_p=2 should PASS', function (done) { - + it("GET " + apiPrefix + "payments?_p=2 should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'payments?_p=2') // api url + agent + .get(apiPrefix + "payments?_p=2") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/offices/1/employees error if (err) { return done(err); } //validate resonse - res.body.should.be.instanceOf(Array) - res.body.length.should.be.equal(20) - + res.body.should.be.instanceOf(Array); + res.body.length.should.be.equal(20); return done(); - }); - }); - - - it('GET ' + apiPrefix + 'customers should PASS', function (done) { - + it("GET " + apiPrefix + "customers should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'customers') // api url + agent + .get(apiPrefix + "customers") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/tables error if (err) { return done(err); @@ -257,17 +237,15 @@ describe('xmysql : tests', function () { res.body.length.should.be.equal(20); return done(); - }); - }); - it('GET ' + apiPrefix + 'customers?_size=100 should PASS', function (done) { - + it("GET " + apiPrefix + "customers?_size=100 should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'customers?_size=100') // api url + agent + .get(apiPrefix + "customers?_size=100") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/tables error if (err) { return done(err); @@ -277,17 +255,15 @@ describe('xmysql : tests', function () { res.body.length.should.be.equal(100); return done(); - }); - }); - it('GET ' + apiPrefix + 'customers?_size=1000 should PASS', function (done) { - + it("GET " + apiPrefix + "customers?_size=1000 should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'customers?_size=1000') // api url + agent + .get(apiPrefix + "customers?_size=1000") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/tables error if (err) { return done(err); @@ -297,17 +273,15 @@ describe('xmysql : tests', function () { res.body.length.should.be.equal(100); return done(); - }); - }); - it('GET ' + apiPrefix + 'customers?_size=-1 should PASS', function (done) { - + it("GET " + apiPrefix + "customers?_size=-1 should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'customers?_size=-1') // api url + agent + .get(apiPrefix + "customers?_size=-1") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/tables error if (err) { return done(err); @@ -317,191 +291,187 @@ describe('xmysql : tests', function () { res.body.length.should.be.equal(20); return done(); - - }); - - }); - - - - it('GET ' + apiPrefix + 'payments?_p=2&_size=10 should PASS', function (done) { - - //http get an url - agent.get(apiPrefix + 'payments?_p=2&_size=10') // api url - .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { - // Handle /api/offices/1/employees error - if (err) { - return done(err); - } - - //validate resonse - res.body.should.be.instanceOf(Array) - res.body.length.should.be.equal(10) - - - return done(); - - }); - - }); - - it('GET ' + apiPrefix + 'offices?_sort=city should PASS', function (done) { - - //http get an url - agent.get(apiPrefix + 'offices?_sort=city') // api url - .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { - // Handle /api/offices/1/employees error - if (err) { - return done(err); - } - - //validate resonse - res.body.should.be.instanceOf(Array) - res.body[0]['city'].should.be.equal('Boston') - - - return done(); - - }); - - }); - - - it('GET ' + apiPrefix + 'offices?_fields=officeCode,city should PASS', function (done) { - - //http get an url - agent.get(apiPrefix + 'offices?_fields=officeCode,city') // api url - .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { - // Handle /api/offices/1/employees error - if (err) { - return done(err); - } - - //validate resonse - res.body.should.be.instanceOf(Array) - Object.keys(res.body[0]).length.should.be.equal(2) - - - return done(); - }); - }); - it('GET ' + apiPrefix + 'offices?_fields=officeCode,ity should PASS', function (done) { - + it("GET " + apiPrefix + "payments?_p=2&_size=10 should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'offices?_fields=officeCode,ity') // api url + agent + .get(apiPrefix + "payments?_p=2&_size=10") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/offices/1/employees error if (err) { return done(err); } //validate resonse - res.body.should.be.instanceOf(Array) - - // ity in _fields is an in valid column and it should be ignored - Object.keys(res.body[0]).length.should.be.equal(1) - + res.body.should.be.instanceOf(Array); + res.body.length.should.be.equal(10); return done(); - }); - }); - it('GET ' + apiPrefix + 'offices?_fields=-territory,-addressLine2,-state should PASS', function (done) { - + it("GET " + apiPrefix + "offices?_sort=city should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'offices?_fields=-territory,-addressLine2,-state') // api url + agent + .get(apiPrefix + "offices?_sort=city") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/offices/1/employees error if (err) { return done(err); } //validate resonse - res.body.should.be.instanceOf(Array) - Object.keys(res.body[0]).length.should.be.equal(6) - + res.body.should.be.instanceOf(Array); + res.body[0]["city"].should.be.equal("Boston"); return done(); - }); - }); + it( + "GET " + apiPrefix + "offices?_fields=officeCode,city should PASS", + function(done) { + //http get an url + agent + .get(apiPrefix + "offices?_fields=officeCode,city") // api url + .expect(200) // 2xx for success and 4xx for failure + .end(function(err, res) { + // Handle /api/offices/1/employees error + if (err) { + return done(err); + } - it('GET ' + apiPrefix + 'offices?_where=(((officeCode,in,1,2))~and(city,eq,boston)) should PASS', function (done) { - - //http get an url - agent.get(apiPrefix + 'offices?_where=(((officeCode,in,1,2))~and(city,eq,boston))') // api url - .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { - // Handle /api/offices/1/employees error - if (err) { - return done(err); - } - - // tate is an invalid column but still it should query right number of columns - res.body.length.should.be.equal(1) - res.body[0]['city'].should.be.equal('Boston') - - return done(); - - }); + //validate resonse + res.body.should.be.instanceOf(Array); + Object.keys(res.body[0]).length.should.be.equal(2); - }); + return done(); + }); + } + ); + + it( + "GET " + apiPrefix + "offices?_fields=officeCode,ity should PASS", + function(done) { + //http get an url + agent + .get(apiPrefix + "offices?_fields=officeCode,ity") // api url + .expect(200) // 2xx for success and 4xx for failure + .end(function(err, res) { + // Handle /api/offices/1/employees error + if (err) { + return done(err); + } + //validate resonse + res.body.should.be.instanceOf(Array); - it('GET ' + apiPrefix + 'offices?_fields=-territory,-addressLine2,-state,-tate should PASS', function (done) { + // ity in _fields is an in valid column and it should be ignored + Object.keys(res.body[0]).length.should.be.equal(1); - //http get an url - agent.get(apiPrefix + 'offices?_fields=-territory,-addressLine2,-state') // api url - .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { - // Handle /api/offices/1/employees error - if (err) { - return done(err); - } + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "offices?_fields=-territory,-addressLine2,-state should PASS", + function(done) { + //http get an url + agent + .get(apiPrefix + "offices?_fields=-territory,-addressLine2,-state") // api url + .expect(200) // 2xx for success and 4xx for failure + .end(function(err, res) { + // Handle /api/offices/1/employees error + if (err) { + return done(err); + } - //validate resonse - res.body.should.be.instanceOf(Array) + //validate resonse + res.body.should.be.instanceOf(Array); + Object.keys(res.body[0]).length.should.be.equal(6); - // tate is an invalid column but still it should query right number of columns - Object.keys(res.body[0]).length.should.be.equal(6) + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "offices?_where=(((officeCode,in,1,2))~and(city,eq,boston)) should PASS", + function(done) { + //http get an url + agent + .get( + apiPrefix + + "offices?_where=(((officeCode,in,1,2))~and(city,eq,boston))" + ) // api url + .expect(200) // 2xx for success and 4xx for failure + .end(function(err, res) { + // Handle /api/offices/1/employees error + if (err) { + return done(err); + } + // tate is an invalid column but still it should query right number of columns + res.body.length.should.be.equal(1); + res.body[0]["city"].should.be.equal("Boston"); - return done(); + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "offices?_fields=-territory,-addressLine2,-state,-tate should PASS", + function(done) { + //http get an url + agent + .get(apiPrefix + "offices?_fields=-territory,-addressLine2,-state") // api url + .expect(200) // 2xx for success and 4xx for failure + .end(function(err, res) { + // Handle /api/offices/1/employees error + if (err) { + return done(err); + } - }); + //validate resonse + res.body.should.be.instanceOf(Array); - }); + // tate is an invalid column but still it should query right number of columns + Object.keys(res.body[0]).length.should.be.equal(6); - it('GET ' + apiPrefix + 'offices?_sort=-city should PASS', function (done) { + return done(); + }); + } + ); + it("GET " + apiPrefix + "offices?_sort=-city should PASS", function(done) { //http get an url - agent.get(apiPrefix + 'offices?_sort=-city') // api url + agent + .get(apiPrefix + "offices?_sort=-city") // api url .expect(200) // 2xx for success and 4xx for failure - .end(function (err, res) { + .end(function(err, res) { // Handle /api/offices/1/employees error if (err) { return done(err); } //validate resonse - res.body.should.be.instanceOf(Array) - res.body[0]['city'].should.be.equal('Tokyo') + res.body.should.be.instanceOf(Array); + res.body[0]["city"].should.be.equal("Tokyo"); return done(); }); - }); // it('GET ' + apiPrefix + 'offices?_sort=-city,ity,-ity should PASS', function (done) { @@ -526,24 +496,24 @@ describe('xmysql : tests', function () { // // }); - - it('POST /api/productlines should PASS', function (done) { - + it("POST /api/productlines should PASS", function(done) { var obj = {}; - obj['productLine'] = 'Hyperloop' - obj['textDescription'] = 'Hyperloop is essentially a train system that Musk calls \"a cross between ' + - 'a Concorde, a railgun, and an air hockey table\". ' + - 'It\'s based on the very high-speed transit (VHST) system proposed in 1972,' + - 'which combines a magnetic levitation train and a low pressure transit tube.' + - 'It evolves some of the original ideas of VHST, but it still uses tunnels' + - 'and pods or capsules to move from place to place.' + obj["productLine"] = "Hyperloop"; + obj["textDescription"] = + 'Hyperloop is essentially a train system that Musk calls "a cross between ' + + 'a Concorde, a railgun, and an air hockey table". ' + + "It's based on the very high-speed transit (VHST) system proposed in 1972," + + "which combines a magnetic levitation train and a low pressure transit tube." + + "It evolves some of the original ideas of VHST, but it still uses tunnels" + + "and pods or capsules to move from place to place."; //post to an url with data - agent.post(apiPrefix + 'productlines') //enter url - .send(obj) //postdata - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .post(apiPrefix + "productlines") //enter url + .send(obj) //postdata + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); @@ -551,33 +521,32 @@ describe('xmysql : tests', function () { //validate response - res.body['affectedRows'].should.be.equals(1) + res.body["affectedRows"].should.be.equals(1); return done(); - }); }); - it('POST /api/productlines/bulk should PASS', function (done) { - - var objArray = [] + it("POST /api/productlines/bulk should PASS", function(done) { + var objArray = []; var obj = {}; - obj['productLine'] = 'Bulletrain' - obj['textDescription'] = 'Japan' + obj["productLine"] = "Bulletrain"; + obj["textDescription"] = "Japan"; var obj1 = {}; - obj1['productLine'] = 'Bulletrain_1' - obj1['textDescription'] = 'China' + obj1["productLine"] = "Bulletrain_1"; + obj1["textDescription"] = "China"; - objArray.push(obj) - objArray.push(obj1) + objArray.push(obj); + objArray.push(obj1); //post to an url with data - agent.post(apiPrefix + 'productlines/bulk') //enter url - .send(objArray) //postdata - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .post(apiPrefix + "productlines/bulk") //enter url + .send(objArray) //postdata + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); @@ -585,32 +554,30 @@ describe('xmysql : tests', function () { //validate response - res.body['affectedRows'].should.be.equals(2) + res.body["affectedRows"].should.be.equals(2); return done(); - }); }); - it('POST /api/productlines/bulk should PASS', function (done) { - - var objArray = [] + it("POST /api/productlines/bulk should PASS", function(done) { + var objArray = []; var obj = {}; - obj['productLine'] = 'Bulletrain_2' + obj["productLine"] = "Bulletrain_2"; var obj1 = {}; - obj1['productLine'] = 'Bulletrain_3' - + obj1["productLine"] = "Bulletrain_3"; - objArray.push(obj) - objArray.push(obj1) + objArray.push(obj); + objArray.push(obj1); //post to an url with data - agent.post(apiPrefix + 'productlines/bulk') //enter url - .send(objArray) //postdata - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .post(apiPrefix + "productlines/bulk") //enter url + .send(objArray) //postdata + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); @@ -618,19 +585,21 @@ describe('xmysql : tests', function () { //validate response - res.body['affectedRows'].should.be.equals(2) + res.body["affectedRows"].should.be.equals(2); return done(); - }); }); - it('GET ' + apiPrefix + 'productlines/bulk should PASS', function (done) { - + it("GET " + apiPrefix + "productlines/bulk should PASS", function(done) { //post to an url with data - agent.get(apiPrefix + 'productlines/bulk?_ids=Bulletrain,Bulletrain_1,Bulletrain_2,Bulletrain_3') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get( + apiPrefix + + "productlines/bulk?_ids=Bulletrain,Bulletrain_1,Bulletrain_2,Bulletrain_3" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); @@ -638,20 +607,21 @@ describe('xmysql : tests', function () { //validate response - res.body.length.should.be.equals(4) + res.body.length.should.be.equals(4); return done(); - }); }); - - it('DELETE /api/productlines/bulk should PASS', function (done) { - + it("DELETE /api/productlines/bulk should PASS", function(done) { //post to an url with data - agent.del(apiPrefix + 'productlines/bulk?_ids=Bulletrain,Bulletrain_1,Bulletrain_2,Bulletrain_3') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .del( + apiPrefix + + "productlines/bulk?_ids=Bulletrain,Bulletrain_1,Bulletrain_2,Bulletrain_3" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); @@ -659,82 +629,79 @@ describe('xmysql : tests', function () { //validate response - res.body['affectedRows'].should.be.equals(4) + res.body["affectedRows"].should.be.equals(4); return done(); - }); }); - - it('PUT /api/productlines should PASS', function (done) { - + it("PUT /api/productlines should PASS", function(done) { var obj = {}; - obj['productLine'] = 'Hyperloop' - obj['textDescription'] = 'Hyperloop is essentially a train system that ElonMusk calls \"a cross between ' + - 'a Concorde, a railgun, and an air hockey table\". ' + - 'It\'s based on the very high-speed transit (VHST) system proposed in 1972,' + - 'which combines a magnetic levitation train and a low pressure transit tube.' + - 'It evolves some of the original ideas of VHST, but it still uses tunnels' + - 'and pods or capsules to move from place to place.' + obj["productLine"] = "Hyperloop"; + obj["textDescription"] = + 'Hyperloop is essentially a train system that ElonMusk calls "a cross between ' + + 'a Concorde, a railgun, and an air hockey table". ' + + "It's based on the very high-speed transit (VHST) system proposed in 1972," + + "which combines a magnetic levitation train and a low pressure transit tube." + + "It evolves some of the original ideas of VHST, but it still uses tunnels" + + "and pods or capsules to move from place to place."; //post to an url with data - agent.put(apiPrefix + 'productlines') //enter url - .send(obj) //postdata - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .put(apiPrefix + "productlines") //enter url + .send(obj) //postdata + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body['affectedRows'].should.be.equals(2) + res.body["affectedRows"].should.be.equals(2); return done(); - }); }); - if(args['host'] === 'localhost') { - it('POST /dynamic should PASS', function (done) { - + if (args["host"] === "localhost") { + it("POST /dynamic should PASS", function(done) { var obj = {}; - obj['query'] = 'select * from ?? limit 0,5' - obj['params'] = ['customers'] + obj["query"] = "select * from ?? limit 0,5"; + obj["params"] = ["customers"]; //post to an url with data - agent.post('/dynamic') //enter url - .send(obj) //postdata - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .post("/dynamic") //enter url + .send(obj) //postdata + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body.length.should.be.equals(5) + res.body.length.should.be.equals(5); return done(); - }); }); - it('POST /dynamic/abc should PASS', function (done) { - + it("POST /dynamic/abc should PASS", function(done) { var obj = {}; - obj['query'] = 'select * from ?? limit 0,5' - obj['params'] = ['customers'] + obj["query"] = "select * from ?? limit 0,5"; + obj["params"] = ["customers"]; //post to an url with data - agent.post('/dynamic') //enter url - .send(obj) //postdata - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .post("/dynamic") //enter url + .send(obj) //postdata + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); @@ -742,25 +709,24 @@ describe('xmysql : tests', function () { //validate response - res.body.length.should.be.equals(5) + res.body.length.should.be.equals(5); return done(); - }); }); - it('POST /dynamic should PASS', function (done) { - + it("POST /dynamic should PASS", function(done) { var obj = {}; - obj['query'] = 'select * from customers limit 0,5' - obj['params'] = [] + obj["query"] = "select * from customers limit 0,5"; + obj["params"] = []; //post to an url with data - agent.post('/dynamic') //enter url - .send(obj) //postdata - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .post("/dynamic") //enter url + .send(obj) //postdata + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); @@ -768,126 +734,129 @@ describe('xmysql : tests', function () { //validate response - res.body.length.should.be.equals(5) + res.body.length.should.be.equals(5); return done(); - }); }); } - - it('PATCH /api/productlines/Hyperloop should PASS', function (done) { - + it("PATCH /api/productlines/Hyperloop should PASS", function(done) { var obj = {}; - obj['textDescription'] = 'Hyperloop is essentially a train system that Elon Musk (https://twitter.com/elonmusk) calls \"a cross between ' + - 'a Concorde, a railgun, and an air hockey table\". ' + - 'It\'s based on the very high-speed transit (VHST) system proposed in 1972,' + - 'which combines a magnetic levitation train and a low pressure transit tube.' + - 'It evolves some of the original ideas of VHST, but it still uses tunnels' + - 'and pods or capsules to move from place to place.' + obj["textDescription"] = + 'Hyperloop is essentially a train system that Elon Musk (https://twitter.com/elonmusk) calls "a cross between ' + + 'a Concorde, a railgun, and an air hockey table". ' + + "It's based on the very high-speed transit (VHST) system proposed in 1972," + + "which combines a magnetic levitation train and a low pressure transit tube." + + "It evolves some of the original ideas of VHST, but it still uses tunnels" + + "and pods or capsules to move from place to place."; //post to an url with data - agent.patch(apiPrefix + 'productlines/Hyperloop') //enter url - .send(obj) //postdata - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .patch(apiPrefix + "productlines/Hyperloop") //enter url + .send(obj) //postdata + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body['affectedRows'].should.be.equals(1) + res.body["affectedRows"].should.be.equals(1); return done(); - }); - - }); - it('DELETE /api/customers/:id should PASS', function (done) { - + it("DELETE /api/customers/:id should PASS", function(done) { var obj = {}; //post to an url with data - agent.del(apiPrefix + 'productlines/Hyperloop') //enter url - .send(obj) //postdata - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body['affectedRows'].should.be.equals(1) - - return done(); - - }); - }); - - it('GET ' + apiPrefix + 'offices/1/employees should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices/1/employees') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .del(apiPrefix + "productlines/Hyperloop") //enter url + .send(obj) //postdata + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body.length.should.be.above(1) + res.body["affectedRows"].should.be.equals(1); return done(); - }); }); - - it('GET ' + apiPrefix + 'offices/1/employees?_where=(jobTitle,eq,Sales%20Rep) should PASS', function (done) { - + it("GET " + apiPrefix + "offices/1/employees should PASS", function(done) { //post to an url with data - agent.get(apiPrefix + 'offices/1/employees?_where=(jobTitle,eq,Sales%20Rep)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "offices/1/employees") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body.length.should.be.equals(2) + res.body.length.should.be.above(1); return done(); - }); }); + it( + "GET " + + apiPrefix + + "offices/1/employees?_where=(jobTitle,eq,Sales%20Rep) should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices/1/employees?_where=(jobTitle,eq,Sales%20Rep)") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - it('GET ' + apiPrefix + 'payments?_where=(amount,gte,1000)~and(customerNumber,lte,120) should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'payments?_where=(amount,gte,1000)~and(customerNumber,lte,120)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } + //validate response + res.body.length.should.be.equals(2); - //validate response - res.body.length.should.be.equals(13) + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "payments?_where=(amount,gte,1000)~and(customerNumber,lte,120) should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "payments?_where=(amount,gte,1000)~and(customerNumber,lte,120)" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - return done(); + //validate response + res.body.length.should.be.equals(13); - }); - }); + return done(); + }); + } + ); // SOMETHING WEIRD HERE // test in travis show 7 but on local machine result has 6 elements @@ -910,897 +879,1017 @@ describe('xmysql : tests', function () { // }); // }); - it('GET ' + apiPrefix + 'offices?_where=(city,like,~on~) should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices?_where=(city,like,~on~)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body.length.should.be.equals(2) - - - return done(); - - }); - }); + it( + "GET " + apiPrefix + "offices?_where=(city,like,~on~) should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices?_where=(city,like,~on~)") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - it('GET ' + apiPrefix + 'offices?_where=(city,like,san~) should PASS', function (done) { + //validate response + res.body.length.should.be.equals(2); - //post to an url with data - agent.get(apiPrefix + 'offices?_where=(city,like,san~)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } + return done(); + }); + } + ); - //validate response - res.body.length.should.be.equals(1) + it( + "GET " + apiPrefix + "offices?_where=(city,like,san~) should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices?_where=(city,like,san~)") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } + //validate response + res.body.length.should.be.equals(1); - return done(); + return done(); + }); + } + ); - }); - }); + it( + "GET " + apiPrefix + "offices?_where=(country,nlike,us~) should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices?_where=(country,nlike,us~)") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - it('GET ' + apiPrefix + 'offices?_where=(country,nlike,us~) should PASS', function (done) { + //validate response + res.body.length.should.be.equals(4); - //post to an url with data - agent.get(apiPrefix + 'offices?_where=(country,nlike,us~)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "payments?_where=(amount,gte,1000)&_sort=-amount should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "payments?_where=(amount,gte,1000)&_sort=-amount") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - //validate response - res.body.length.should.be.equals(4) + //validate response + res.body[0].amount.should.be.equals(120166.58); + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "payments?_where=(checkNumber,eq,JM555205)~or(checkNumber,eq,OM314933) should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "payments?_where=(checkNumber,eq,JM555205)~or(checkNumber,eq,OM314933)" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - return done(); + //validate response + res.body.length.should.be.equals(2); - }); - }); + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "payments?_where=((checkNumber,eq,JM555205)~or(checkNumber,eq,OM314933)) should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "payments?_where=((checkNumber,eq,JM555205)~or(checkNumber,eq,OM314933))" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } + //validate response + res.body.length.should.be.equals(2); - it('GET ' + apiPrefix + 'payments?_where=(amount,gte,1000)&_sort=-amount should PASS', function (done) { + return done(); + }); + } + ); + it("GET " + apiPrefix + "employees/1002/employees should PASS", function( + done + ) { //post to an url with data - agent.get(apiPrefix + 'payments?_where=(amount,gte,1000)&_sort=-amount') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "employees/1002/employees") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body[0].amount.should.be.equals(120166.58) + res.body.length.should.be.above(1); return done(); - }); }); - it('GET ' + apiPrefix + 'payments?_where=(checkNumber,eq,JM555205)~or(checkNumber,eq,OM314933) should PASS', function (done) { - + it("GET " + apiPrefix + "productlines/trains/products should PASS", function( + done + ) { //post to an url with data - agent.get(apiPrefix + 'payments?_where=(checkNumber,eq,JM555205)~or(checkNumber,eq,OM314933)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "productlines/trains/products") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body.length.should.be.equals(2) + res.body.length.should.be.above(1); return done(); - }); }); - it('GET ' + apiPrefix + 'payments?_where=((checkNumber,eq,JM555205)~or(checkNumber,eq,OM314933)) should PASS', function (done) { - + it("GET " + apiPrefix + "productlines/trains/products should PASS", function( + done + ) { //post to an url with data - agent.get(apiPrefix + 'payments?_where=((checkNumber,eq,JM555205)~or(checkNumber,eq,OM314933))') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "productlines/trains/products") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body.length.should.be.equals(2) + res.body.length.should.be.above(1); return done(); - }); }); - it('GET ' + apiPrefix + 'employees/1002/employees should PASS', function (done) { - + it("GET " + apiPrefix + "employees/1165/customers should PASS", function( + done + ) { //post to an url with data - agent.get(apiPrefix + 'employees/1002/employees') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "employees/1165/customers") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body.length.should.be.above(1) + res.body.length.should.be.above(1); return done(); - }); }); - - it('GET ' + apiPrefix + 'productlines/trains/products should PASS', function (done) { - + it("GET " + apiPrefix + "customers/103/orders should PASS", function(done) { //post to an url with data - agent.get(apiPrefix + 'productlines/trains/products') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "customers/103/orders") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body.length.should.be.above(1) + res.body.length.should.be.above(1); return done(); - }); }); + it( + "GET " + apiPrefix + "products/S10_1678/orderdetails should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "products/S10_1678/orderdetails") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } + + //validate response + res.body.length.should.be.above(1); - it('GET ' + apiPrefix + 'productlines/trains/products should PASS', function (done) { + return done(); + }); + } + ); + it("GET " + apiPrefix + "customers/103/payments should PASS", function(done) { //post to an url with data - agent.get(apiPrefix + 'productlines/trains/products') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "customers/103/payments") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } //validate response - res.body.length.should.be.above(1) + res.body.length.should.be.above(1); return done(); - }); }); - it('GET ' + apiPrefix + 'employees/1165/customers should PASS', function (done) { + it( + "GET " + + apiPrefix + + "customers/groupby?_fields=city&_sort=city should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "customers/groupby?_fields=city&_sort=city") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - //post to an url with data - agent.get(apiPrefix + 'employees/1165/customers') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } + //validate response + res.body[0]["city"].should.be.equals("Aachen"); + res.body.length.should.be.equals(95); - //validate response - res.body.length.should.be.above(1) + return done(); + }); + } + ); - return done(); + it( + "GET " + apiPrefix + "offices/ugroupby?_fields=country should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices/ugroupby?_fields=country") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - }); - }); + //validate response + Object.keys(res.body).length.should.be.equals(1); + res.body["country"].length.should.be.equals(5); - it('GET ' + apiPrefix + 'customers/103/orders should PASS', function (done) { + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "offices/ugroupby?_fields=country,city,state should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices/ugroupby?_fields=country,city,state") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - //post to an url with data - agent.get(apiPrefix + 'customers/103/orders') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } + //validate response + //res.body.length.should.be.equals(3) + Object.keys(res.body).length.should.be.equals(3); + res.body["country"].length.should.be.equals(5); + res.body["city"].length.should.be.equals(7); + res.body["state"].length.should.be.equals(5); - //validate response - res.body.length.should.be.above(1) + return done(); + }); + } + ); - return done(); + it( + "GET " + apiPrefix + "offices/ugroupby?_fields=country,city should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices/ugroupby?_fields=country,city") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - }); - }); + //validate response + Object.keys(res.body).length.should.be.equals(2); + res.body["country"].length.should.be.equals(5); + res.body["city"].length.should.be.equals(7); - it('GET ' + apiPrefix + 'products/S10_1678/orderdetails should PASS', function (done) { + return done(); + }); + } + ); + it("GET " + apiPrefix + "offices/ugroupby?_fields= should PASS", function( + done + ) { //post to an url with data - agent.get(apiPrefix + 'products/S10_1678/orderdetails') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "offices/ugroupby?_fields=") //enter url + .expect(400) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } - //validate response - res.body.length.should.be.above(1) + Object.keys(res.body).length.should.be.equals(1); return done(); - }); }); - it('GET ' + apiPrefix + 'customers/103/payments should PASS', function (done) { - + it("GET " + apiPrefix + "payments/chart?_fields=amount should PASS", function( + done + ) { //post to an url with data - agent.get(apiPrefix + 'customers/103/payments') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "payments/chart?_fields=amount") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } - //validate response - res.body.length.should.be.above(1) + res.body.length.should.be.equals(7); + res.body[0]["_count"].should.be.equals(45); + res.body[2]["_count"].should.be.equals(109); + res.body[6]["_count"].should.be.equals(2); return done(); - }); }); - it('GET ' + apiPrefix + 'customers/groupby?_fields=city&_sort=city should PASS', function (done) { + it( + "GET " + + apiPrefix + + "payments/chart?_fields=amount&min=0&max=131000&step=25000 should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "payments/chart?_fields=amount&min=0&max=131000&step=25000" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } + + res.body.length.should.be.equals(5); + res.body[0]["_count"].should.be.equals(107); + res.body[1]["_count"].should.be.equals(124); + + return done(); + }); + } + ); + it("GET " + apiPrefix + "payments/autochart should PASS", function(done) { //post to an url with data - agent.get(apiPrefix + 'customers/groupby?_fields=city&_sort=city') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "payments/autochart") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } - //validate response - res.body[0]['city'].should.be.equals("Aachen") - res.body.length.should.be.equals(95) + res.body[0]["chart"].length.should.be.equals(7); + res.body[0]["chart"][0]["_count"].should.be.equals(45); + res.body[0]["chart"][6]["_count"].should.be.equals(2); return done(); - }); }); + it( + "GET " + apiPrefix + "payments?_where=(amount,bw,1000,5000) should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "payments?_where=(amount,bw,1000,5000)") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - it('GET ' + apiPrefix + 'offices/ugroupby?_fields=country should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices/ugroupby?_fields=country') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } + res.body.length.should.be.equals(19); - //validate response - Object.keys(res.body).length.should.be.equals(1) - res.body['country'].length.should.be.equals(5) + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "payments/chart?_fields=amount&min=0&max=131000&step=25000&range=1 should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "payments/chart?_fields=amount&min=0&max=131000&step=25000&range=1" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - return done(); + res.body.length.should.be.equals(5); + res.body[4]["_count"].should.be.equals(273); + res.body[1]["_count"].should.be.equals(231); + res.body[0]["_count"].should.be.equals(107); - }); - }); + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "payments/chart?_fields=amount&steparray=0,50000,100000,140000 should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "payments/chart?_fields=amount&steparray=0,50000,100000,140000" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } + res.body.length.should.be.equals(3); + res.body[0]["_count"].should.be.equals(231); + res.body[1]["_count"].should.be.equals(37); + res.body[2]["_count"].should.be.equals(5); - it('GET ' + apiPrefix + 'offices/ugroupby?_fields=country,city,state should PASS', function (done) { + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "payments/chart?_fields=amount&steparray=0,50000,100000,140000&range=1 should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "payments/chart?_fields=amount&steparray=0,50000,100000,140000&range=1" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - //post to an url with data - agent.get(apiPrefix + 'offices/ugroupby?_fields=country,city,state') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } + res.body.length.should.be.equals(3); + res.body[0]["_count"].should.be.equals(231); + res.body[1]["_count"].should.be.equals(268); + res.body[2]["_count"].should.be.equals(273); - //validate response - //res.body.length.should.be.equals(3) - Object.keys(res.body).length.should.be.equals(3) - res.body['country'].length.should.be.equals(5) - res.body['city'].length.should.be.equals(7) - res.body['state'].length.should.be.equals(5) + return done(); + }); + } + ); - return done(); + it( + "GET " + apiPrefix + "payments/chart?_fields=amount&range=1 should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "payments/chart?_fields=amount&range=1") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - }); - }); + res.body.length.should.be.equals(7); + res.body[0]["_count"].should.be.equals(45); + res.body[6]["_count"].should.be.equals(273); - it('GET ' + apiPrefix + 'offices/ugroupby?_fields=country,city should PASS', function (done) { + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "offices/1/employees?_groupby=jobTitle&_having=(_count,gt,1) should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "offices/1/employees?_groupby=jobTitle&_having=(_count,gt,1)" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - //post to an url with data - agent.get(apiPrefix + 'offices/ugroupby?_fields=country,city') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } + //validate response + res.body[0]["_count"].should.be.equals(2); + res.body.length.should.be.equals(1); - //validate response - Object.keys(res.body).length.should.be.equals(2) - res.body['country'].length.should.be.equals(5) - res.body['city'].length.should.be.equals(7) + return done(); + }); + } + ); - return done(); + it( + "GET " + apiPrefix + "offices/1/employees?_groupby=jobTitle should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices/1/employees?_groupby=jobTitle") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - }); - }); + //validate response + res.body[0]["jobTitle"].should.be.equals("President"); + res.body.length.should.be.equals(5); - it('GET ' + apiPrefix + 'offices/ugroupby?_fields= should PASS', function (done) { + return done(); + }); + } + ); + it("GET " + apiPrefix + "offices?_groupby=country should PASS", function( + done + ) { //post to an url with data - agent.get(apiPrefix + 'offices/ugroupby?_fields=') //enter url - .expect(400)//200 for success 4xx for failure - .end(function (err, res) { + agent + .get(apiPrefix + "offices?_groupby=country") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } - Object.keys(res.body).length.should.be.equals(1) + //validate response + res.body[0]["country"].should.be.equals("Australia"); + res.body.length.should.be.equals(5); return done(); - }); }); - it('GET ' + apiPrefix + 'payments/chart?_fields=amount should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'payments/chart?_fields=amount') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } + it( + "GET " + apiPrefix + "offices?_groupby=country&_sort=country should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices?_groupby=country&_sort=-country") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - res.body.length.should.be.equals(7) - res.body[0]['_count'].should.be.equals(45) - res.body[2]['_count'].should.be.equals(109) - res.body[6]['_count'].should.be.equals(2) + //validate response + res.body[0]["country"].should.be.equals("USA"); - return done(); - - }); - }) - - it('GET ' + apiPrefix + 'payments/chart?_fields=amount&min=0&max=131000&step=25000 should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'payments/chart?_fields=amount&min=0&max=131000&step=25000') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - res.body.length.should.be.equals(5) - res.body[0]['_count'].should.be.equals(107) - res.body[1]['_count'].should.be.equals(124) - - return done(); - - }); - }) - - it('GET ' + apiPrefix + 'payments/autochart should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'payments/autochart') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - res.body[0]['chart'].length.should.be.equals(7) - res.body[0]['chart'][0]['_count'].should.be.equals(45) - res.body[0]['chart'][6]['_count'].should.be.equals(2) - - return done(); - - }); - }) - - it('GET ' + apiPrefix + 'payments?_where=(amount,bw,1000,5000) should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'payments?_where=(amount,bw,1000,5000)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - res.body.length.should.be.equals(19) - - return done(); - - }); - }) - - - it('GET ' + apiPrefix + 'payments/chart?_fields=amount&min=0&max=131000&step=25000&range=1 should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'payments/chart?_fields=amount&min=0&max=131000&step=25000&range=1') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - res.body.length.should.be.equals(5) - res.body[4]['_count'].should.be.equals(273) - res.body[1]['_count'].should.be.equals(231) - res.body[0]['_count'].should.be.equals(107) - - - return done(); - - }); - }) - - it('GET ' + apiPrefix + 'payments/chart?_fields=amount&steparray=0,50000,100000,140000 should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'payments/chart?_fields=amount&steparray=0,50000,100000,140000') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - res.body.length.should.be.equals(3) - res.body[0]['_count'].should.be.equals(231) - res.body[1]['_count'].should.be.equals(37) - res.body[2]['_count'].should.be.equals(5) - - return done(); - - }); - }) - - it('GET ' + apiPrefix + 'payments/chart?_fields=amount&steparray=0,50000,100000,140000&range=1 should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'payments/chart?_fields=amount&steparray=0,50000,100000,140000&range=1') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - res.body.length.should.be.equals(3) - res.body[0]['_count'].should.be.equals(231) - res.body[1]['_count'].should.be.equals(268) - res.body[2]['_count'].should.be.equals(273) - - return done(); - - }); - }) - - it('GET ' + apiPrefix + 'payments/chart?_fields=amount&range=1 should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'payments/chart?_fields=amount&range=1') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - res.body.length.should.be.equals(7) - res.body[0]['_count'].should.be.equals(45) - res.body[6]['_count'].should.be.equals(273) - - return done(); - - }); - }) - - it('GET ' + apiPrefix + 'offices/1/employees?_groupby=jobTitle&_having=(_count,gt,1) should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices/1/employees?_groupby=jobTitle&_having=(_count,gt,1)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['_count'].should.be.equals(2) - res.body.length.should.be.equals(1) - - return done(); - - }); - }); - - it('GET ' + apiPrefix + 'offices/1/employees?_groupby=jobTitle should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices/1/employees?_groupby=jobTitle') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['jobTitle'].should.be.equals("President") - res.body.length.should.be.equals(5) - - return done(); - - }); - }); - - - it('GET ' + apiPrefix + 'offices?_groupby=country should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices?_groupby=country') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['country'].should.be.equals("Australia") - res.body.length.should.be.equals(5) - - return done(); - - }); - }); - - - it('GET ' + apiPrefix + 'offices?_groupby=country&_sort=country should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices?_groupby=country&_sort=-country') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['country'].should.be.equals("USA") - - return done(); - - }); - }); - - it('GET ' + apiPrefix + 'offices?_groupby=country&_sort=_count should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices?_groupby=country&_sort=_count') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['_count'].should.be.equals(1) - - return done(); - - }); - }); - - it('GET ' + apiPrefix + 'offices?_groupby=country&_sort=-_count should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices?_groupby=country&_sort=-_count') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['country'].should.be.equals("USA") - - return done(); - - }); - }); - - - it('GET ' + apiPrefix + 'offices/groupby?_fields=country&_having=(_count,gt,1) should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices/groupby?_fields=country&_having=(_count,gt,1)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['country'].should.be.equals("USA") - - return done(); - - }); - }); - - - it('GET ' + apiPrefix + 'offices?_groupby=country&_having=(_count,gt,1) should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices?_groupby=country&_having=(_count,gt,1)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['_count'].should.be.equals(3) - - return done(); - - }); - }); - - - it('GET ' + apiPrefix + 'offices/groupby?_fields=country should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices/groupby?_fields=country') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['country'].should.be.equals("USA") - res.body.length.should.be.equals(5) - - return done(); - - }); - }); - - - it('GET ' + apiPrefix + 'offices/groupby?_fields=country,city&_sort=city,country should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'offices/groupby?_fields=country,city&_sort=city,country') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['country'].should.be.equals("USA") - res.body[0]['city'].should.be.equals("Boston") - res.body.length.should.be.equals(7) - - return done(); - - }); - }); - - it('GET ' + apiPrefix + 'orders/aggregate?_fields=orderNumber,customerNumber should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'orders/aggregate?_fields=orderNumber,customerNumber') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body[0]['min_of_orderNumber'].should.be.equals(10100) - res.body[0]['max_of_orderNumber'].should.be.equals(10425) - res.body[0]['sum_of_orderNumber'].should.be.equals(3345575) - Object.keys(res.body[0]).length.should.be.equals(12) - - return done(); - - }); - }); - - - it('GET ' + apiPrefix + 'orders/aggregate should FAIL', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'orders/aggregate') //enter url - .expect(400)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - - done(err) - - }); - }); - - it('GET ' + apiPrefix + 'orders/groupby should FAIL', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'orders/groupby') //enter url - .expect(400)//200 for success 4xx for failure - .end(function (err, res) { - // Handle /api/v error - done(err) - }); - }); - - it('GET ' + apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline) should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)') //enter url - .expect(400)//200 for success 4xx for failure - .end(function (err, res) { + return done(); + }); + } + ); - // Handle /api/v error - if (err) { - return done(err); - } + it( + "GET " + apiPrefix + "offices?_groupby=country&_sort=_count should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices?_groupby=country&_sort=_count") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - return done(); + //validate response + res.body[0]["_count"].should.be.equals(1); - }); - }); + return done(); + }); + } + ); + it( + "GET " + apiPrefix + "offices?_groupby=country&_sort=-_count should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices?_groupby=country&_sort=-_count") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - it('GET ' + apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName should PASS', function (done) { + //validate response + res.body[0]["country"].should.be.equals("USA"); - //post to an url with data - agent.get(apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "offices/groupby?_fields=country&_having=(_count,gt,1) should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + "offices/groupby?_fields=country&_having=(_count,gt,1)" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - // Handle /api/v error - if (err) { - return done(err); - } + //validate response + res.body[0]["country"].should.be.equals("USA"); - //validate response - Object.keys(res.body[0]).length.should.be.equals(2) - res.body.length.should.be.equals(20) + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "offices?_groupby=country&_having=(_count,gt,1) should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices?_groupby=country&_having=(_count,gt,1)") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - return done(); + //validate response + res.body[0]["_count"].should.be.equals(3); - }); - }); + return done(); + }); + } + ); - it('GET ' + apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl_productline,pr.productName should PASS', function (done) { + it( + "GET " + apiPrefix + "offices/groupby?_fields=country should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "offices/groupby?_fields=country") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - //post to an url with data - agent.get(apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl_productline,pr.productName') //enter url - .expect(400)//200 for success 4xx for failure - .end(function (err, res) { + //validate response + res.body[0]["country"].should.be.equals("USA"); + res.body.length.should.be.equals(5); - // Handle /api/v error - if (err) { - return done(err); - } + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "offices/groupby?_fields=country,city&_sort=city,country should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + "offices/groupby?_fields=country,city&_sort=city,country" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - return done(); + //validate response + res.body[0]["country"].should.be.equals("USA"); + res.body[0]["city"].should.be.equals("Boston"); + res.body.length.should.be.equals(7); - }); - }); + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "orders/aggregate?_fields=orderNumber,customerNumber should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "orders/aggregate?_fields=orderNumber,customerNumber") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } + //validate response + res.body[0]["min_of_orderNumber"].should.be.equals(10100); + res.body[0]["max_of_orderNumber"].should.be.equals(10425); + res.body[0]["sum_of_orderNumber"].should.be.equals(3345575); + Object.keys(res.body[0]).length.should.be.equals(12); - it('GET ' + apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName&_size=2 should PASS', function (done) { + return done(); + }); + } + ); + it("GET " + apiPrefix + "orders/aggregate should FAIL", function(done) { //post to an url with data - agent.get(apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName&_size=2') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - + agent + .get(apiPrefix + "orders/aggregate") //enter url + .expect(400) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - Object.keys(res.body[0]).length.should.be.equals(2) - res.body.length.should.be.equals(2) - - return done(); + done(err); }); }); - it('GET ' + apiPrefix + 'payments/count?_where=(amount,gt,19000) should PASS', function (done) { - + it("GET " + apiPrefix + "orders/groupby should FAIL", function(done) { //post to an url with data - agent.get(apiPrefix + 'payments/count?_where=(amount,gt,19000)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - + agent + .get(apiPrefix + "orders/groupby") //enter url + .expect(400) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error - if (err) { - return done(err); - } + done(err); + }); + }); - //validate response - res.body[0]['no_of_rows'].should.be.equals(196) + it( + "GET " + + apiPrefix + + "xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline) should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)" + ) //enter url + .expect(400) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - return done(); + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - }); - }); + //validate response + Object.keys(res.body[0]).length.should.be.equals(2); + res.body.length.should.be.equals(20); + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl_productline,pr.productName should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl_productline,pr.productName" + ) //enter url + .expect(400) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - it('GET ' + apiPrefix + 'payments/chart?_fields=amount&steppair=0,50000,40000,100000 should PASS', function (done) { + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName&_size=2 should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName&_size=2" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - //post to an url with data - agent.get(apiPrefix + 'payments/chart?_fields=amount&steppair=0,50000,40000,100000') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { + //validate response + Object.keys(res.body[0]).length.should.be.equals(2); + res.body.length.should.be.equals(2); - // Handle /api/v error - if (err) { - return done(err); - } + return done(); + }); + } + ); - //validate response - res.body.length.should.be.equals(2) - res.body[0]['_count'].should.be.equals(231) - res.body[1]['_count'].should.be.equals(80) + it( + "GET " + apiPrefix + "payments/count?_where=(amount,gt,19000) should PASS", + function(done) { + //post to an url with data + agent + .get(apiPrefix + "payments/count?_where=(amount,gt,19000)") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - return done(); + //validate response + res.body[0]["no_of_rows"].should.be.equals(196); - }); - }); + return done(); + }); + } + ); + + it( + "GET " + + apiPrefix + + "payments/chart?_fields=amount&steppair=0,50000,40000,100000 should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "payments/chart?_fields=amount&steppair=0,50000,40000,100000" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } + + //validate response + res.body.length.should.be.equals(2); + res.body[0]["_count"].should.be.equals(231); + res.body[1]["_count"].should.be.equals(80); + return done(); + }); + } + ); // it('GET ' + apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products,_j,ord.orderDetails&_on1=(pl.productline,eq,pr.productline)&_on2=(pr.productcode,eq,ord.productcode) should PASS', function (done) { // @@ -1823,185 +1912,166 @@ describe('xmysql : tests', function () { // }); // }); - it('GET ' + apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName&_size=2&_where=(productName,like,1972~) should PASS', function (done) { - - //post to an url with data - agent.get(apiPrefix + 'xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName&_size=2&_where=(productName,like,1972~)') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - - // Handle /api/v error - if (err) { - return done(err); - } - - //validate response - res.body.length.should.be.equals(1) - - return done(); + it( + "GET " + + apiPrefix + + "xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName&_size=2&_where=(productName,like,1972~) should PASS", + function(done) { + //post to an url with data + agent + .get( + apiPrefix + + "xjoin?_join=pl.productlines,_j,pr.products&_on1=(pl.productline,eq,pr.productline)&_fields=pl.productline,pr.productName&_size=2&_where=(productName,like,1972~)" + ) //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { + // Handle /api/v error + if (err) { + return done(err); + } - }); - }); + //validate response + res.body.length.should.be.equals(1); - it('/_health should PASS', function (done) { + return done(); + }); + } + ); + it("/_health should PASS", function(done) { //post to an url with data - agent.get('/_health') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - + agent + .get("/_health") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } - res.body['process_uptime'].should.be.greaterThanOrEqual(0); - res.body['mysql_uptime'].should.be.greaterThanOrEqual(0); + res.body["process_uptime"].should.be.greaterThanOrEqual(0); + res.body["mysql_uptime"].should.be.greaterThanOrEqual(0); return done(); - }); }); - it('/_health?details=1 should PASS', function (done) { - + it("/_health?details=1 should PASS", function(done) { //post to an url with data - agent.get('/_health?details=1') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - + agent + .get("/_health?details=1") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } - res.body['process_uptime'].should.be.greaterThanOrEqual(0); - res.body['mysql_uptime'].should.be.greaterThanOrEqual(0); - res.body['os_total_memory'].should.be.greaterThanOrEqual(0); - + res.body["process_uptime"].should.be.greaterThanOrEqual(0); + res.body["mysql_uptime"].should.be.greaterThanOrEqual(0); + res.body["os_total_memory"].should.be.greaterThanOrEqual(0); return done(); - }); }); - it('/_version should PASS', function (done) { - + it("/_version should PASS", function(done) { //post to an url with data - agent.get('/_version') //enter url - .expect(200)//200 for success 4xx for failure - .end(function (err, res) { - + agent + .get("/_version") //enter url + .expect(200) //200 for success 4xx for failure + .end(function(err, res) { // Handle /api/v error if (err) { return done(err); } - res.body['Xmysql'].should.equals(version); - res.body['mysql'].should.not.equals(""); - res.body['node'].should.not.equals(""); + res.body["Xmysql"].should.equals(version); + res.body["mysql"].should.not.equals(""); + res.body["node"].should.not.equals(""); return done(); - }); }); + it("where clause unit ?_where=(abc,eq,1234) should PASS", function(done) { + var err = whereClause.getConditionClause("(abc,eq,1234)"); - it('where clause unit ?_where=(abc,eq,1234) should PASS', function (done) { - - var err = whereClause.getConditionClause('(abc,eq,1234)') + err.err.should.be.equal(0); + err.query.should.be.equal("(??=?)"); + err.params[0].should.be.equal("abc"); + err.params[1].should.be.equal("1234"); - err.err.should.be.equal(0) - err.query.should.be.equal('(??=?)') - err.params[0].should.be.equal('abc') - err.params[1].should.be.equal('1234') - - done() + done(); //console.log(query,params,err); - }); - it('where clause unit ?_where=(abc,ne,1234) should PASS', function (done) { - - var err = whereClause.getConditionClause('(abc,ne,1234)') + it("where clause unit ?_where=(abc,ne,1234) should PASS", function(done) { + var err = whereClause.getConditionClause("(abc,ne,1234)"); - err.err.should.be.equal(0) - err.query.should.be.equal('(??!=?)') - err.params[0].should.be.equal('abc') - err.params[1].should.be.equal('1234') + err.err.should.be.equal(0); + err.query.should.be.equal("(??!=?)"); + err.params[0].should.be.equal("abc"); + err.params[1].should.be.equal("1234"); - done() + done(); //console.log(query,params,err); - }); + it("where clause unit ?_where=(abc,lt,1234) should PASS", function(done) { + var err = whereClause.getConditionClause("(abc,lt,1234)"); - it('where clause unit ?_where=(abc,lt,1234) should PASS', function (done) { + err.err.should.be.equal(0); + err.query.should.be.equal("(???)"); + err.params[0].should.be.equal("abc"); + err.params[1].should.be.equal("1234"); - var err = whereClause.getConditionClause('(abc,gt,1234)') - - err.err.should.be.equal(0) - err.query.should.be.equal('(??>?)') - err.params[0].should.be.equal('abc') - err.params[1].should.be.equal('1234') - - done() + done(); //console.log(query,params,err); - }); - it('where clause unit ?_where=(abc,gte,1234) should PASS', function (done) { + it("where clause unit ?_where=(abc,gte,1234) should PASS", function(done) { + var err = whereClause.getConditionClause("(abc,gte,1234)"); + err.err.should.be.equal(0); + err.query.should.be.equal("(??>=?)"); + err.params[0].should.be.equal("abc"); + err.params[1].should.be.equal("1234"); - var err = whereClause.getConditionClause('(abc,gte,1234)') - - err.err.should.be.equal(0) - err.query.should.be.equal('(??>=?)') - err.params[0].should.be.equal('abc') - err.params[1].should.be.equal('1234') - - done() + done(); //console.log(query,params,err); - }); - // it('where clause unit ?_where=(abc,like,1234) should PASS', function (done) { // // var query = '' @@ -2037,233 +2107,200 @@ describe('xmysql : tests', function () { // // }); - it('where clause unit ?_where=abc,eq,1234) should FAIL', function (done) { - + it("where clause unit ?_where=abc,eq,1234) should FAIL", function(done) { + var err = whereClause.getConditionClause("abc,eq,1234)"); - var err = whereClause.getConditionClause('abc,eq,1234)') + err.err.should.be.equal(1); + err.query.should.be.equal(""); + err.params.length.should.be.equal(0); - err.err.should.be.equal(1) - err.query.should.be.equal('') - err.params.length.should.be.equal(0) - - done() + done(); //console.log(query,params,err); - }); - it('where clause unit ?_where=(abc,eq,1234 should FAIL', function (done) { - + it("where clause unit ?_where=(abc,eq,1234 should FAIL", function(done) { + var err = whereClause.getConditionClause("(abc,eq,1234"); - var err = whereClause.getConditionClause('(abc,eq,1234') + err.err.should.be.equal(1); + err.query.should.be.equal(""); + err.params.length.should.be.equal(0); - err.err.should.be.equal(1) - err.query.should.be.equal('') - err.params.length.should.be.equal(0) - - done() + done(); //console.log(query,params,err); - }); - it('where clause unit ?_where=(abc,eq1234) should FAIL', function (done) { - - var err = whereClause.getConditionClause('(abc,eq1234)') + it("where clause unit ?_where=(abc,eq1234) should FAIL", function(done) { + var err = whereClause.getConditionClause("(abc,eq1234)"); - err.err.should.be.equal(1) - err.query.should.be.equal('') - err.params.length.should.be.equal(0) + err.err.should.be.equal(1); + err.query.should.be.equal(""); + err.params.length.should.be.equal(0); - done() + done(); //console.log(query,params,err); - }); - it('where clause unit ?_where=(abceq,1234) should FAIL', function (done) { + it("where clause unit ?_where=(abceq,1234) should FAIL", function(done) { + var err = whereClause.getConditionClause("(abceq,1234)"); - var err = whereClause.getConditionClause('(abceq,1234)') + err.err.should.be.equal(1); + err.query.should.be.equal(""); + err.params.length.should.be.equal(0); - err.err.should.be.equal(1) - err.query.should.be.equal('') - err.params.length.should.be.equal(0) - - done() + done(); //console.log(query,params,err); - }); + it("where clause unit ?_where=(1,eq,1)(1,eq,2)~or should FAIL", function(done) { + var err = whereClause.getConditionClause("(1,eq,1)(1,eq,2)~or"); - it('where clause unit ?_where=(1,eq,1)(1,eq,2)~or should FAIL', function (done) { - + err.err.should.be.equal(1); + err.query.should.be.equal(""); + err.params.length.should.be.equal(0); - var err = whereClause.getConditionClause('(1,eq,1)(1,eq,2)~or') - - err.err.should.be.equal(1) - err.query.should.be.equal('') - err.params.length.should.be.equal(0) - - done() + done(); //console.log(query,params,err); - }); - it('where clause unit ?_where=(1,eq,1)~or~or(1,eq,2)(1,eq,2) should FAIL', function (done) { + it("where clause unit ?_where=(1,eq,1)~or~or(1,eq,2)(1,eq,2) should FAIL", function(done) { + var err = whereClause.getConditionClause("(1,eq,1)~or~or(1,eq,2)(1,eq,2)"); - var err = whereClause.getConditionClause('(1,eq,1)~or~or(1,eq,2)(1,eq,2)') + err.err.should.be.equal(1); + err.query.should.be.equal(""); + err.params.length.should.be.equal(0); - err.err.should.be.equal(1) - err.query.should.be.equal('') - err.params.length.should.be.equal(0) - - done() + done(); //console.log(query,params,err); - }); - it('where clause unit ?_where=(abc,eq,1)~or(b,eq,2) should PASS', function (done) { - + it("where clause unit ?_where=(abc,eq,1)~or(b,eq,2) should PASS", function(done) { + var err = whereClause.getConditionClause("(abc,eq,1)~or(b,eq,2)"); - var err = whereClause.getConditionClause('(abc,eq,1)~or(b,eq,2)') - - err.err.should.be.equal(0) - err.query.should.be.equal('(??=?)or(??=?)') - err.params.length.should.be.equal(4) - err.params[0].should.be.equal('abc') - err.params[1].should.be.equal('1') - err.params[2].should.be.equal('b') - err.params[3].should.be.equal('2') + err.err.should.be.equal(0); + err.query.should.be.equal("(??=?)or(??=?)"); + err.params.length.should.be.equal(4); + err.params[0].should.be.equal("abc"); + err.params[1].should.be.equal("1"); + err.params[2].should.be.equal("b"); + err.params[3].should.be.equal("2"); // err.params[1].should.be.equal('1234') - done() + done(); //console.log(query,params,err); - }); + it("where clause unit ?_where=((a,eq,1)~and(b,eq,2))~or(c,eq,3) should PASS", function(done) { + var err = whereClause.getConditionClause( + "((abc,eq,1234)~and(b,eq,2))~or(cde,eq,3)" + ); - it('where clause unit ?_where=((a,eq,1)~and(b,eq,2))~or(c,eq,3) should PASS', function (done) { - + err.err.should.be.equal(0); + err.query.should.be.equal("((??=?)and(??=?))or(??=?)"); + err.params.length.should.be.equal(6); - var err = whereClause.getConditionClause('((abc,eq,1234)~and(b,eq,2))~or(cde,eq,3)') + err.params[0].should.be.equal("abc"); + err.params[2].should.be.equal("b"); + err.params[4].should.be.equal("cde"); - err.err.should.be.equal(0) - err.query.should.be.equal('((??=?)and(??=?))or(??=?)') - err.params.length.should.be.equal(6) - - err.params[0].should.be.equal('abc') - err.params[2].should.be.equal('b') - err.params[4].should.be.equal('cde') - - err.params[1].should.be.equal('1234') - err.params[3].should.be.equal('2') - err.params[5].should.be.equal('3') - - done() + err.params[1].should.be.equal("1234"); + err.params[3].should.be.equal("2"); + err.params[5].should.be.equal("3"); + done(); }); + it("where clause unit ?_where=((a,eq,1)~and(b,eq,2))~xor(c,eq,3) should PASS", function(done) { + var err = whereClause.getConditionClause( + "((abc,eq,1234)~and(b,eq,2))~xor(cde,eq,3)" + ); - it('where clause unit ?_where=((a,eq,1)~and(b,eq,2))~xor(c,eq,3) should PASS', function (done) { + err.err.should.be.equal(0); + err.query.should.be.equal("((??=?)and(??=?))xor(??=?)"); + err.params.length.should.be.equal(6); + err.params[0].should.be.equal("abc"); + err.params[2].should.be.equal("b"); + err.params[4].should.be.equal("cde"); - var err = whereClause.getConditionClause('((abc,eq,1234)~and(b,eq,2))~xor(cde,eq,3)') - - err.err.should.be.equal(0) - err.query.should.be.equal('((??=?)and(??=?))xor(??=?)') - err.params.length.should.be.equal(6) - - err.params[0].should.be.equal('abc') - err.params[2].should.be.equal('b') - err.params[4].should.be.equal('cde') - - err.params[1].should.be.equal('1234') - err.params[3].should.be.equal('2') - err.params[5].should.be.equal('3') - - done() + err.params[1].should.be.equal("1234"); + err.params[3].should.be.equal("2"); + err.params[5].should.be.equal("3"); + done(); }); - - it('where clause unit ?_where=(a,eq,1)~and((b,eq,2)~or(c,eq,3)) should PASS', function (done) { - - - var err = whereClause.getConditionClause('(a,eq,1)~and((b,eq,2)~or(c,eq,3))') + it("where clause unit ?_where=(a,eq,1)~and((b,eq,2)~or(c,eq,3)) should PASS", function(done) { + var err = whereClause.getConditionClause( + "(a,eq,1)~and((b,eq,2)~or(c,eq,3))" + ); //console.log(query,params); - err.err.should.be.equal(0) - err.query.should.be.equal('(??=?)and((??=?)or(??=?))') - err.params.length.should.be.equal(6) + err.err.should.be.equal(0); + err.query.should.be.equal("(??=?)and((??=?)or(??=?))"); + err.params.length.should.be.equal(6); - err.params[0].should.be.equal('a') - err.params[2].should.be.equal('b') - err.params[4].should.be.equal('c') + err.params[0].should.be.equal("a"); + err.params[2].should.be.equal("b"); + err.params[4].should.be.equal("c"); - err.params[1].should.be.equal('1') - err.params[3].should.be.equal('2') - err.params[5].should.be.equal('3') - - done() + err.params[1].should.be.equal("1"); + err.params[3].should.be.equal("2"); + err.params[5].should.be.equal("3"); + done(); }); - it('where clause unit ?_where=(a,in,1,2,3) should PASS', function (done) { - - var err = whereClause.getConditionClause('(a,in,1,2,3)') - - err.err.should.be.equal(0) - err.query.should.be.equal('(?? in (?,?,?))') + it("where clause unit ?_where=(a,in,1,2,3) should PASS", function(done) { + var err = whereClause.getConditionClause("(a,in,1,2,3)"); - done() + err.err.should.be.equal(0); + err.query.should.be.equal("(?? in (?,?,?))"); + done(); }); - it('where clause unit ?_where=(a,like,~1234) should PASS', function (done) { - - var err = whereClause.getConditionClause('(a,like,~1234)') + it("where clause unit ?_where=(a,like,~1234) should PASS", function(done) { + var err = whereClause.getConditionClause("(a,like,~1234)"); - err.err.should.be.equal(0) - err.query.should.be.equal('(?? like ?)') - err.params[0].should.be.equal('a') - err.params[1].should.be.equal('%1234') - - done() + err.err.should.be.equal(0); + err.query.should.be.equal("(?? like ?)"); + err.params[0].should.be.equal("a"); + err.params[1].should.be.equal("%1234"); + done(); }); - it('where clause unit ?_where=(a,like,~1234~) should PASS', function (done) { + it("where clause unit ?_where=(a,like,~1234~) should PASS", function(done) { + var err = whereClause.getConditionClause("(a,like,~1234~)"); - var err = whereClause.getConditionClause('(a,like,~1234~)') - - err.err.should.be.equal(0) - err.query.should.be.equal('(?? like ?)') - err.params[0].should.be.equal('a') - err.params[1].should.be.equal('%1234%') - - done() + err.err.should.be.equal(0); + err.query.should.be.equal("(?? like ?)"); + err.params[0].should.be.equal("a"); + err.params[1].should.be.equal("%1234%"); + done(); }); - it('where clause unit ?_where=(a,is,null)~and(b,is,true)~and(c,is,false) should PASS', function (done) { - - var err = whereClause.getConditionClause('(a,is,null)~and(b,is,true)~and(c,is,false)') + it("where clause unit ?_where=(a,is,null)~and(b,is,true)~and(c,is,false) should PASS", function(done) { + var err = whereClause.getConditionClause( + "(a,is,null)~and(b,is,true)~and(c,is,false)" + ); - err.err.should.be.equal(0) - err.query.should.be.equal('(?? is ?)and(?? is ?)and(?? is ?)') + err.err.should.be.equal(0); + err.query.should.be.equal("(?? is ?)and(?? is ?)and(?? is ?)"); //err.params[1].should.be.equal(null) - err.params[3].should.be.equal(true) - err.params[5].should.be.equal(false) - - done() + err.params[3].should.be.equal(true); + err.params[5].should.be.equal(false); + done(); }); - - });