Browse Source

Merge pull request #75 from v2io/eslint

eslint airbnb rules
pull/85/head
o1lab 6 years ago committed by GitHub
parent
commit
2ba88b5293
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      .eslintrc
  2. 27
      .eslintrc.js
  3. 91
      bin/index.js
  4. 39
      examples/aws-lambda/index.js
  5. 96
      index.js
  6. 116
      lib/util/cmd.helper.js
  7. 192
      lib/util/data.helper.js
  8. 274
      lib/util/whereClause.helper.js
  9. 443
      lib/xapi.js
  10. 503
      lib/xctrl.js
  11. 1111
      lib/xsql.js
  12. 460
      package-lock.json
  13. 4
      package.json
  14. 2831
      tests/tests.js

11
.eslintrc

@ -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 }]
}
}

27
.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
}
};

91
bin/index.js

@ -1,70 +1,71 @@
#! /usr/bin/env node #! /usr/bin/env node
const morgan = require('morgan'); const morgan = require("morgan");
const bodyParser = require('body-parser'); const bodyParser = require("body-parser");
const express = require('express'); const express = require("express");
const sqlConfig = require('commander'); const sqlConfig = require("commander");
const mysql = require('mysql'); const mysql = require("mysql");
const cors = require('cors'); const cors = require("cors");
const dataHelp = require('../lib/util/data.helper.js'); const dataHelp = require("../lib/util/data.helper.js");
const Xapi = require('../lib/xapi.js'); const Xapi = require("../lib/xapi.js");
const cmdargs = require('../lib/util/cmd.helper.js'); const cmdargs = require("../lib/util/cmd.helper.js");
const cluster = require('cluster'); const cluster = require("cluster");
const numCPUs = require('os').cpus().length; const numCPUs = require("os").cpus().length;
function startXmysql(sqlConfig) { function startXmysql(sqlConfig) {
/**************** START : setup express ****************/ /**************** START : setup express ****************/
let app = express(); let app = express();
app.use(morgan('tiny')); app.use(morgan("tiny"));
app.use(cors()); app.use(cors());
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ app.use(
extended: true bodyParser.urlencoded({
})); extended: true
})
);
/**************** END : setup express ****************/ /**************** END : setup express ****************/
/**************** START : setup mysql ****************/ /**************** START : setup mysql ****************/
let mysqlPool = mysql.createPool(sqlConfig); let mysqlPool = mysql.createPool(sqlConfig);
/**************** END : setup mysql ****************/ /**************** END : setup mysql ****************/
/**************** START : setup Xapi ****************/ /**************** START : setup Xapi ****************/
console.log(''); console.log("");
console.log(''); console.log("");
console.log(''); console.log("");
console.log(' Generating REST APIs at the speed of your thought.. '); console.log(" Generating REST APIs at the speed of your thought.. ");
console.log(''); console.log("");
let t = process.hrtime(); let t = process.hrtime();
let moreApis = new Xapi(sqlConfig, mysqlPool, app); let moreApis = new Xapi(sqlConfig, mysqlPool, app);
moreApis.init((err, results) => { moreApis.init((err, results) => {
app.listen(sqlConfig.portNumber, sqlConfig.ipAddress); app.listen(sqlConfig.portNumber, sqlConfig.ipAddress);
var t1 = process.hrtime(t); var t1 = process.hrtime(t);
var t2 = t1[0] + t1[1] / 1000000000; var t2 = t1[0] + t1[1] / 1000000000;
console.log(
console.log(" Xmysql took : %d seconds", dataHelp.round(t2, 1)); " Xmysql took : %d seconds",
console.log(" API's base URL : " + "localhost:" + sqlConfig.portNumber); dataHelp.round(t2, 1)
console.log(' '); );
console.log(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '); console.log(
" API's base URL : " +
"localhost:" +
sqlConfig.portNumber
);
console.log(" ");
console.log(
" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "
);
}); });
/**************** END : setup Xapi ****************/ /**************** END : setup Xapi ****************/
} }
function start(sqlConfig) { function start(sqlConfig) {
//handle cmd line arguments //handle cmd line arguments
cmdargs.handle(sqlConfig); cmdargs.handle(sqlConfig);
if (cluster.isMaster && sqlConfig.useCpuCores > 1) { if (cluster.isMaster && sqlConfig.useCpuCores > 1) {
console.log(`Master ${process.pid} is running`); console.log(`Master ${process.pid} is running`);
for (let i = 0; i < numCPUs && i < sqlConfig.useCpuCores; i++) { for (let i = 0; i < numCPUs && i < sqlConfig.useCpuCores; i++) {
@ -72,23 +73,21 @@ function start(sqlConfig) {
cluster.fork(); cluster.fork();
} }
cluster.on('exit', function(worker, code, signal) { cluster.on("exit", function(worker, code, signal) {
console.log('Worker ' + worker.process.pid + ' died with code: ' console.log(
+ code + ', and signal: ' + signal); "Worker " +
console.log('Starting a new worker'); worker.process.pid +
" died with code: " +
code +
", and signal: " +
signal
);
console.log("Starting a new worker");
cluster.fork(); cluster.fork();
}); });
} else { } else {
startXmysql(sqlConfig); startXmysql(sqlConfig);
} }
} }
start(sqlConfig); start(sqlConfig);

39
examples/aws-lambda/index.js

@ -8,7 +8,7 @@
* ** You need to put your lambda in a VPC * ** You need to put your lambda in a VPC
* ** The lambda role needs access to the VPC * ** The lambda role needs access to the VPC
* ** The RDS server has to be inside the VPC as well * ** The RDS server has to be inside the VPC as well
* *
* Performance: * Performance:
* * Requests to the API Gateway resolve in ~ 90ms * * Requests to the API Gateway resolve in ~ 90ms
* *
@ -20,30 +20,32 @@
*/ */
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", {value: true}); Object.defineProperty(exports, "__esModule", { value: true });
var bodyParser = require("body-parser"); var bodyParser = require("body-parser");
var express = require("express"); var express = require("express");
var serverless = require('serverless-http'); var serverless = require("serverless-http");
var cors = require("cors"); var cors = require("cors");
var mysql = require('mysql'); var mysql = require("mysql");
var Xapi = require('./node_modules/xmysql/lib/xapi.js'); var Xapi = require("./node_modules/xmysql/lib/xapi.js");
var morgan = require('morgan'); var morgan = require("morgan");
var app = express(); var app = express();
var onXapiInitialized = new Promise(function (resolve, reject) { var onXapiInitialized = new Promise(function(resolve, reject) {
try { try {
// /**************** START : setup express ****************/ // /**************** START : setup express ****************/
app.use(morgan('tiny')); app.use(morgan("tiny"));
app.use(cors()); app.use(cors());
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ app.use(
extended: true bodyParser.urlencoded({
})); extended: true
})
);
// /**************** END : setup express ****************/ // /**************** END : setup express ****************/
app.use(function (req, res, next) { app.use(function(req, res, next) {
// You can add authentication here // You can add authentication here
console.log('Received request for: ' + req.url, req); console.log("Received request for: " + req.url, req);
next(); next();
}); });
@ -53,8 +55,8 @@ var onXapiInitialized = new Promise(function (resolve, reject) {
database: config.mysql.database, database: config.mysql.database,
user: config.mysql.user, user: config.mysql.user,
password: config.mysql.password, password: config.mysql.password,
apiPrefix: '/', apiPrefix: "/",
ipAddress: 'localhost', ipAddress: "localhost",
portNumber: 3000, portNumber: 3000,
ignoreTables: [], ignoreTables: [],
storageFolder: __dirname storageFolder: __dirname
@ -62,18 +64,17 @@ var onXapiInitialized = new Promise(function (resolve, reject) {
var mysqlPool = mysql.createPool(mysqlConfig); var mysqlPool = mysql.createPool(mysqlConfig);
var xapi = new Xapi(mysqlConfig, mysqlPool, app); var xapi = new Xapi(mysqlConfig, mysqlPool, app);
xapi.init(function (err, results) { xapi.init(function(err, results) {
app.listen(3000); app.listen(3000);
resolve(); resolve();
}); });
} } catch (err) {
catch (err) {
reject(err); reject(err);
} }
}); });
function handler(event, context, callback) { function handler(event, context, callback) {
onXapiInitialized.then(function () { onXapiInitialized.then(function() {
serverless(app)(event, context, callback); serverless(app)(event, context, callback);
}); });
} }

96
index.js

@ -1,71 +1,72 @@
#! /usr/bin/env node #! /usr/bin/env node
const morgan = require('morgan'); const morgan = require("morgan");
const bodyParser = require('body-parser'); const bodyParser = require("body-parser");
const express = require('express'); const express = require("express");
const sqlConfig = require('commander'); const sqlConfig = require("commander");
const mysql = require('mysql'); const mysql = require("mysql");
const cors = require('cors'); const cors = require("cors");
const dataHelp = require('./lib/util/data.helper.js'); const dataHelp = require("./lib/util/data.helper.js");
const Xapi = require('./lib/xapi.js'); const Xapi = require("./lib/xapi.js");
const cmdargs = require('./lib/util/cmd.helper.js'); const cmdargs = require("./lib/util/cmd.helper.js");
const cluster = require('cluster'); const cluster = require("cluster");
const numCPUs = require('os').cpus().length; const numCPUs = require("os").cpus().length;
const { version } = require('./package.json'); const { version } = require("./package.json");
function startXmysql(sqlConfig) { function startXmysql(sqlConfig) {
/**************** START : setup express ****************/ /**************** START : setup express ****************/
let app = express(); let app = express();
app.set('version', version); app.set("version", version);
app.use(morgan('tiny')); app.use(morgan("tiny"));
app.use(cors()); app.use(cors());
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ app.use(
extended: true bodyParser.urlencoded({
})); extended: true
})
);
/**************** END : setup express ****************/ /**************** END : setup express ****************/
/**************** START : setup mysql ****************/ /**************** START : setup mysql ****************/
let mysqlPool = mysql.createPool(sqlConfig); let mysqlPool = mysql.createPool(sqlConfig);
/**************** END : setup mysql ****************/ /**************** END : setup mysql ****************/
/**************** START : setup Xapi ****************/ /**************** START : setup Xapi ****************/
console.log(''); console.log("");
console.log(''); console.log("");
console.log(''); console.log("");
console.log(' Generating REST APIs at the speed of your thought.. '); console.log(" Generating REST APIs at the speed of your thought.. ");
console.log(''); console.log("");
let t = process.hrtime(); let t = process.hrtime();
let moreApis = new Xapi(sqlConfig, mysqlPool, app); let moreApis = new Xapi(sqlConfig, mysqlPool, app);
moreApis.init((err, results) => { moreApis.init((err, results) => {
app.listen(sqlConfig.portNumber, sqlConfig.ipAddress); app.listen(sqlConfig.portNumber, sqlConfig.ipAddress);
var t1 = process.hrtime(t); var t1 = process.hrtime(t);
var t2 = t1[0] + t1[1] / 1000000000; var t2 = t1[0] + t1[1] / 1000000000;
console.log(
console.log(" Xmysql took : %d seconds", dataHelp.round(t2, 1)); " Xmysql took : %d seconds",
console.log(" API's base URL : " + "localhost:" + sqlConfig.portNumber); dataHelp.round(t2, 1)
console.log(' '); );
console.log(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '); console.log(
" API's base URL : " +
"localhost:" +
sqlConfig.portNumber
);
console.log(" ");
console.log(
" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "
);
}); });
/**************** END : setup Xapi ****************/ /**************** END : setup Xapi ****************/
} }
function start(sqlConfig) { function start(sqlConfig) {
cmdargs.handle(sqlConfig); cmdargs.handle(sqlConfig);
if (cluster.isMaster && sqlConfig.useCpuCores > 1) { if (cluster.isMaster && sqlConfig.useCpuCores > 1) {
console.log(`Master ${process.pid} is running`); console.log(`Master ${process.pid} is running`);
for (let i = 0; i < numCPUs && i < sqlConfig.useCpuCores; i++) { for (let i = 0; i < numCPUs && i < sqlConfig.useCpuCores; i++) {
@ -73,24 +74,21 @@ function start(sqlConfig) {
cluster.fork(); cluster.fork();
} }
cluster.on('exit', function(worker, code, signal) { cluster.on("exit", function(worker, code, signal) {
console.log('Worker ' + worker.process.pid + ' died with code: ' console.log(
+ code + ', and signal: ' + signal); "Worker " +
console.log('Starting a new worker'); worker.process.pid +
" died with code: " +
code +
", and signal: " +
signal
);
console.log("Starting a new worker");
cluster.fork(); cluster.fork();
}); });
} else { } else {
startXmysql(sqlConfig); startXmysql(sqlConfig);
} }
} }
start(sqlConfig); start(sqlConfig);

116
lib/util/cmd.helper.js

@ -1,101 +1,107 @@
'use strict'; "use strict";
const program = require('commander'); const program = require("commander");
const colors = require('colors'); const colors = require("colors");
const maxCpus = require('os').cpus().length; const maxCpus = require("os").cpus().length;
program.on("--help", () => {
program.on('--help', () => { console.log("");
console.log('') console.log(" Examples:".blue);
console.log(' Examples:'.blue) console.log("");
console.log('') console.log(" $ xmysql -u username -p password -d databaseSchema".blue);
console.log(' $ xmysql -u username -p password -d databaseSchema'.blue) console.log("");
console.log('') });
})
program program
.version(module.exports.version) .version(module.exports.version)
.option('-h, --host <n>', 'hostname of database / localhost by default') .option("-h, --host <n>", "hostname of database / localhost by default")
.option('-u, --user <n>', 'username of database / root by default') .option("-u, --user <n>", "username of database / root by default")
.option('-p, --password <n>', 'password of database / empty by default') .option("-p, --password <n>", "password of database / empty by default")
.option('-d, --database <n>', 'database schema name') .option("-d, --database <n>", "database schema name")
.option('-r, --ipAddress <n>', 'IP interface of your server / localhost by default') .option(
.option('-n, --portNumber <n>', 'port number for app / 3000 by default') "-r, --ipAddress <n>",
.option('-o, --port <n>', 'port number for mysql / 3306 by default') "IP interface of your server / localhost by default"
.option('-S, --socketPath <n>', 'unix socket path / not used by default') )
.option('-s, --storageFolder <n>', 'storage folder / current working dir by default / available only with local') .option("-n, --portNumber <n>", "port number for app / 3000 by default")
.option('-i, --ignoreTables <n>', 'comma separated table names to ignore') .option("-o, --port <n>", "port number for mysql / 3306 by default")
.option('-a, --apiPrefix <n>', 'api url prefix / "/api/" by default') .option("-S, --socketPath <n>", "unix socket path / not used by default")
.option('-y, --readOnly', 'readonly apis / false by default') .option(
.option('-c, --useCpuCores <n>', 'use number of CPU cores (using cluster) / 1 by default') "-s, --storageFolder <n>",
.parse(process.argv) "storage folder / current working dir by default / available only with local"
)
.option("-i, --ignoreTables <n>", "comma separated table names to ignore")
.option("-a, --apiPrefix <n>", 'api url prefix / "/api/" by default')
.option("-y, --readOnly", "readonly apis / false by default")
.option(
"-c, --useCpuCores <n>",
"use number of CPU cores (using cluster) / 1 by default"
)
.parse(process.argv);
function paintHelp(txt) { 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) { function processInvalidArguments(program) {
let err = "";
let err = '';
if (!program.password) { if (!program.password) {
err += 'Error: password for database is missing\n'; err += "Error: password for database is missing\n";
} }
if (!program.database) { if (!program.database) {
err += 'Error: database name is missing\n'; err += "Error: database name is missing\n";
} }
if (err !== '') { if (err !== "") {
program.outputHelp(paintHelp) program.outputHelp(paintHelp);
console.log(err.red) console.log(err.red);
} }
} }
exports.handle = program => { exports.handle = program => {
/**************** START : default values ****************/ /**************** START : default values ****************/
program.ipAddress = program.ipAddress || 'localhost'; program.ipAddress = program.ipAddress || "localhost";
program.portNumber = program.portNumber || 3000; program.portNumber = program.portNumber || 3000;
program.port = program.port || 3306; program.port = program.port || 3306;
program.user = program.user || 'root'; program.user = program.user || "root";
program.password = program.password || ''; program.password = program.password || "";
program.host = program.host || 'localhost'; program.host = program.host || "localhost";
program.socketPath = program.socketPath || ''; program.socketPath = program.socketPath || "";
program.storageFolder = program.storageFolder || process.cwd() program.storageFolder = program.storageFolder || process.cwd();
program.apiPrefix = program.apiPrefix || '/api/' program.apiPrefix = program.apiPrefix || "/api/";
program.readOnly = program.readOnly || false; program.readOnly = program.readOnly || false;
program.useCpuCores = program.useCpuCores || 1; program.useCpuCores = program.useCpuCores || 1;
if(program.useCpuCores === '0') { if (program.useCpuCores === "0") {
program.useCpuCores = maxCpus; program.useCpuCores = maxCpus;
} }
if (program.ignoreTables) { if (program.ignoreTables) {
let ignoreTables = program.ignoreTables.split(',') let ignoreTables = program.ignoreTables.split(",");
program.ignoreTables = {} program.ignoreTables = {};
for (var i = 0; i < ignoreTables.length; ++i) { for (var i = 0; i < ignoreTables.length; ++i) {
program.ignoreTables[ignoreTables[i]] = ignoreTables[i]; program.ignoreTables[ignoreTables[i]] = ignoreTables[i];
} }
} else { } else {
program.ignoreTables = {} program.ignoreTables = {};
} }
program.connectionLimit = 10; program.connectionLimit = 10;
if (program.host === 'localhost' || program.host === '127.0.0.1' || program.host === '::1') { if (
program.dynamic = 1 program.host === "localhost" ||
program.host === "127.0.0.1" ||
program.host === "::1"
) {
program.dynamic = 1;
} }
// console.log(program); // console.log(program);
/**************** END : default values ****************/ /**************** END : default values ****************/
if (program.database && program.host && program.user) { if (program.database && program.host && program.user) {
//console.log('Starting server at:', 'http://' + program.host + ':' + program.portNumber) //console.log('Starting server at:', 'http://' + program.host + ':' + program.portNumber)
} else { } else {
processInvalidArguments(program) processInvalidArguments(program);
process.exit(1) process.exit(1);
} }
}; };

192
lib/util/data.helper.js

@ -1,8 +1,6 @@
'use strict'; "use strict";
exports.findOrInsertObjectArrayByKey = (obj, key, array) => { exports.findOrInsertObjectArrayByKey = (obj, key, array) => {
let found = 0; let found = 0;
let i = 0; let i = 0;
@ -16,15 +14,13 @@ exports.findOrInsertObjectArrayByKey = (obj, key, array) => {
} }
if (!found) { if (!found) {
array.push(obj) array.push(obj);
} }
return array[i]; return array[i];
}; };
exports.findObjectInArrayByKey = (key, value, objArray) => { exports.findObjectInArrayByKey = (key, value, objArray) => {
for (let i = 0; i < objArray.length; ++i) { for (let i = 0; i < objArray.length; ++i) {
if (objArray[i][key] === value) { if (objArray[i][key] === value) {
return objArray[i]; return objArray[i];
@ -34,24 +30,21 @@ exports.findObjectInArrayByKey = (key, value, objArray) => {
return null; return null;
}; };
exports.round = function(number, precision) {
exports.round = function (number, precision) {
var factor = Math.pow(10, precision); var factor = Math.pow(10, precision);
var tempNumber = number * factor; var tempNumber = number * factor;
var roundedTempNumber = Math.round(tempNumber); var roundedTempNumber = Math.round(tempNumber);
return roundedTempNumber / factor; return roundedTempNumber / factor;
}; };
exports.numberRound = (number, precision) => { exports.numberRound = (number, precision) => {
var factor = Math.pow(10, precision); var factor = Math.pow(10, precision);
var tempNumber = number * factor; var tempNumber = number * factor;
var roundedTempNumber = Math.round(tempNumber); var roundedTempNumber = Math.round(tempNumber);
return roundedTempNumber / factor; return roundedTempNumber / factor;
} };
exports.numberGetLength = (number) => {
exports.numberGetLength = number => {
var n = number; var n = number;
if (number < 0) { if (number < 0) {
@ -59,109 +52,103 @@ exports.numberGetLength = (number) => {
} }
return n.toString().length; return n.toString().length;
} };
exports.numberGetFixed = (number) => { exports.numberGetFixed = number => {
//console.log(number, typeof number); //console.log(number, typeof number);
return parseInt(number.toFixed()) return parseInt(number.toFixed());
} };
exports.getStepArraySimple = function (min, max, step) {
var arr = [] exports.getStepArraySimple = function(min, max, step) {
var arr = [];
for (var i = min; i <= max; i = i + step) { for (var i = min; i <= max; i = i + step) {
arr.push(i) arr.push(i);
} }
return arr; return arr;
}; };
exports.getStepArray = (min, max, stddev) => { exports.getStepArray = (min, max, stddev) => {
// console.log(' = = = = = = = '); // console.log(' = = = = = = = ');
//console.log('original numbers', min, max, stddev); //console.log('original numbers', min, max, stddev);
min = this.numberGetFixed(min) min = this.numberGetFixed(min);
max = this.numberGetFixed(max) max = this.numberGetFixed(max);
stddev = this.numberGetFixed(stddev) stddev = this.numberGetFixed(stddev);
// console.log('fixed numbers', min, max, stddev); // console.log('fixed numbers', min, max, stddev);
let minMinusHalf = min - stddev / 2 let minMinusHalf = min - stddev / 2;
let maxMinusHalf = max + stddev / 2 let maxMinusHalf = max + stddev / 2;
minMinusHalf = this.numberGetFixed(minMinusHalf) minMinusHalf = this.numberGetFixed(minMinusHalf);
maxMinusHalf = this.numberGetFixed(maxMinusHalf) maxMinusHalf = this.numberGetFixed(maxMinusHalf);
// console.log('fixed numbers + (min,max)', min, max, stddev, '(', minMinusHalf, ',', 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)); // console.log('numbers length', 'min', numberGetLength(min), 'max', numberGetLength(max), 'stddev', numberGetLength(stddev));
let minLen = this.numberGetLength(minMinusHalf) let minLen = this.numberGetLength(minMinusHalf);
let maxLen = this.numberGetLength(maxMinusHalf) let maxLen = this.numberGetLength(maxMinusHalf);
let stddevLen = this.numberGetLength(stddev) let stddevLen = this.numberGetLength(stddev);
// //
// console.log('- - - -'); // console.log('- - - -');
// console.log('Range', 'min', numberRound(minMinusHalf, -1)); // console.log('Range', 'min', numberRound(minMinusHalf, -1));
// console.log('Range', 'max', numberRound(maxMinusHalf, -1)); // console.log('Range', 'max', numberRound(maxMinusHalf, -1));
// console.log('Range', 'stddev', numberRound(stddev, -1)); // console.log('Range', 'stddev', numberRound(stddev, -1));
if (minLen > 1) if (minLen > 1) minMinusHalf = this.numberRound(minMinusHalf, -1);
minMinusHalf = this.numberRound(minMinusHalf, -1)
if (maxLen > 2)
maxMinusHalf = this.numberRound(maxMinusHalf, -1)
if (stddevLen !== 1) if (maxLen > 2) maxMinusHalf = this.numberRound(maxMinusHalf, -1);
stddev = this.numberRound(stddev, -1)
if (stddevLen !== 1) stddev = this.numberRound(stddev, -1);
var arr = [] var arr = [];
for (var step = minMinusHalf; step < maxMinusHalf; step = step + stddev) { for (var step = minMinusHalf; step < maxMinusHalf; step = step + stddev) {
arr.push(step) arr.push(step);
} }
arr.push(maxMinusHalf) arr.push(maxMinusHalf);
// console.log(arr); // console.log(arr);
return 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 () { exports.getSchemaQuery = function() {
return 'select ? as ??, count(*) as _count from ?? where ?? between ? and ? ' 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) { exports.getDataType = function(colType, typesArr) {
// console.log(colType,typesArr); // console.log(colType,typesArr);
@ -171,29 +158,40 @@ exports.getDataType = function(colType, typesArr) {
} }
} }
return 0; return 0;
} };
exports.getColumnType = function (column) {
let strTypes = ['varchar', 'text', 'char', 'tinytext', 'mediumtext', 'longtext', 'blob', 'mediumblob', 'longblob', 'tinyblob', 'binary', 'varbinary']; exports.getColumnType = function(column) {
let intTypes = ['int', 'long', 'smallint', 'mediumint', 'bigint', 'tinyint']; let strTypes = [
let flatTypes = ['float', 'double', 'decimal']; "varchar",
let dateTypes = ['date', 'datetime', 'timestamp', 'time', 'year']; "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); //console.log(column);
if (this.getDataType(column['data_type'], strTypes)) { if (this.getDataType(column["data_type"], strTypes)) {
return "string" return "string";
} else if (this.getDataType(column['data_type'], intTypes)) { } else if (this.getDataType(column["data_type"], intTypes)) {
return "int" return "int";
} else if (this.getDataType(column['data_type'], flatTypes)) { } else if (this.getDataType(column["data_type"], flatTypes)) {
return "float" return "float";
} else if (this.getDataType(column['data_type'], dateTypes)) { } else if (this.getDataType(column["data_type"], dateTypes)) {
return "date" return "date";
} else { } else {
return "string" return "string";
} }
};
}
exports.getType = function(colType, typesArr) { exports.getType = function(colType, typesArr) {
for (let i = 0; i < typesArr.length; ++i) { for (let i = 0; i < typesArr.length; ++i) {
@ -206,6 +204,4 @@ exports.getType = function(colType, typesArr) {
} }
} }
return 0; return 0;
} };

274
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] * @returns obj.query = (?,?,?,?) obj.params = [1,2,3,4]
*/ */
function prepareInClauseParams(input) { function prepareInClauseParams(input) {
let inElems = input.split(",");
let inElems = input.split(',') let obj = {};
let obj = {} obj.whereQuery = "";
obj.whereQuery = '' obj.whereParams = [];
obj.whereParams = []
for (var j = 0; j < inElems.length; ++j) { for (var j = 0; j < inElems.length; ++j) {
if (j === 0) { if (j === 0) {
//enclose with open parenthesis //enclose with open parenthesis
obj.whereQuery += '(' obj.whereQuery += "(";
} }
if (j) { if (j) {
obj.whereQuery += ',' obj.whereQuery += ",";
} }
// add q mark and push the variable // add q mark and push the variable
obj.whereQuery += '?' obj.whereQuery += "?";
obj.whereParams.push(inElems[j]) obj.whereParams.push(inElems[j]);
if (j === inElems.length - 1) { if (j === inElems.length - 1) {
//enclose with closing parenthesis //enclose with closing parenthesis
obj.whereQuery += ')' obj.whereQuery += ")";
} }
} }
//console.log(obj); //console.log(obj);
return obj return obj;
} }
function prepareLikeValue(value) { function prepareLikeValue(value) {
//return value.replace("~", "%"); //return value.replace("~", "%");
return value.replace(/~/g, '%'); return value.replace(/~/g, "%");
} }
function prepareIsValue(value) { function prepareIsValue(value) {
//return value.replace("~", "%"); //return value.replace("~", "%");
if (value === 'null') { if (value === "null") {
return null; return null;
} else if (value === 'true') { } else if (value === "true") {
return true; return true;
} else if (value === 'false') { } else if (value === "false") {
return false; return false;
} else { } else {
return null return null;
} }
} }
function prepareBetweenValue(value) { function prepareBetweenValue(value) {
let values = value.split(",");
let values = value.split(',') let obj = {};
let obj = {} obj.whereQuery = "";
obj.whereQuery = '' obj.whereParams = [];
obj.whereParams = []
if (values.length === 2) { if (values.length === 2) {
obj.whereQuery = ' ? and ? ' obj.whereQuery = " ? and ? ";
obj.whereParams.push(values[0]) obj.whereParams.push(values[0]);
obj.whereParams.push(values[1]) obj.whereParams.push(values[1]);
} }
//console.log('prepareBetweenValue', obj); //console.log('prepareBetweenValue', obj);
@ -77,75 +69,78 @@ function prepareBetweenValue(value) {
return obj; return obj;
} }
function replaceWhereParamsToQMarks(
function replaceWhereParamsToQMarks(openParentheses, str, comparisonOperator, condType) { openParentheses,
str,
let converted = '' comparisonOperator,
condType
) {
let converted = "";
if (openParentheses) { if (openParentheses) {
for (var i = 0; i < str.length; ++i) { for (var i = 0; i < str.length; ++i) {
if (str[i] === '(') { if (str[i] === "(") {
converted += '(' converted += "(";
} else { } else {
converted += '??' converted += "??";
break; break;
} }
} }
} else { } else {
if (
if (comparisonOperator !== ' in ' && comparisonOperator !== ' between ' && condType !== ' on ') { comparisonOperator !== " in " &&
converted = '?' comparisonOperator !== " between " &&
} else if (condType === ' on ') { condType !== " on "
converted = '??' ) {
converted = "?";
} else if (condType === " on ") {
converted = "??";
} }
for (var i = str.length - 1; i >= 0; --i) { for (var i = str.length - 1; i >= 0; --i) {
if (str[i] === ')') { if (str[i] === ")") {
converted += ')' converted += ")";
} else { } else {
break; break;
} }
} }
} }
return converted; return converted;
} }
function getComparisonOperator(operator) { function getComparisonOperator(operator) {
switch (operator) { switch (operator) {
case "eq":
case 'eq': return "=";
return '='
break; break;
case 'ne': case "ne":
return '!=' return "!=";
break; break;
case 'lt': case "lt":
return '<' return "<";
break; break;
case 'lte': case "lte":
return '<=' return "<=";
break; break;
case 'gt': case "gt":
return '>' return ">";
break; break;
case 'gte': case "gte":
return '>=' return ">=";
break; break;
case 'is': case "is":
return ' is ' return " is ";
break; break;
case 'isnot': case "isnot":
return ' is not ' return " is not ";
break; break;
// case 'isnull': // case 'isnull':
@ -156,89 +151,90 @@ function getComparisonOperator(operator) {
// return ' is not NULL ' // return ' is not NULL '
// break; // break;
case 'like': case "like":
return ' like ' return " like ";
break; break;
case 'nlike': case "nlike":
return ' not like ' return " not like ";
break; break;
case 'in': case "in":
return ' in ' return " in ";
break; break;
case 'bw': case "bw":
return ' between ' return " between ";
break; break;
default: default:
return null return null;
break; break;
} }
} }
function getLogicalOperator(operator) { function getLogicalOperator(operator) {
switch (operator) { switch (operator) {
case "~or":
case '~or': return "or";
return 'or'
break; break;
case '~and': case "~and":
return 'and' return "and";
break; break;
// case '~not': // case '~not':
// return 'not' // return 'not'
// break; // break;
case '~xor': case "~xor":
return 'xor' return "xor";
break; break;
default: default:
return null return null;
break; break;
} }
} }
exports.getConditionClause = function(whereInQueryParams, condType = "where") {
exports.getConditionClause = function (whereInQueryParams, condType = 'where') { let whereQuery = "";
let whereQuery = '';
let whereParams = []; let whereParams = [];
let grammarErr = 0; let grammarErr = 0;
let numOfConditions = whereInQueryParams.split(/~or|~and|~not|~xor/); let numOfConditions = whereInQueryParams.split(/~or|~and|~not|~xor/);
let logicalOperatorsInClause = whereInQueryParams.match(/(~or|~and|~not|~xor)/g) 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);
if (
numOfConditions &&
logicalOperatorsInClause &&
numOfConditions.length !== logicalOperatorsInClause.length + 1
) {
console.log(
"conditions and logical operators mismatch",
numOfConditions.length,
logicalOperatorsInClause.length
);
} else { } else {
//console.log('numOfConditions',numOfConditions,whereInQueryParams); //console.log('numOfConditions',numOfConditions,whereInQueryParams);
//console.log('logicalOperatorsInClause',logicalOperatorsInClause); //console.log('logicalOperatorsInClause',logicalOperatorsInClause);
for (var i = 0; i < numOfConditions.length; ++i) { for (var i = 0; i < numOfConditions.length; ++i) {
let variable = "";
let variable = '' let comparisonOperator = "";
let comparisonOperator = '' let logicalOperator = "";
let logicalOperator = '' let variableValue = "";
let variableValue = '' let temp = "";
let temp = ''
// split on commas // split on commas
var arr = numOfConditions[i].split(','); var arr = numOfConditions[i].split(",");
// consider first two splits only // consider first two splits only
var result = arr.splice(0, 2); var result = arr.splice(0, 2);
// join to make only 3 array elements // join to make only 3 array elements
result.push(arr.join(',')); result.push(arr.join(","));
// variable, operator, variablevalue // variable, operator, variablevalue
if (result.length !== 3) { if (result.length !== 3) {
@ -258,81 +254,86 @@ exports.getConditionClause = function (whereInQueryParams, condType = 'where') {
} }
// get the variableName and push // get the variableName and push
whereParams.push(variable[1]) whereParams.push(variable[1]);
// then replace the variable name with ?? // then replace the variable name with ??
temp = replaceWhereParamsToQMarks(true, result[0], ' ignore ', condType) temp = replaceWhereParamsToQMarks(true, result[0], " ignore ", condType);
if (!temp) { if (!temp) {
grammarErr = 1; grammarErr = 1;
break; break;
} }
whereQuery += temp whereQuery += temp;
/**************** END : variable ****************/ /**************** END : variable ****************/
/**************** START : operator and value ****************/ /**************** START : operator and value ****************/
comparisonOperator = getComparisonOperator(result[1]) comparisonOperator = getComparisonOperator(result[1]);
if (!comparisonOperator) { if (!comparisonOperator) {
grammarErr = 1; grammarErr = 1;
break; break;
} }
whereQuery += comparisonOperator whereQuery += comparisonOperator;
// get the variableValue and push to params // get the variableValue and push to params
variableValue = result[2].match(/(.*?)\)/) variableValue = result[2].match(/(.*?)\)/);
if (!variableValue || variableValue.length !== 2) { if (!variableValue || variableValue.length !== 2) {
grammarErr = 1; grammarErr = 1;
break; break;
} }
if (comparisonOperator === ' in ') { if (comparisonOperator === " in ") {
let obj = prepareInClauseParams(variableValue[1]) let obj = prepareInClauseParams(variableValue[1]);
whereQuery += obj.whereQuery whereQuery += obj.whereQuery;
whereParams = whereParams.concat(obj.whereParams) whereParams = whereParams.concat(obj.whereParams);
} else if (comparisonOperator === ' like ' || comparisonOperator === ' not like ') { } else if (
whereParams.push(prepareLikeValue(variableValue[1])) comparisonOperator === " like " ||
} else if (comparisonOperator === ' is ') { comparisonOperator === " not like "
whereParams.push(prepareIsValue(variableValue[1])) ) {
} else if (comparisonOperator === ' between ') { whereParams.push(prepareLikeValue(variableValue[1]));
let obj = prepareBetweenValue(variableValue[1]) } else if (comparisonOperator === " is ") {
whereQuery += obj.whereQuery whereParams.push(prepareIsValue(variableValue[1]));
whereParams = whereParams.concat(obj.whereParams) } else if (comparisonOperator === " between ") {
let obj = prepareBetweenValue(variableValue[1]);
whereQuery += obj.whereQuery;
whereParams = whereParams.concat(obj.whereParams);
//console.log(whereQuery, whereParams); //console.log(whereQuery, whereParams);
} else { } else {
whereParams.push(variableValue[1]) whereParams.push(variableValue[1]);
} }
// then replace the variableValue with ? // then replace the variableValue with ?
temp = replaceWhereParamsToQMarks(false, result[2], comparisonOperator, condType) temp = replaceWhereParamsToQMarks(
false,
result[2],
comparisonOperator,
condType
);
if (!temp) { if (!temp) {
grammarErr = 1; grammarErr = 1;
break; break;
} }
whereQuery += temp whereQuery += temp;
if (numOfConditions.length !== -1 && i !== numOfConditions.length - 1) { if (numOfConditions.length !== -1 && i !== numOfConditions.length - 1) {
//console.log('finding logical operator for',logicalOperatorsInClause[i]); //console.log('finding logical operator for',logicalOperatorsInClause[i]);
logicalOperator = getLogicalOperator(logicalOperatorsInClause[i]) logicalOperator = getLogicalOperator(logicalOperatorsInClause[i]);
if (!logicalOperator) { if (!logicalOperator) {
grammarErr = 1; grammarErr = 1;
break; break;
} }
whereQuery += getLogicalOperator(logicalOperatorsInClause[i]) whereQuery += getLogicalOperator(logicalOperatorsInClause[i]);
} }
/**************** END : operator ****************/ /**************** END : operator ****************/
} }
} }
let obj = {} let obj = {};
obj['query'] = '' obj["query"] = "";
obj['params'] = [] obj["params"] = [];
obj['err'] = grammarErr obj["err"] = grammarErr;
// console.log(whereInQueryParams); // console.log(whereInQueryParams);
// console.log(whereQuery); // console.log(whereQuery);
@ -341,10 +342,9 @@ exports.getConditionClause = function (whereInQueryParams, condType = 'where') {
// console.log('= = = = = = = = ='); // console.log('= = = = = = = = =');
if (!grammarErr) { if (!grammarErr) {
obj['query'] = whereQuery obj["query"] = whereQuery;
obj['params'] = whereParams obj["params"] = whereParams;
} }
return obj return obj;
};
}

443
lib/xapi.js

@ -1,380 +1,424 @@
'use strict'; "use strict";
var Xsql = require('./xsql.js'); var Xsql = require("./xsql.js");
var Xctrl = require('./xctrl.js'); var Xctrl = require("./xctrl.js");
var multer = require('multer'); var multer = require("multer");
const path = require('path'); const path = require("path");
const v8 = require('v8'), const v8 = require("v8"),
os = require('os'); os = require("os");
//define class //define class
class Xapi { class Xapi {
constructor(args, mysqlPool, app) { constructor(args, mysqlPool, app) {
this.config = args; this.config = args;
this.mysql = new Xsql(args, mysqlPool) this.mysql = new Xsql(args, mysqlPool);
this.app = app; this.app = app;
this.ctrls = []; this.ctrls = [];
/**************** START : multer ****************/ /**************** START : multer ****************/
this.storage = multer.diskStorage({ this.storage = multer.diskStorage({
destination: function (req, file, cb) { destination: function(req, file, cb) {
cb(null, process.cwd()) cb(null, process.cwd());
}, },
filename: function (req, file, cb) { filename: function(req, file, cb) {
console.log(file); 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 ****************/ /**************** END : multer ****************/
} }
init(cbk) { init(cbk) {
this.mysql.init((err, results) => { this.mysql.init((err, results) => {
this.app.use(this.urlMiddleware.bind(this));
this.app.use(this.urlMiddleware.bind(this)) let stat = this.setupRoutes();
let stat = this.setupRoutes() this.app.use(this.errorMiddleware.bind(this));
this.app.use(this.errorMiddleware.bind(this)) cbk(err, stat);
cbk(err, stat) });
})
} }
urlMiddleware(req, res, next) { urlMiddleware(req, res, next) {
// get only request url from originalUrl // get only request url from originalUrl
let justUrl = req.originalUrl.split('?')[0] let justUrl = req.originalUrl.split("?")[0];
let pathSplit = [] let pathSplit = [];
// split by apiPrefix // split by apiPrefix
let apiSuffix = justUrl.split(this.config.apiPrefix) let apiSuffix = justUrl.split(this.config.apiPrefix);
if (apiSuffix.length === 2) { if (apiSuffix.length === 2) {
// split by / // split by /
pathSplit = apiSuffix[1].split('/') pathSplit = apiSuffix[1].split("/");
if (pathSplit.length) { if (pathSplit.length) {
if (pathSplit.length >= 3) { if (pathSplit.length >= 3) {
// handle for relational routes // handle for relational routes
req.app.locals._parentTable = pathSplit[0] req.app.locals._parentTable = pathSplit[0];
req.app.locals._childTable = pathSplit[2] req.app.locals._childTable = pathSplit[2];
} else { } else {
// handles rest of routes // handles rest of routes
req.app.locals._tableName = pathSplit[0] req.app.locals._tableName = pathSplit[0];
} }
} }
} }
next(); next();
} }
errorMiddleware(err, req, res, 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) else if (err && err.message)
res.status(500).json({error: 'Internal server error : ' + err.message}); res.status(500).json({ error: "Internal server error : " + err.message });
else else res.status(500).json({ error: "Internal server error : " + err });
res.status(500).json({error: 'Internal server error : ' + err});
next(err); next(err);
} }
asyncMiddleware(fn) { asyncMiddleware(fn) {
return (req, res, next) => { return (req, res, next) => {
Promise.resolve(fn(req, res, next)) Promise.resolve(fn(req, res, next)).catch(err => {
.catch((err) => { next(err);
next(err); });
}); };
}
} }
root(req, res) { root(req, res) {
let routes = []; let routes = [];
routes = this.mysql.getSchemaRoutes(false, req.protocol + '://' + req.get('host') + this.config.apiPrefix); routes = this.mysql.getSchemaRoutes(
routes = routes.concat(this.mysql.globalRoutesPrint(req.protocol + '://' + req.get('host') + this.config.apiPrefix)) false,
res.json(routes) 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() { setupRoutes() {
let stat = {};
let stat = {} stat.tables = 0;
stat.tables = 0 stat.apis = 0;
stat.apis = 0
// console.log('this.config while setting up routes', this.config); // console.log('this.config while setting up routes', this.config);
// show routes for database schema // 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 // show all resouces
this.app.route(this.config.apiPrefix + 'tables') this.app
.route(this.config.apiPrefix + "tables")
.get(this.asyncMiddleware(this.tables.bind(this))); .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))); .get(this.asyncMiddleware(this.xjoin.bind(this)));
stat.apis += 3; stat.apis += 3;
/**************** START : setup routes for each table ****************/ /**************** START : setup routes for each table ****************/
let resources = []; let resources = [];
resources = this.mysql.getSchemaRoutes(true, this.config.apiPrefix); resources = this.mysql.getSchemaRoutes(true, this.config.apiPrefix);
stat.tables += resources.length stat.tables += resources.length;
// iterate over each resource // iterate over each resource
for (var j = 0; j < resources.length; ++j) { 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); 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 // iterate over each routes in resource and map function
for (var i = 0; i < routes.length; ++i) { for (var i = 0; i < routes.length; ++i) {
switch (routes[i]["routeType"]) {
switch (routes[i]['routeType']) { case "list":
this.app
case 'list': .route(routes[i]["routeUrl"])
this.app.route(routes[i]['routeUrl'])
.get(this.asyncMiddleware(resourceCtrl.list.bind(resourceCtrl))); .get(this.asyncMiddleware(resourceCtrl.list.bind(resourceCtrl)));
break; break;
case 'findOne': case "findOne":
this.app.route(routes[i]['routeUrl']) this.app
.get(this.asyncMiddleware(resourceCtrl.findOne.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.get(
this.asyncMiddleware(resourceCtrl.findOne.bind(resourceCtrl))
);
break; break;
case 'create': case "create":
if (!this.config.readOnly) if (!this.config.readOnly)
this.app.route(routes[i]['routeUrl']) this.app
.post(this.asyncMiddleware(resourceCtrl.create.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.post(
this.asyncMiddleware(resourceCtrl.create.bind(resourceCtrl))
);
break; break;
case 'read': case "read":
this.app.route(routes[i]['routeUrl']) this.app
.route(routes[i]["routeUrl"])
.get(this.asyncMiddleware(resourceCtrl.read.bind(resourceCtrl))); .get(this.asyncMiddleware(resourceCtrl.read.bind(resourceCtrl)));
break; break;
case 'bulkInsert': case "bulkInsert":
if (!this.config.readOnly) { if (!this.config.readOnly) {
this.app.route(routes[i]['routeUrl']) this.app
.post(this.asyncMiddleware(resourceCtrl.bulkInsert.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.post(
this.asyncMiddleware(
resourceCtrl.bulkInsert.bind(resourceCtrl)
)
);
} }
break; break;
case 'bulkRead': case "bulkRead":
if (!this.config.readOnly){ if (!this.config.readOnly) {
this.app.route(routes[i]['routeUrl']) this.app
.get(this.asyncMiddleware(resourceCtrl.bulkRead.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.get(
this.asyncMiddleware(resourceCtrl.bulkRead.bind(resourceCtrl))
);
} else { } else {
stat.apis--; stat.apis--;
} }
break; break;
case 'bulkDelete': case "bulkDelete":
if (!this.config.readOnly){ if (!this.config.readOnly) {
this.app.route(routes[i]['routeUrl']) this.app
.delete(this.asyncMiddleware(resourceCtrl.bulkDelete.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.delete(
this.asyncMiddleware(
resourceCtrl.bulkDelete.bind(resourceCtrl)
)
);
} else { } else {
stat.apis--; stat.apis--;
} }
break; break;
case 'patch': case "patch":
if (!this.config.readOnly){ if (!this.config.readOnly) {
this.app.route(routes[i]['routeUrl']) this.app
.patch(this.asyncMiddleware(resourceCtrl.patch.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.patch(
this.asyncMiddleware(resourceCtrl.patch.bind(resourceCtrl))
);
} else { } else {
stat.apis--; stat.apis--;
} }
break; break;
case 'update': case "update":
if (!this.config.readOnly){ if (!this.config.readOnly) {
this.app.route(routes[i]['routeUrl']) this.app
.put(this.asyncMiddleware(resourceCtrl.update.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.put(
this.asyncMiddleware(resourceCtrl.update.bind(resourceCtrl))
);
} else { } else {
stat.apis--; stat.apis--;
} }
break; break;
case 'delete': case "delete":
if (!this.config.readOnly){ if (!this.config.readOnly) {
this.app.route(routes[i]['routeUrl']) this.app
.delete(this.asyncMiddleware(resourceCtrl.delete.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.delete(
this.asyncMiddleware(resourceCtrl.delete.bind(resourceCtrl))
);
} else { } else {
stat.apis--; stat.apis--;
} }
break; break;
case 'exists': case "exists":
this.app.route(routes[i]['routeUrl']) this.app
.get(this.asyncMiddleware(resourceCtrl.exists.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.get(
this.asyncMiddleware(resourceCtrl.exists.bind(resourceCtrl))
);
break; break;
case 'count': case "count":
this.app.route(routes[i]['routeUrl']) this.app
.route(routes[i]["routeUrl"])
.get(this.asyncMiddleware(resourceCtrl.count.bind(resourceCtrl))); .get(this.asyncMiddleware(resourceCtrl.count.bind(resourceCtrl)));
break; break;
case 'distinct': case "distinct":
this.app.route(routes[i]['routeUrl']) this.app
.get(this.asyncMiddleware(resourceCtrl.distinct.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.get(
this.asyncMiddleware(resourceCtrl.distinct.bind(resourceCtrl))
);
break; break;
case 'describe': case "describe":
this.app.route(routes[i]['routeUrl']) this.app
.route(routes[i]["routeUrl"])
.get(this.asyncMiddleware(this.tableDescribe.bind(this))); .get(this.asyncMiddleware(this.tableDescribe.bind(this)));
break; break;
case 'relational': case "relational":
this.app.route(routes[i]['routeUrl']) this.app
.get(this.asyncMiddleware(resourceCtrl.nestedList.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.get(
this.asyncMiddleware(resourceCtrl.nestedList.bind(resourceCtrl))
);
break; break;
case 'groupby': case "groupby":
this.app.route(routes[i]['routeUrl']) this.app
.get(this.asyncMiddleware(resourceCtrl.groupBy.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.get(
this.asyncMiddleware(resourceCtrl.groupBy.bind(resourceCtrl))
);
break; break;
case 'ugroupby': case "ugroupby":
this.app.route(routes[i]['routeUrl']) this.app
.get(this.asyncMiddleware(resourceCtrl.ugroupby.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.get(
this.asyncMiddleware(resourceCtrl.ugroupby.bind(resourceCtrl))
);
break; break;
case 'chart': case "chart":
this.app.route(routes[i]['routeUrl']) this.app
.route(routes[i]["routeUrl"])
.get(this.asyncMiddleware(resourceCtrl.chart.bind(resourceCtrl))); .get(this.asyncMiddleware(resourceCtrl.chart.bind(resourceCtrl)));
break; break;
case 'autoChart': case "autoChart":
this.app.route(routes[i]['routeUrl']) this.app
.get(this.asyncMiddleware(resourceCtrl.autoChart.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.get(
this.asyncMiddleware(resourceCtrl.autoChart.bind(resourceCtrl))
);
break; break;
case 'aggregate': case "aggregate":
this.app.route(routes[i]['routeUrl']) this.app
.get(this.asyncMiddleware(resourceCtrl.aggregate.bind(resourceCtrl))); .route(routes[i]["routeUrl"])
.get(
this.asyncMiddleware(resourceCtrl.aggregate.bind(resourceCtrl))
);
break; break;
} }
} }
} }
/**************** END : setup routes for each table ****************/ /**************** END : setup routes for each table ****************/
if (this.config.dynamic === 1 && !this.config.readOnly) { if (this.config.dynamic === 1 && !this.config.readOnly) {
this.app
this.app.route('/dynamic*') .route("/dynamic*")
.post(this.asyncMiddleware(this.runQuery.bind(this))); .post(this.asyncMiddleware(this.runQuery.bind(this)));
/**************** START : multer routes ****************/ /**************** START : multer routes ****************/
this.app.post('/upload', this.upload.single('file'), this.uploadFile.bind(this)); this.app.post(
this.app.post('/uploads', this.upload.array('files', 10), this.uploadFiles.bind(this)); "/upload",
this.app.get('/download', this.downloadFile.bind(this)); 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 ****************/ /**************** END : multer routes ****************/
stat.apis += 4; stat.apis += 4;
} }
/**************** START : health and version ****************/ /**************** START : health and version ****************/
this.app.get('/_health', this.asyncMiddleware(this.health.bind(this))); this.app.get("/_health", this.asyncMiddleware(this.health.bind(this)));
this.app.get('/_version', this.asyncMiddleware(this.version.bind(this))); this.app.get("/_version", this.asyncMiddleware(this.version.bind(this)));
stat.apis += 2; stat.apis += 2;
/**************** END : health and version ****************/ /**************** END : health and version ****************/
let statStr =
let statStr = ' Generated: ' + stat.apis + ' REST APIs for ' + stat.tables + ' tables ' " Generated: " +
stat.apis +
console.log(' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '); " REST APIs for " +
console.log(' '); stat.tables +
console.log(' Database : %s', this.config.database); " tables ";
console.log(' Number of Tables : %s', stat.tables);
console.log(' '); console.log(
console.log(' REST APIs Generated : %s'.green.bold, stat.apis); " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "
console.log(' '); );
console.log(" ");
return stat 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) { async xjoin(req, res) {
let obj = {};
let obj = {} obj.query = "";
obj.query = '';
obj.params = []; obj.params = [];
this.mysql.prepareJoinQuery(req, res, obj) this.mysql.prepareJoinQuery(req, res, obj);
//console.log(obj); //console.log(obj);
if (obj.query.length) { if (obj.query.length) {
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) res.status(200).json(results);
} else { } else {
res.status(400).json({err: 'Invalid Xjoin request'}); res.status(400).json({ err: "Invalid Xjoin request" });
} }
} }
async tableDescribe(req, res) { async tableDescribe(req, res) {
let query = "describe ??";
let query = 'describe ??';
let params = [req.app.locals._tableName]; let params = [req.app.locals._tableName];
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 tables(req, res) { async tables(req, res) {
let query =
let query = 'SELECT table_name AS resource FROM information_schema.tables WHERE table_schema = ? '; "SELECT table_name AS resource FROM information_schema.tables WHERE table_schema = ? ";
let params = [this.config.database]; let params = [this.config.database];
if (Object.keys(this.config.ignoreTables).length > 0) { if (Object.keys(this.config.ignoreTables).length > 0) {
query += 'and table_name not in (?)' query += "and table_name not in (?)";
params.push(Object.keys(this.config.ignoreTables)) 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) { async runQuery(req, res) {
let query = req.body.query; let query = req.body.query;
let params = req.body.params; let params = req.body.params;
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);
} }
/**************** START : files related ****************/ /**************** START : files related ****************/
downloadFile(req, res) { downloadFile(req, res) {
let file = path.join(process.cwd(), req.query.name); let file = path.join(process.cwd(), req.query.name);
@ -382,19 +426,17 @@ class Xapi {
} }
uploadFile(req, res) { uploadFile(req, res) {
if (req.file) { if (req.file) {
console.log(req.file.path); console.log(req.file.path);
res.end(req.file.path); res.end(req.file.path);
} else { } else {
res.end('upload failed'); res.end("upload failed");
} }
} }
uploadFiles(req, res) { uploadFiles(req, res) {
if (!req.files || req.files.length === 0) { if (!req.files || req.files.length === 0) {
res.end('upload failed') res.end("upload failed");
} else { } else {
let files = []; let files = [];
for (let i = 0; i < req.files.length; ++i) { for (let i = 0; i < req.files.length; ++i) {
@ -403,58 +445,49 @@ class Xapi {
res.end(files.toString()); res.end(files.toString());
} }
} }
/**************** END : files related ****************/ /**************** END : files related ****************/
/**************** START : health and version ****************/ /**************** START : health and version ****************/
async getMysqlUptime() { async getMysqlUptime() {
let v = await this.mysql.exec('SHOW GLOBAL STATUS LIKE \'Uptime\';', []); let v = await this.mysql.exec("SHOW GLOBAL STATUS LIKE 'Uptime';", []);
return v[0]['Value']; return v[0]["Value"];
} }
async getMysqlHealth() { async getMysqlHealth() {
let v = await this.mysql.exec('select version() as version', []); let v = await this.mysql.exec("select version() as version", []);
return v[0]['version']; return v[0]["version"];
} }
async health(req, res) { async health(req, res) {
let status = {}; let status = {};
status['process_uptime'] = process.uptime(); status["process_uptime"] = process.uptime();
status['mysql_uptime'] = await this.getMysqlUptime(); status["mysql_uptime"] = await this.getMysqlUptime();
if (Object.keys(req.query).length) { if (Object.keys(req.query).length) {
status['process_memory_usage'] = process.memoryUsage(); status["process_memory_usage"] = process.memoryUsage();
status['os_total_memory'] = os.totalmem(); status["os_total_memory"] = os.totalmem();
status['os_free_memory'] = os.freemem(); status["os_free_memory"] = os.freemem();
status['os_load_average'] = os.loadavg(); status["os_load_average"] = os.loadavg();
status['v8_heap_statistics'] = v8.getHeapStatistics(); status["v8_heap_statistics"] = v8.getHeapStatistics();
} }
res.json(status); res.json(status);
} }
async version(req, res) { async version(req, res) {
let version = {}; let version = {};
version['Xmysql'] = this.app.get('version'); version["Xmysql"] = this.app.get("version");
version['mysql'] = await this.getMysqlHealth(); version["mysql"] = await this.getMysqlHealth();
version['node'] = process.versions.node; version["node"] = process.versions.node;
res.json(version); res.json(version);
} }
/**************** END : health and version ****************/ /**************** END : health and version ****************/
} }
//expose class //expose class
module.exports = Xapi; module.exports = Xapi;

503
lib/xctrl.js

@ -1,16 +1,12 @@
//define class //define class
class xctrl { class xctrl {
constructor(app, mysql) {
constructor(app,mysql) {
this.app = app; this.app = app;
this.mysql = mysql; this.mysql = mysql;
} }
async create(req, res) { async create(req, res) {
let query = "INSERT INTO ?? SET ?";
let query = 'INSERT INTO ?? SET ?';
let params = []; let params = [];
params.push(req.app.locals._tableName); params.push(req.app.locals._tableName);
@ -18,105 +14,102 @@ class xctrl {
var results = await this.mysql.exec(query, params); var results = await this.mysql.exec(query, params);
res.status(200).json(results); res.status(200).json(results);
} }
async list(req, res) { async list(req, res) {
let queryParamsObj = {};
let queryParamsObj = {} queryParamsObj.query = "";
queryParamsObj.query = '' queryParamsObj.params = [];
queryParamsObj.params = []
this.mysql.prepareListQuery(req, res, queryParamsObj, 0); 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); res.status(200).json(results);
} }
async nestedList(req, res) { async nestedList(req, res) {
let queryParamsObj = {};
let queryParamsObj = {} queryParamsObj.query = "";
queryParamsObj.query = '';
queryParamsObj.params = []; 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); res.status(200).json(results);
} }
async findOne(req, res) { async findOne(req, res) {
let queryParamsObj = {};
let queryParamsObj = {} queryParamsObj.query = "";
queryParamsObj.query = '' queryParamsObj.params = [];
queryParamsObj.params = []
this.mysql.prepareListQuery(req, res, queryParamsObj, 2); 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); res.status(200).json(results);
} }
async read(req, res) { async read(req, res) {
let query = "select * from ?? where ";
let query = 'select * from ?? where ';
let params = []; let params = [];
params.push(req.app.locals._tableName); params.push(req.app.locals._tableName);
let clause = this.mysql.getPrimaryKeyWhereClause(req.app.locals._tableName, let clause = this.mysql.getPrimaryKeyWhereClause(
req.params.id.split('___')); req.app.locals._tableName,
req.params.id.split("___")
);
if (!clause) { if (!clause) {
return res.status(400).send({ 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 += clause;
query += ' LIMIT 1' query += " LIMIT 1";
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 exists(req, res) { async exists(req, res) {
let query = "select * from ?? where ";
let query = 'select * from ?? where ';
let params = []; let params = [];
params.push(req.app.locals._tableName); params.push(req.app.locals._tableName);
let clause = this.mysql.getPrimaryKeyWhereClause(req.app.locals._tableName, let clause = this.mysql.getPrimaryKeyWhereClause(
req.params.id.split('___')); req.app.locals._tableName,
req.params.id.split("___")
);
if (!clause) { if (!clause) {
return res.status(400).send({ 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 += clause;
query += ' LIMIT 1' query += " LIMIT 1";
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 update(req, res) { async update(req, res) {
let query = "REPLACE INTO ?? SET ?";
let query = 'REPLACE INTO ?? SET ?';
let params = []; let params = [];
params.push(req.app.locals._tableName); params.push(req.app.locals._tableName);
@ -124,31 +117,31 @@ class xctrl {
var results = await this.mysql.exec(query, params); var results = await this.mysql.exec(query, params);
res.status(200).json(results); res.status(200).json(results);
} }
async patch(req, res) { async patch(req, res) {
let query = "UPDATE ?? SET ";
let query = 'UPDATE ?? SET ';
let keys = Object.keys(req.body); let keys = Object.keys(req.body);
// SET clause // SET clause
let updateKeys = ''; let updateKeys = "";
for (let i = 0; i < keys.length; ++i) { for (let i = 0; i < keys.length; ++i) {
updateKeys += keys[i] + ' = ? ' updateKeys += keys[i] + " = ? ";
if (i !== keys.length - 1) if (i !== keys.length - 1) updateKeys += ", ";
updateKeys += ', '
} }
// where clause // where clause
query += updateKeys + ' where ' query += updateKeys + " where ";
let clause = this.mysql.getPrimaryKeyWhereClause(req.app.locals._tableName, let clause = this.mysql.getPrimaryKeyWhereClause(
req.params.id.split('___')); req.app.locals._tableName,
req.params.id.split("___")
);
if (!clause) { if (!clause) {
return res.status(400).send({ 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 += clause;
@ -160,23 +153,23 @@ class xctrl {
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 delete(req, res) { async delete(req, res) {
let query = "DELETE FROM ?? WHERE ";
let query = 'DELETE FROM ?? WHERE ';
let params = []; let params = [];
params.push(req.app.locals._tableName); params.push(req.app.locals._tableName);
let clause = this.mysql.getPrimaryKeyWhereClause(req.app.locals._tableName, let clause = this.mysql.getPrimaryKeyWhereClause(
req.params.id.split('___')); req.app.locals._tableName,
req.params.id.split("___")
);
if (!clause) { if (!clause) {
return res.status(400).send({ 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); let results = await this.mysql.exec(query, params);
res.status(200).json(results); res.status(200).json(results);
} }
async bulkInsert(req, res) { async bulkInsert(req, res) {
let queryParamsObj = {};
let queryParamsObj = {} queryParamsObj.query = "";
queryParamsObj.query = '' queryParamsObj.params = [];
queryParamsObj.params = [] let results = [];
let results = []
//console.log(req.app.locals._tableName, req.body); //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); res.status(200).json(results);
} }
async bulkDelete(req, res) { async bulkDelete(req, res) {
let query = "delete from ?? where ?? in ";
let query = 'delete from ?? where ?? in ';
let params = []; let params = [];
params.push(req.app.locals._tableName); params.push(req.app.locals._tableName);
params.push(this.mysql.getPrimaryKeyName(req.app.locals._tableName)); params.push(this.mysql.getPrimaryKeyName(req.app.locals._tableName));
query += '(' query += "(";
if (req.query && req.query._ids) { 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) { for (var i = 0; i < ids.length; ++i) {
if (i) { if (i) {
query += ',' query += ",";
} }
query += '?' query += "?";
params.push(ids[i]) params.push(ids[i]);
} }
} }
query += ')' query += ")";
//console.log(query, params); //console.log(query, params);
var results = await this.mysql.exec(query, params); var results = await this.mysql.exec(query, params);
res.status(200).json(results); res.status(200).json(results);
} }
async bulkRead(req, res) { async bulkRead(req, res) {
let queryParamsObj = {};
let queryParamsObj = {} queryParamsObj.query = "";
queryParamsObj.query = '' queryParamsObj.params = [];
queryParamsObj.params = []
this.mysql.prepareListQuery(req, res, queryParamsObj, 3); this.mysql.prepareListQuery(req, res, queryParamsObj, 3);
//console.log(queryParamsObj.query, queryParamsObj.params); //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); res.status(200).json(results);
} }
async count(req, res) { 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 = [];
queryParams.params.push(req.app.locals._tableName); 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); let results = await this.mysql.exec(queryParams.query, queryParams.params);
res.status(200).json(results); res.status(200).json(results);
} }
async distinct(req, res) { async distinct(req, res) {
let queryParamsObj = {};
let queryParamsObj = {} queryParamsObj.query = "";
queryParamsObj.query = '' queryParamsObj.params = [];
queryParamsObj.params = []
this.mysql.prepareListQuery(req, res, queryParamsObj, 4); 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); res.status(200).json(results);
} }
async groupBy(req, res) { async groupBy(req, res) {
if (req.query && req.query._fields) { if (req.query && req.query._fields) {
let queryParamsObj = {};
let queryParamsObj = {} queryParamsObj.query = "select ";
queryParamsObj.query = 'select ';
queryParamsObj.params = []; queryParamsObj.params = [];
/**************** add columns and group by columns ****************/ /**************** 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; let tableName = req.app.locals._tableName;
queryParamsObj.params.push(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) { if (!req.query._sort) {
req.query._sort = {} req.query._sort = {};
req.query._sort = '-_count' req.query._sort = "-_count";
} }
/**************** add having clause ****************/ /**************** 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 ****************/ /**************** add orderby clause ****************/
this.mysql.getOrderByClause(req.query, tableName, queryParamsObj); this.mysql.getOrderByClause(req.query, tableName, queryParamsObj);
//console.log(queryParamsObj.query, queryParamsObj.params); //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); res.status(200).json(results);
} else { } 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) { async ugroupby(req, res) {
if (req.query && req.query._fields) { if (req.query && req.query._fields) {
let queryParamsObj = {};
let queryParamsObj = {} queryParamsObj.query = "";
queryParamsObj.query = '';
queryParamsObj.params = []; queryParamsObj.params = [];
let uGrpByResults = {} let uGrpByResults = {};
/**************** add fields with count(*) *****************/ /**************** add fields with count(*) *****************/
let fields = req.query._fields.split(',') let fields = req.query._fields.split(",");
for (var i = 0; i < fields.length; ++i) { for (var i = 0; i < fields.length; ++i) {
uGrpByResults[fields[i]] = [];
uGrpByResults[fields[i]] = []
if (i) { if (i) {
queryParamsObj.query += ' UNION ' queryParamsObj.query += " UNION ";
} }
queryParamsObj.query += ' SELECT IFNULL(CONCAT(?,?,??),?) as ugroupby, count(*) as _count from ?? GROUP BY ?? ' queryParamsObj.query +=
queryParamsObj.params.push(fields[i]) " SELECT IFNULL(CONCAT(?,?,??),?) as ugroupby, count(*) as _count from ?? GROUP BY ?? ";
queryParamsObj.params.push('~') queryParamsObj.params.push(fields[i]);
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.params.push(fields[i]) queryParamsObj.params.push(req.app.locals._tableName);
queryParamsObj.params.push(fields[i]);
} }
//console.log(queryParamsObj.query, queryParamsObj.params); //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) { 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 obj = {};
let grpByColValue = results[i]['ugroupby'].split('~')[1] obj[grpByColValue] = results[i]["_count"];
let obj = {}
obj[grpByColValue] = results[i]['_count'];
uGrpByResults[grpByColName].push(obj)
uGrpByResults[grpByColName].push(obj);
} }
res.status(200).json(uGrpByResults); res.status(200).json(uGrpByResults);
} else { } 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) { async aggregate(req, res) {
if (req.query && req.query._fields) { if (req.query && req.query._fields) {
let tableName = req.app.locals._tableName; let tableName = req.app.locals._tableName;
let query = 'select ' let query = "select ";
let params = [] let params = [];
let fields = req.query._fields.split(','); let fields = req.query._fields.split(",");
for (var i = 0; i < fields.length; ++i) { for (var i = 0; i < fields.length; ++i) {
if (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(fields[i]);
params.push('min_of_' + fields[i]); params.push("min_of_" + fields[i]);
params.push(fields[i]); params.push(fields[i]);
params.push('max_of_' + fields[i]); params.push("max_of_" + fields[i]);
params.push(fields[i]); params.push(fields[i]);
params.push('avg_of_' + fields[i]); params.push("avg_of_" + fields[i]);
params.push(fields[i]); params.push(fields[i]);
params.push('sum_of_' + fields[i]); params.push("sum_of_" + fields[i]);
params.push(fields[i]); params.push(fields[i]);
params.push('stddev_of_' + fields[i]); params.push("stddev_of_" + fields[i]);
params.push(fields[i]); params.push(fields[i]);
params.push('variance_of_' + fields[i]); params.push("variance_of_" + fields[i]);
} }
query = query + ' from ??' query = query + " from ??";
params.push(tableName) params.push(tableName);
var results = await this.mysql.exec(query, params); var results = await this.mysql.exec(query, params);
res.status(200).json(results); res.status(200).json(results);
} else { } 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) { async chart(req, res) {
let query = "";
let query = '' let params = [];
let params = [] let obj = {};
let obj = {}
if (req.query) { if (req.query) {
let isRange = false;
let isRange = false
if (req.query.range) { if (req.query.range) {
isRange = true isRange = true;
} }
if (req.query && req.query.min && req.query.max && req.query.step) { if (req.query && req.query.min && req.query.max && req.query.step) {
//console.log(req.params.min, req.params.max, req.params.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, req.query._fields,
parseInt(req.query.min), parseInt(req.query.min),
parseInt(req.query.max), parseInt(req.query.max),
parseInt(req.query.step), parseInt(req.query.step),
isRange) isRange
);
} else if (
} else if (req.query && req.query.steparray && req.query.steparray.length > 1) { req.query &&
req.query.steparray &&
obj = this.mysql.getChartQueryAndParamsFromStepArray(req.app.locals._tableName, req.query.steparray.length > 1
) {
obj = this.mysql.getChartQueryAndParamsFromStepArray(
req.app.locals._tableName,
req.query._fields, req.query._fields,
(req.query.steparray.split(',')).map(Number), req.query.steparray.split(",").map(Number),
isRange) isRange
);
} else if (
} else if (req.query && req.query.steppair && req.query.steppair.length > 1) { req.query &&
req.query.steppair &&
obj = this.mysql.getChartQueryAndParamsFromStepPair(req.app.locals._tableName, req.query.steppair.length > 1
) {
obj = this.mysql.getChartQueryAndParamsFromStepPair(
req.app.locals._tableName,
req.query._fields, req.query._fields,
(req.query.steppair.split(',')).map(Number), req.query.steppair.split(",").map(Number),
false) false
);
} else { } else {
query =
query = 'select min(??) as min,max(??) as max,stddev(??) as stddev,avg(??) as avg from ??'; "select min(??) as min,max(??) as max,stddev(??) as stddev,avg(??) as avg from ??";
params = []; params = [];
params.push(req.query._fields); params.push(req.query._fields);
@ -466,66 +487,70 @@ class xctrl {
let _this = this; let _this = this;
let results = await let results = await _this.mysql.exec(query, params);
_this.mysql.exec(query, params);
//console.log(results, results['max'], req.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, req.query._fields,
results[0]['min'], results[0]["min"],
results[0]['max'], results[0]["max"],
results[0]['stddev'], results[0]["stddev"],
isRange 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 let results = await this.mysql.exec(obj.query, obj.params);
this.mysql.exec(obj.query, obj.params);
res.status(200).json(results); res.status(200).json(results);
} else { } 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) { async autoChart(req, res) {
let query = "describe ??";
let params = [req.app.locals._tableName];
let obj = {};
let results = [];
let query = 'describe ??' let isRange = false;
let params = [req.app.locals._tableName]
let obj = {}
let results = []
let isRange = false
if (req.query.range) { 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); //console.log(describeResults);
for (var i = 0; i < describeResults.length; ++i) { for (var i = 0; i < describeResults.length; ++i) {
//console.log('is this numeric column', describeResults[i]['Type']); //console.log('is this numeric column', describeResults[i]['Type']);
if (describeResults[i]['Key'] !== 'PRI' && this.mysql.isTypeOfColumnNumber(describeResults[i]['Type'])) { if (
describeResults[i]["Key"] !== "PRI" &&
query = 'select min(??) as min,max(??) as max,stddev(??) as stddev,avg(??) as avg from ??'; this.mysql.isTypeOfColumnNumber(describeResults[i]["Type"])
) {
query =
"select min(??) as min,max(??) as max,stddev(??) as stddev,avg(??) as avg from ??";
params = []; 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); params.push(req.app.locals._tableName);
let _this = this; let _this = this;
@ -534,32 +559,30 @@ class xctrl {
//console.log(minMaxResults, minMaxResults['max'], req.params); //console.log(minMaxResults, minMaxResults['max'], req.params);
query = '' query = "";
params = [] params = [];
obj = _this.mysql.getChartQueryAndParamsFromMinMaxStddev(req.app.locals._tableName, obj = _this.mysql.getChartQueryAndParamsFromMinMaxStddev(
describeResults[i]['Field'], req.app.locals._tableName,
minMaxResults[0]['min'], describeResults[i]["Field"],
minMaxResults[0]['max'], minMaxResults[0]["min"],
minMaxResults[0]['stddev'], minMaxResults[0]["max"],
minMaxResults[0]["stddev"],
isRange isRange
) );
let r = await this.mysql.exec(obj.query, obj.params); let r = await this.mysql.exec(obj.query, obj.params);
let resultObj = {} let resultObj = {};
resultObj['column'] = describeResults[i]['Field'] resultObj["column"] = describeResults[i]["Field"];
resultObj['chart'] = r resultObj["chart"] = r;
results.push(resultObj); results.push(resultObj);
} }
} }
res.status(200).json(results); res.status(200).json(results);
} }
} }
//expose class //expose class

1111
lib/xsql.js

File diff suppressed because it is too large Load Diff

460
package-lock.json generated

@ -176,6 +176,12 @@
"typedarray": "^0.0.6" "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": { "content-disposition": {
"version": "0.5.2", "version": "0.5.2",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
@ -231,6 +237,15 @@
"ms": "2.0.0" "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": { "delayed-stream": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@ -285,6 +300,16 @@
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
"dev": true "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": { "ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "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", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz",
"integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" "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": { "escape-html": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@ -306,6 +365,85 @@
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true "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": { "etag": {
"version": "1.8.1", "version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
@ -354,6 +492,12 @@
"integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=",
"dev": true "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": { "finalhandler": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz",
@ -368,6 +512,15 @@
"unpipe": "~1.0.0" "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": { "form-data": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz",
@ -401,6 +554,18 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true "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": { "glob": {
"version": "7.1.2", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
@ -415,24 +580,51 @@
"path-is-absolute": "^1.0.0" "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": { "growl": {
"version": "1.10.5", "version": "1.10.5",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
"dev": true "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": { "has-flag": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true "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": { "he": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
"integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
"dev": true "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": { "http-errors": {
"version": "1.6.2", "version": "1.6.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", "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", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz",
"integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" "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": { "isarray": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" "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": { "log": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/log/-/log-1.4.0.tgz", "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", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" "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": { "object-assign": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
"integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" "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": { "on-finished": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@ -658,22 +956,100 @@
"wrappy": "1" "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": { "parseurl": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" "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": { "path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true "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": { "path-to-regexp": {
"version": "0.1.7", "version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" "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": { "process-nextick-args": {
"version": "1.0.7", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
@ -709,6 +1085,27 @@
"unpipe": "1.0.0" "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": { "readable-stream": {
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
@ -723,11 +1120,26 @@
"util-deprecate": "~1.0.1" "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": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
"integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" "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": { "send": {
"version": "0.16.1", "version": "0.16.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz",
@ -827,6 +1239,38 @@
"nan": ">=2.5.1" "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": { "sqlstring": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.0.tgz", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.0.tgz",
@ -850,6 +1294,12 @@
"safe-buffer": "~5.1.0" "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": { "superagent": {
"version": "3.6.3", "version": "3.6.3",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-3.6.3.tgz", "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", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" "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": { "vary": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",

4
package.json

@ -36,6 +36,10 @@
"mysql": "^2.15.0" "mysql": "^2.15.0"
}, },
"devDependencies": { "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", "mocha": "^5.2.0",
"should": "^13.1.2", "should": "^13.1.2",
"sleep": "^5.1.1", "sleep": "^5.1.1",

2831
tests/tests.js

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save