badmfck-api-server 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/apiServer/APIService.js +1 -1
- package/dist/apiServer/MysqlService.d.ts +46 -0
- package/dist/apiServer/MysqlService.js +250 -0
- package/dist/apiServer/structures/HTTPStatus.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +3 -1
- package/package.json +5 -3
- package/badmfck-api-server-1.0.1.tgz +0 -0
- package/badmfck-api-server-1.0.2.tgz +0 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
import { FieldInfo, MysqlError, Pool, PoolConnection } from "mysql";
|
2
|
+
import { BaseService } from "./BaseService";
|
3
|
+
export interface MysqlServiceOptions {
|
4
|
+
connectionLimit: number;
|
5
|
+
host: string;
|
6
|
+
user: string;
|
7
|
+
password: string;
|
8
|
+
port: number;
|
9
|
+
database: string;
|
10
|
+
onLog?: (level: number, data: any) => void;
|
11
|
+
}
|
12
|
+
export interface MysqlResult {
|
13
|
+
error?: MysqlError | null;
|
14
|
+
isDuplicateError?: boolean;
|
15
|
+
fields?: FieldInfo[] | null;
|
16
|
+
data: any;
|
17
|
+
}
|
18
|
+
export interface MySqlQuery {
|
19
|
+
query: string;
|
20
|
+
fields: MysqlQueryField[];
|
21
|
+
}
|
22
|
+
export interface MysqlQueryField {
|
23
|
+
name: string;
|
24
|
+
value: string | number | boolean | null | undefined;
|
25
|
+
system?: boolean;
|
26
|
+
ignoreInInsert?: boolean;
|
27
|
+
ignoreInUpdate?: boolean;
|
28
|
+
useInReplace?: boolean;
|
29
|
+
_parsedValue?: string | number | boolean | null;
|
30
|
+
}
|
31
|
+
export declare class MysqlService extends BaseService {
|
32
|
+
reconnectionTimeout: number;
|
33
|
+
reconnecting: boolean;
|
34
|
+
pool: Pool | null;
|
35
|
+
options: MysqlServiceOptions;
|
36
|
+
retries: number;
|
37
|
+
constructor(options: MysqlServiceOptions);
|
38
|
+
init(): Promise<void>;
|
39
|
+
onApplicationReady(): Promise<void>;
|
40
|
+
static prepareQuery(query: string, fields: MysqlQueryField[]): string;
|
41
|
+
static prepareQueryFieldValue(value: string | number | boolean | null | undefined, system?: boolean): string | number | boolean | null | undefined;
|
42
|
+
execute(query: string): Promise<MysqlResult>;
|
43
|
+
sendQuery(conn: PoolConnection, query: string, resolve: (data: MysqlResult) => void): void;
|
44
|
+
createPool(): Promise<boolean>;
|
45
|
+
}
|
46
|
+
export default MysqlService;
|
@@ -0,0 +1,250 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.MysqlService = void 0;
|
7
|
+
const mysql_1 = __importDefault(require("mysql"));
|
8
|
+
const BaseService_1 = require("./BaseService");
|
9
|
+
const badmfck_signal_1 = require("badmfck-signal");
|
10
|
+
const REQ_MYSQL_QUERY = new badmfck_signal_1.Req();
|
11
|
+
class MysqlService extends BaseService_1.BaseService {
|
12
|
+
reconnectionTimeout = 1000 * 3;
|
13
|
+
reconnecting = false;
|
14
|
+
pool = null;
|
15
|
+
options;
|
16
|
+
retries = 5;
|
17
|
+
constructor(options) {
|
18
|
+
super("mysql");
|
19
|
+
this.options = options;
|
20
|
+
this.init();
|
21
|
+
}
|
22
|
+
async init() {
|
23
|
+
const ok = await this.createPool();
|
24
|
+
if (!ok) {
|
25
|
+
if (this.options.onLog)
|
26
|
+
this.options.onLog(2, "Mysql server not connected");
|
27
|
+
}
|
28
|
+
REQ_MYSQL_QUERY.listener = async (data) => {
|
29
|
+
if (!Array.isArray(data))
|
30
|
+
data = [data];
|
31
|
+
const promises = [];
|
32
|
+
for (let i of data) {
|
33
|
+
const query = MysqlService.prepareQuery(i.query, i.fields);
|
34
|
+
promises.push(this.execute(query));
|
35
|
+
}
|
36
|
+
return await Promise.all(promises);
|
37
|
+
};
|
38
|
+
}
|
39
|
+
async onApplicationReady() { }
|
40
|
+
static prepareQuery(query, fields) {
|
41
|
+
for (let i of fields) {
|
42
|
+
const val = this.prepareQueryFieldValue(i.value, i.system);
|
43
|
+
i._parsedValue = val;
|
44
|
+
query = query.replaceAll("@" + i.name, val + "");
|
45
|
+
}
|
46
|
+
const tmp = query.toLowerCase();
|
47
|
+
if (tmp.indexOf("select") === 0 && tmp.indexOf("limit") === -1)
|
48
|
+
query += " LIMIT 100";
|
49
|
+
query = query.replaceAll("@NOLIMIT", "");
|
50
|
+
if (query.indexOf("@fields") !== -1) {
|
51
|
+
let insertFieldNames = [];
|
52
|
+
let insertFieldValues = [];
|
53
|
+
for (let i of fields) {
|
54
|
+
if (i.ignoreInInsert)
|
55
|
+
continue;
|
56
|
+
insertFieldNames.push('`' + i.name.replaceAll("`", '').replaceAll('\"', "").replaceAll('\'', "") + '`');
|
57
|
+
insertFieldValues.push(i._parsedValue);
|
58
|
+
}
|
59
|
+
query = query
|
60
|
+
.replaceAll('@fields', insertFieldNames.join(","))
|
61
|
+
.replaceAll('@values', insertFieldValues.join(","));
|
62
|
+
}
|
63
|
+
if (query.indexOf("@onupdate") !== -1) {
|
64
|
+
let onUpdate = [];
|
65
|
+
for (let i of fields) {
|
66
|
+
if (i.ignoreInUpdate)
|
67
|
+
continue;
|
68
|
+
onUpdate.push('`' + i.name.replaceAll("`", '').replaceAll('\"', "").replaceAll('\'', "") + '` = ' + i._parsedValue);
|
69
|
+
}
|
70
|
+
query = query.replaceAll("@onupdate", onUpdate.join(" , "));
|
71
|
+
}
|
72
|
+
if (query.indexOf('@onduplicate') !== -1) {
|
73
|
+
let onDuplicate = [];
|
74
|
+
for (let i of fields) {
|
75
|
+
if (!i.useInReplace)
|
76
|
+
continue;
|
77
|
+
onDuplicate.push('`' + i.name.replaceAll("`", '').replaceAll('\"', "").replaceAll('\'', "") + '` = ' + i._parsedValue);
|
78
|
+
}
|
79
|
+
query = query.replaceAll("@onduplicate", onDuplicate.join(" , "));
|
80
|
+
}
|
81
|
+
return query;
|
82
|
+
}
|
83
|
+
static prepareQueryFieldValue(value, system) {
|
84
|
+
if (!system && typeof value === "string") {
|
85
|
+
value = value ? value.replaceAll('"', '\\"') : null;
|
86
|
+
value = '"' + value + '"';
|
87
|
+
}
|
88
|
+
return value;
|
89
|
+
}
|
90
|
+
async execute(query) {
|
91
|
+
return new Promise((resolve, reject) => {
|
92
|
+
if (!this.pool) {
|
93
|
+
if (this.options.onLog)
|
94
|
+
this.options.onLog(2, "No pool");
|
95
|
+
resolve({
|
96
|
+
error: {
|
97
|
+
code: "NO_POOL",
|
98
|
+
errno: 100000,
|
99
|
+
fatal: true,
|
100
|
+
sql: query,
|
101
|
+
name: "NO_POOL",
|
102
|
+
message: "Mysql pool not created"
|
103
|
+
},
|
104
|
+
data: null,
|
105
|
+
fields: null
|
106
|
+
});
|
107
|
+
return;
|
108
|
+
}
|
109
|
+
this.pool.getConnection((err, conn) => {
|
110
|
+
if (err) {
|
111
|
+
if (this.options.onLog)
|
112
|
+
this.options.onLog(2, `${err}`);
|
113
|
+
resolve({
|
114
|
+
error: err,
|
115
|
+
data: null,
|
116
|
+
fields: null
|
117
|
+
});
|
118
|
+
return;
|
119
|
+
}
|
120
|
+
if (!conn) {
|
121
|
+
resolve({
|
122
|
+
error: {
|
123
|
+
code: "NO_CONN",
|
124
|
+
errno: 100001,
|
125
|
+
fatal: true,
|
126
|
+
sql: query,
|
127
|
+
name: "NO_CONN",
|
128
|
+
message: "Mysql pool cant get connection"
|
129
|
+
},
|
130
|
+
data: null,
|
131
|
+
fields: null
|
132
|
+
});
|
133
|
+
}
|
134
|
+
try {
|
135
|
+
this.sendQuery(conn, query, resolve);
|
136
|
+
}
|
137
|
+
catch (e) {
|
138
|
+
try {
|
139
|
+
conn.removeAllListeners();
|
140
|
+
conn.release();
|
141
|
+
}
|
142
|
+
catch (e) { }
|
143
|
+
resolve({
|
144
|
+
error: {
|
145
|
+
code: "QUERY_ERR",
|
146
|
+
errno: 100002,
|
147
|
+
fatal: true,
|
148
|
+
sql: query,
|
149
|
+
name: "QUERY_ERR",
|
150
|
+
message: "Error: " + e
|
151
|
+
},
|
152
|
+
data: null,
|
153
|
+
fields: null
|
154
|
+
});
|
155
|
+
}
|
156
|
+
});
|
157
|
+
});
|
158
|
+
}
|
159
|
+
sendQuery(conn, query, resolve) {
|
160
|
+
let errCatched = false;
|
161
|
+
conn.on("error", err => {
|
162
|
+
errCatched = true;
|
163
|
+
conn.release();
|
164
|
+
conn.removeAllListeners();
|
165
|
+
if (this.options.onLog)
|
166
|
+
this.options.onLog(2, `${err}`);
|
167
|
+
conn.removeAllListeners();
|
168
|
+
resolve({
|
169
|
+
error: {
|
170
|
+
code: "CONN_ERR",
|
171
|
+
errno: 100003,
|
172
|
+
fatal: true,
|
173
|
+
sql: query,
|
174
|
+
name: "CONN_ERR",
|
175
|
+
message: "Error: " + err
|
176
|
+
},
|
177
|
+
data: null,
|
178
|
+
fields: null
|
179
|
+
});
|
180
|
+
});
|
181
|
+
if (this.options.onLog)
|
182
|
+
this.options.onLog(0, query);
|
183
|
+
conn.query(query, (err, results, fields) => {
|
184
|
+
conn.release();
|
185
|
+
conn.removeAllListeners();
|
186
|
+
if (errCatched)
|
187
|
+
return;
|
188
|
+
if (err) {
|
189
|
+
const dup = `${err}`.toLowerCase().indexOf("er_dup_entry") !== -1;
|
190
|
+
if (this.options.onLog)
|
191
|
+
this.options.onLog(2, `${err}`);
|
192
|
+
resolve({
|
193
|
+
error: err,
|
194
|
+
data: null,
|
195
|
+
fields: null,
|
196
|
+
isDuplicateError: dup
|
197
|
+
});
|
198
|
+
return;
|
199
|
+
}
|
200
|
+
resolve({
|
201
|
+
error: err,
|
202
|
+
data: results,
|
203
|
+
fields: fields
|
204
|
+
});
|
205
|
+
return;
|
206
|
+
});
|
207
|
+
}
|
208
|
+
async createPool() {
|
209
|
+
if (this.options.onLog)
|
210
|
+
this.options.onLog(1, "Connecting to mysql: \n HOST: " + this.options.host + '\n USER:' + this.options.user + '\n PORT:' + this.options.port);
|
211
|
+
let err = false;
|
212
|
+
try {
|
213
|
+
this.pool = mysql_1.default.createPool({
|
214
|
+
connectionLimit: this.options.connectionLimit,
|
215
|
+
host: this.options.host,
|
216
|
+
user: this.options.user,
|
217
|
+
password: this.options.password,
|
218
|
+
port: this.options.port,
|
219
|
+
database: this.options.database,
|
220
|
+
multipleStatements: true
|
221
|
+
});
|
222
|
+
}
|
223
|
+
catch (e) {
|
224
|
+
if (this.options.onLog)
|
225
|
+
this.options.onLog(2, "Can't connect to MYSQL!");
|
226
|
+
err = true;
|
227
|
+
}
|
228
|
+
return new Promise((res, rej) => {
|
229
|
+
if (err) {
|
230
|
+
res(false);
|
231
|
+
return;
|
232
|
+
}
|
233
|
+
if (!this.pool) {
|
234
|
+
res(false);
|
235
|
+
return;
|
236
|
+
}
|
237
|
+
this.pool.getConnection((e, cnn) => {
|
238
|
+
if (e) {
|
239
|
+
if (this.options.onLog)
|
240
|
+
this.options.onLog(2, e.message);
|
241
|
+
res(false);
|
242
|
+
return;
|
243
|
+
}
|
244
|
+
res(true);
|
245
|
+
});
|
246
|
+
});
|
247
|
+
}
|
248
|
+
}
|
249
|
+
exports.MysqlService = MysqlService;
|
250
|
+
exports.default = MysqlService;
|
@@ -8,4 +8,4 @@ var HTTP_STATUS;
|
|
8
8
|
HTTP_STATUS[HTTP_STATUS["UNAUTHORIZED"] = 401] = "UNAUTHORIZED";
|
9
9
|
HTTP_STATUS[HTTP_STATUS["BAD_REQUEST"] = 400] = "BAD_REQUEST";
|
10
10
|
HTTP_STATUS[HTTP_STATUS["SERVER_ERROR"] = 500] = "SERVER_ERROR";
|
11
|
-
})(HTTP_STATUS
|
11
|
+
})(HTTP_STATUS || (exports.HTTP_STATUS = HTTP_STATUS = {}));
|
package/dist/index.d.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
1
|
import { APIService, Initializer } from "./apiServer/APIService";
|
2
2
|
import { LocalRequest } from "./apiServer/LocalRequest";
|
3
|
-
|
3
|
+
import { MysqlService } from "./apiServer/MysqlService";
|
4
|
+
export { APIService, Initializer, LocalRequest, MysqlService };
|
package/dist/index.js
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.LocalRequest = exports.Initializer = exports.APIService = void 0;
|
3
|
+
exports.MysqlService = exports.LocalRequest = exports.Initializer = exports.APIService = void 0;
|
4
4
|
const APIService_1 = require("./apiServer/APIService");
|
5
5
|
Object.defineProperty(exports, "APIService", { enumerable: true, get: function () { return APIService_1.APIService; } });
|
6
6
|
Object.defineProperty(exports, "Initializer", { enumerable: true, get: function () { return APIService_1.Initializer; } });
|
7
7
|
const LocalRequest_1 = require("./apiServer/LocalRequest");
|
8
8
|
Object.defineProperty(exports, "LocalRequest", { enumerable: true, get: function () { return LocalRequest_1.LocalRequest; } });
|
9
|
+
const MysqlService_1 = require("./apiServer/MysqlService");
|
10
|
+
Object.defineProperty(exports, "MysqlService", { enumerable: true, get: function () { return MysqlService_1.MysqlService; } });
|
package/package.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "badmfck-api-server",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.4",
|
4
4
|
"description": "Simple API http server based on express",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"types": "dist/index.d.ts",
|
7
7
|
"scripts": {
|
8
8
|
"prepublish": "tsc",
|
9
|
-
"build":"tsc",
|
9
|
+
"build": "tsc",
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1"
|
11
11
|
},
|
12
12
|
"keywords": [
|
@@ -17,10 +17,12 @@
|
|
17
17
|
"express"
|
18
18
|
],
|
19
19
|
"dependencies": {
|
20
|
+
"@types/mysql": "^2.15.21",
|
20
21
|
"axios": "^1.4.0",
|
21
22
|
"badmfck-signal": "^1.0.1",
|
22
23
|
"cors": "^2.8.5",
|
23
|
-
"express": "^4.18.2"
|
24
|
+
"express": "^4.18.2",
|
25
|
+
"mysql": "^2.18.1"
|
24
26
|
},
|
25
27
|
"devDependencies": {
|
26
28
|
"@types/cors": "^2.8.13",
|
Binary file
|
Binary file
|