xmysql-timzoned 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
package/.eslintrc.js ADDED
@@ -0,0 +1,28 @@
1
+ module.exports = {
2
+ extends: ["eslint-config-airbnb-base", "eslint-config-prettier"],
3
+ plugins: ["eslint-plugin-import", "eslint-plugin-prettier"],
4
+ parserOptions: {
5
+ ecmaFeatures: {
6
+ ecmaVersion: 6
7
+ }
8
+ },
9
+ env: {
10
+ es6: true,
11
+ node: true
12
+ },
13
+ rules: {
14
+ "prettier/prettier": ["error", {}],
15
+ "max-len": ["error", { code: 2000, ignoreUrls: true }],
16
+ "linebreak-style": 0,
17
+ "no-use-before-define": ["error", { functions: false, classes: false }],
18
+ "no-plusplus": ["error", { allowForLoopAfterthoughts: true }],
19
+ "no-underscore-dangle": 0,
20
+ "import/no-amd": 0,
21
+ "import/no-dynamic-require": 0,
22
+ "no-console": 0,
23
+ "no-param-reassign": 0,
24
+ "no-unused-vars": ["error", { argsIgnorePattern: "next" }],
25
+ "comma-dangle": 0
26
+ }
27
+ };
28
+
package/.travis.yml ADDED
@@ -0,0 +1,17 @@
1
+ language: node_js
2
+ node_js:
3
+ - '7.6.0'
4
+ - '8'
5
+ - '10'
6
+ - '12'
7
+ - 'node'
8
+ services:
9
+ - mysql
10
+ install:
11
+ - npm install
12
+ before_install:
13
+ - mysql -e 'CREATE DATABASE IF NOT EXISTS classicmodels;'
14
+ - mysql -u root --default-character-set=utf8 classicmodels < tests/sample.sql
15
+ script:
16
+ - npm test
17
+
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 o1lab
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/bin/index.js ADDED
@@ -0,0 +1,94 @@
1
+ #! /usr/bin/env node
2
+
3
+ const morgan = require("morgan");
4
+ const bodyParser = require("body-parser");
5
+ const express = require("express");
6
+ const sqlConfig = require("commander");
7
+ const mysql = require("mysql");
8
+ const cors = require("cors");
9
+ const dataHelp = require("../lib/util/data.helper.js");
10
+ const Xapi = require("../lib/xapi.js");
11
+ const cmdargs = require("../lib/util/cmd.helper.js");
12
+ const cluster = require("cluster");
13
+ const numCPUs = require("os").cpus().length;
14
+
15
+
16
+ function startXmysql(sqlConfig) {
17
+ /**************** START : setup express ****************/
18
+ let app = express();
19
+ app.use(morgan("tiny"));
20
+ app.use(cors());
21
+ app.use(bodyParser.json());
22
+ app.use(
23
+ bodyParser.urlencoded({
24
+ extended: true
25
+ })
26
+ );
27
+ /**************** END : setup express ****************/
28
+
29
+ /**************** START : setup mysql ****************/
30
+ let mysqlPool = mysql.createPool(sqlConfig);
31
+ /**************** END : setup mysql ****************/
32
+
33
+ /**************** START : setup Xapi ****************/
34
+ console.log("");
35
+ console.log("");
36
+ console.log("");
37
+ console.log(" Generating REST APIs at the speed of your thought.. ");
38
+ console.log("");
39
+
40
+ let t = process.hrtime();
41
+ let moreApis = new Xapi(sqlConfig, mysqlPool, app);
42
+
43
+ moreApis.init((err, results) => {
44
+ app.listen(sqlConfig.portNumber, sqlConfig.ipAddress);
45
+ var t1 = process.hrtime(t);
46
+ var t2 = t1[0] + t1[1] / 1000000000;
47
+
48
+ console.log(
49
+ " Xmysql took : %d seconds",
50
+ dataHelp.round(t2, 1)
51
+ );
52
+ console.log(
53
+ " API's base URL : " +
54
+ "localhost:" +
55
+ sqlConfig.portNumber
56
+ );
57
+ console.log(" ");
58
+ console.log(
59
+ " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - "
60
+ );
61
+ });
62
+ /**************** END : setup Xapi ****************/
63
+ }
64
+
65
+ function start(sqlConfig) {
66
+ //handle cmd line arguments
67
+ cmdargs.handle(sqlConfig);
68
+
69
+ if (cluster.isMaster && sqlConfig.useCpuCores > 1) {
70
+ console.log(`Master ${process.pid} is running`);
71
+
72
+ for (let i = 0; i < numCPUs && i < sqlConfig.useCpuCores; i++) {
73
+ console.log(`Forking process number ${i}...`);
74
+ cluster.fork();
75
+ }
76
+
77
+ cluster.on("exit", function(worker, code, signal) {
78
+ console.log(
79
+ "Worker " +
80
+ worker.process.pid +
81
+ " died with code: " +
82
+ code +
83
+ ", and signal: " +
84
+ signal
85
+ );
86
+ console.log("Starting a new worker");
87
+ cluster.fork();
88
+ });
89
+ } else {
90
+ startXmysql(sqlConfig);
91
+ }
92
+ }
93
+
94
+ start(sqlConfig);
package/dockerfile ADDED
@@ -0,0 +1,33 @@
1
+ FROM alpine:3.7
2
+
3
+
4
+ RUN apk --update --no-cache add \
5
+ nodejs \
6
+ nodejs-npm
7
+
8
+ # Bug fix for segfault ( Convert PT_GNU_STACK program header into PT_PAX_FLAGS )
9
+ RUN apk --update --no-cache add paxctl \
10
+ && paxctl -cm $(which node)
11
+
12
+ RUN mkdir -p /usr/src/{app,bin,lib}
13
+ WORKDIR /usr/src/app
14
+
15
+ # only install production deps to keep image small
16
+ COPY package.json /usr/src/app
17
+ RUN npm install --production
18
+
19
+ RUN apk del nodejs-npm
20
+
21
+ COPY index.js /usr/src/app
22
+ COPY bin/ /usr/src/app/bin
23
+ COPY lib/ /usr/src/app/lib
24
+ COPY docker-entrypoint.sh /docker-entrypoint.sh
25
+
26
+ # env
27
+ ENV DATABASE_HOST 127.0.0.1
28
+ ENV DATABASE_USER root
29
+ ENV DATABASE_PASSWORD password
30
+ ENV DATABASE_NAME sakila
31
+
32
+ EXPOSE 80
33
+ ENTRYPOINT ["/docker-entrypoint.sh"]
package/index.js ADDED
@@ -0,0 +1 @@
1
+ exports.xapi = require('./lib/xapi.js')
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ const program = require("commander");
3
+ const colors = require("colors");
4
+ const maxCpus = require("os").cpus().length;
5
+
6
+ program.on("--help", () => {
7
+ console.log("");
8
+ console.log(" Examples:".blue);
9
+ console.log("");
10
+ console.log(" $ xmysql -u username -p password -d databaseSchema".blue);
11
+ console.log("");
12
+ });
13
+
14
+ program
15
+ .version(module.exports.version)
16
+ .option("-h, --host <n>", "hostname of database / localhost by default")
17
+ .option("-u, --user <n>", "username of database / root by default")
18
+ .option("-p, --password <n>", "password of database / empty by default")
19
+ .option("-d, --database <n>", "database schema name")
20
+ .option("-t, --timezone <n>", "set the timezone")
21
+ .option(
22
+ "-r, --ipAddress <n>",
23
+ "IP interface of your server / localhost by default"
24
+ )
25
+ .option("-n, --portNumber <n>", "port number for app / 3000 by default")
26
+ .option("-o, --port <n>", "port number for mysql / 3306 by default")
27
+ .option("-S, --socketPath <n>", "unix socket path / not used by default")
28
+ .option(
29
+ "-s, --storageFolder <n>",
30
+ "storage folder / current working dir by default / available only with local"
31
+ )
32
+ .option("-i, --ignoreTables <n>", "comma separated table names to ignore")
33
+ .option("-a, --apiPrefix <n>", 'api url prefix / "/api/" by default')
34
+ .option("-y, --readOnly", "readonly apis / false by default")
35
+ .option(
36
+ "-c, --useCpuCores <n>",
37
+ "use number of CPU cores (using cluster) / 1 by default"
38
+ )
39
+ .parse(process.argv);
40
+
41
+ function paintHelp(txt) {
42
+ return colors.magenta(txt); //display the help text in a color
43
+ }
44
+
45
+ function processInvalidArguments(program) {
46
+ let err = "";
47
+
48
+ if (!program.password) {
49
+ err += "Error: password for database is missing\n";
50
+ }
51
+
52
+ if (!program.database) {
53
+ err += "Error: database name is missing\n";
54
+ }
55
+
56
+ if (err !== "") {
57
+ program.outputHelp(paintHelp);
58
+ console.log(err.red);
59
+ }
60
+ }
61
+
62
+ exports.handle = program => {
63
+ /**************** START : default values ****************/
64
+ program.ipAddress = program.ipAddress || "localhost";
65
+ program.portNumber = program.portNumber || 3000;
66
+ program.port = program.port || 3306;
67
+ program.user = program.user || "root";
68
+ program.password = program.password || "";
69
+ program.host = program.host || "localhost";
70
+ program.socketPath = program.socketPath || "";
71
+ program.storageFolder = program.storageFolder || process.cwd();
72
+ program.apiPrefix = program.apiPrefix || "/api/";
73
+ program.readOnly = program.readOnly || false;
74
+ program.useCpuCores = program.useCpuCores || 1;
75
+ program.timezone = program.timezone || "UTC";
76
+
77
+ if (program.useCpuCores === "0") {
78
+ program.useCpuCores = maxCpus;
79
+ }
80
+
81
+ if (program.ignoreTables) {
82
+ let ignoreTables = program.ignoreTables.split(",");
83
+ program.ignoreTables = {};
84
+ for (var i = 0; i < ignoreTables.length; ++i) {
85
+ program.ignoreTables[ignoreTables[i]] = ignoreTables[i];
86
+ }
87
+ } else {
88
+ program.ignoreTables = {};
89
+ }
90
+
91
+ program.connectionLimit = 10;
92
+
93
+ if (
94
+ program.host === "localhost" ||
95
+ program.host === "127.0.0.1" ||
96
+ program.host === "::1"
97
+ ) {
98
+ program.dynamic = 1;
99
+ }
100
+ // console.log(program);
101
+ /**************** END : default values ****************/
102
+
103
+ if (program.database && program.host && program.user) {
104
+ //console.log('Starting server at:', 'http://' + program.host + ':' + program.portNumber)
105
+ } else {
106
+ processInvalidArguments(program);
107
+ process.exit(1);
108
+ }
109
+ };
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+
3
+ exports.findOrInsertObjectArrayByKey = (obj, key, array) => {
4
+ let found = 0;
5
+ let i = 0;
6
+
7
+ for (i = 0; i < array.length; ++i) {
8
+ if (key in array[i]) {
9
+ if (obj[key] === array[i][key]) {
10
+ found = 1;
11
+ break;
12
+ }
13
+ }
14
+ }
15
+
16
+ if (!found) {
17
+ array.push(obj);
18
+ }
19
+
20
+ return array[i];
21
+ };
22
+
23
+ exports.findObjectInArrayByKey = (key, value, objArray) => {
24
+ for (let i = 0; i < objArray.length; ++i) {
25
+ if (objArray[i][key] === value) {
26
+ return objArray[i];
27
+ }
28
+ }
29
+
30
+ return null;
31
+ };
32
+
33
+ exports.round = function(number, precision) {
34
+ var factor = Math.pow(10, precision);
35
+ var tempNumber = number * factor;
36
+ var roundedTempNumber = Math.round(tempNumber);
37
+ return roundedTempNumber / factor;
38
+ };
39
+
40
+ exports.numberRound = (number, precision) => {
41
+ var factor = Math.pow(10, precision);
42
+ var tempNumber = number * factor;
43
+ var roundedTempNumber = Math.round(tempNumber);
44
+ return roundedTempNumber / factor;
45
+ };
46
+
47
+ exports.numberGetLength = number => {
48
+ var n = number;
49
+
50
+ if (number < 0) {
51
+ n = n * -1;
52
+ }
53
+
54
+ return n.toString().length;
55
+ };
56
+
57
+ exports.numberGetFixed = number => {
58
+ //console.log(number, typeof number);
59
+ return parseInt(number.toFixed());
60
+ };
61
+
62
+ exports.getStepArraySimple = function(min, max, step) {
63
+ var arr = [];
64
+ for (var i = min; i <= max; i = i + step) {
65
+ arr.push(i);
66
+ }
67
+
68
+ return arr;
69
+ };
70
+
71
+ exports.getStepArray = (min, max, stddev) => {
72
+ // console.log(' = = = = = = = ');
73
+ //console.log('original numbers', min, max, stddev);
74
+
75
+ min = this.numberGetFixed(min);
76
+ max = this.numberGetFixed(max);
77
+ stddev = this.numberGetFixed(stddev);
78
+
79
+ // console.log('fixed numbers', min, max, stddev);
80
+
81
+ let minMinusHalf = min - stddev / 2;
82
+ let maxMinusHalf = max + stddev / 2;
83
+
84
+ minMinusHalf = this.numberGetFixed(minMinusHalf);
85
+ maxMinusHalf = this.numberGetFixed(maxMinusHalf);
86
+
87
+ // console.log('fixed numbers + (min,max)', min, max, stddev, '(', minMinusHalf, ',', maxMinusHalf, ')');
88
+ // console.log('numbers length', 'min', numberGetLength(min), 'max', numberGetLength(max), 'stddev', numberGetLength(stddev));
89
+
90
+ let minLen = this.numberGetLength(minMinusHalf);
91
+ let maxLen = this.numberGetLength(maxMinusHalf);
92
+ let stddevLen = this.numberGetLength(stddev);
93
+ //
94
+ // console.log('- - - -');
95
+ // console.log('Range', 'min', numberRound(minMinusHalf, -1));
96
+ // console.log('Range', 'max', numberRound(maxMinusHalf, -1));
97
+ // console.log('Range', 'stddev', numberRound(stddev, -1));
98
+
99
+ if (minLen > 1) minMinusHalf = this.numberRound(minMinusHalf, -1);
100
+
101
+ if (maxLen > 2) maxMinusHalf = this.numberRound(maxMinusHalf, -1);
102
+
103
+ if (stddevLen !== 1) stddev = this.numberRound(stddev, -1);
104
+
105
+ var arr = [];
106
+ for (var step = minMinusHalf; step < maxMinusHalf; step = step + stddev) {
107
+ arr.push(step);
108
+ }
109
+ arr.push(maxMinusHalf);
110
+
111
+ // console.log(arr);
112
+
113
+ return arr;
114
+ };
115
+
116
+ exports.getSchemaQuery = function() {
117
+ return (
118
+ "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, " +
119
+ "c.column_comment,c.column_default,c.data_type,c.character_maximum_length, " +
120
+ "k.constraint_name, k.referenced_table_name, k.referenced_column_name, " +
121
+ "s.index_name,s.seq_in_index, " +
122
+ "v.table_name as isView " +
123
+ "from " +
124
+ "information_schema.columns as c " +
125
+ "left join " +
126
+ "information_schema.key_column_usage as k " +
127
+ "on " +
128
+ "c.column_name=k.column_name and " +
129
+ "c.table_schema = k.referenced_table_schema and " +
130
+ "c.table_name = k.table_name " +
131
+ "left join " +
132
+ "information_schema.statistics as s " +
133
+ "on " +
134
+ "c.column_name = s.column_name and " +
135
+ "c.table_schema = s.index_schema and " +
136
+ "c.table_name = s.table_name " +
137
+ "LEFT JOIN " +
138
+ "information_schema.VIEWS as v " +
139
+ "ON " +
140
+ "c.table_schema = v.table_schema and " +
141
+ "c.table_name = v.table_name " +
142
+ "where " +
143
+ "c.table_schema=? " +
144
+ "order by " +
145
+ "c.table_name, c.ordinal_position"
146
+ );
147
+ };
148
+
149
+ exports.getRoutines = function () {
150
+ return 'select routine_name from information_schema.routines'
151
+ }
152
+
153
+ exports.getChartQuery = function() {
154
+ return "select ? as ??, count(*) as _count from ?? where ?? between ? and ? ";
155
+ };
156
+
157
+ exports.getDataType = function(colType, typesArr) {
158
+ // console.log(colType,typesArr);
159
+ for (let i = 0; i < typesArr.length; ++i) {
160
+ if (colType.indexOf(typesArr[i]) !== -1) {
161
+ return 1;
162
+ }
163
+ }
164
+ return 0;
165
+ };
166
+
167
+ exports.getColumnType = function(column) {
168
+ let strTypes = [
169
+ "varchar",
170
+ "text",
171
+ "char",
172
+ "tinytext",
173
+ "mediumtext",
174
+ "longtext",
175
+ "blob",
176
+ "mediumblob",
177
+ "longblob",
178
+ "tinyblob",
179
+ "binary",
180
+ "varbinary"
181
+ ];
182
+ let intTypes = ["int", "long", "smallint", "mediumint", "bigint", "tinyint"];
183
+ let flatTypes = ["float", "double", "decimal"];
184
+ let dateTypes = ["date", "datetime", "timestamp", "time", "year"];
185
+
186
+ //console.log(column);
187
+ if (this.getDataType(column["data_type"], strTypes)) {
188
+ return "string";
189
+ } else if (this.getDataType(column["data_type"], intTypes)) {
190
+ return "int";
191
+ } else if (this.getDataType(column["data_type"], flatTypes)) {
192
+ return "float";
193
+ } else if (this.getDataType(column["data_type"], dateTypes)) {
194
+ return "date";
195
+ } else {
196
+ return "string";
197
+ }
198
+ };
199
+
200
+ exports.getType = function(colType, typesArr) {
201
+ for (let i = 0; i < typesArr.length; ++i) {
202
+ // if (typesArr[i].indexOf(colType) !== -1) {
203
+ // return 1;
204
+ // }
205
+
206
+ if (colType.indexOf(typesArr[i]) !== -1) {
207
+ return 1;
208
+ }
209
+ }
210
+ return 0;
211
+ };