badmfck-api-server 2.1.2 → 2.1.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.
@@ -9,6 +9,7 @@ export interface APIServiceNetworkLogItem {
|
|
9
9
|
id: number;
|
10
10
|
created: number;
|
11
11
|
time: number;
|
12
|
+
referer?: string;
|
12
13
|
request: {
|
13
14
|
[key: string]: any;
|
14
15
|
};
|
@@ -59,6 +60,6 @@ export declare class APIService extends BaseService {
|
|
59
60
|
netLog: APIServiceNetworkLogItem[];
|
60
61
|
constructor(options?: APIServiceOptions | null);
|
61
62
|
init(): Promise<void>;
|
62
|
-
sendResponse(res: Response, data: TransferPacketVO<any>, requestTime: number, endpoint?: string, log?: APIServiceNetworkLogItem | null, req?: HTTPRequestVO): Promise<void>;
|
63
|
+
sendResponse(ref: string, res: Response, data: TransferPacketVO<any>, requestTime: number, endpoint?: string, log?: APIServiceNetworkLogItem | null, req?: HTTPRequestVO): Promise<void>;
|
63
64
|
checkDataLength(data: any, result?: any, lvl?: number): any;
|
64
65
|
}
|
@@ -83,7 +83,7 @@ async function Initializer(services) {
|
|
83
83
|
exports.Initializer = Initializer;
|
84
84
|
class APIService extends BaseService_1.BaseService {
|
85
85
|
static nextLogID = 0;
|
86
|
-
version = "2.1.
|
86
|
+
version = "2.1.4";
|
87
87
|
options;
|
88
88
|
monitor;
|
89
89
|
monitorIndexFile;
|
@@ -154,10 +154,10 @@ class APIService extends BaseService_1.BaseService {
|
|
154
154
|
app.use(express_1.default.urlencoded({ limit: '10mb', extended: true }));
|
155
155
|
app.use((0, express_fileupload_1.default)({
|
156
156
|
limitHandler: (req, res, next) => {
|
157
|
-
this.sendResponse(res, {
|
157
|
+
this.sendResponse(req.get("Referer") ?? "", res, {
|
158
158
|
error: DefaultErrors_1.default.FILE_TOO_LARGE,
|
159
159
|
data: null,
|
160
|
-
httpStatus: 413
|
160
|
+
httpStatus: 413,
|
161
161
|
}, +new Date(), req.path);
|
162
162
|
},
|
163
163
|
limits: { fileSize: this.options.fileLimit },
|
@@ -182,7 +182,7 @@ class APIService extends BaseService_1.BaseService {
|
|
182
182
|
if (typeof err === "object" && err.status === 400 && 'body' in err && err.type === 'entity.parse.failed') {
|
183
183
|
responseError = DefaultErrors_1.default.JSON_MALFORMED;
|
184
184
|
}
|
185
|
-
this.sendResponse(resp, {
|
185
|
+
this.sendResponse(req.get("Referer") ?? "", resp, {
|
186
186
|
error: responseError,
|
187
187
|
data: null,
|
188
188
|
httpStatus: 400
|
@@ -231,7 +231,8 @@ class APIService extends BaseService_1.BaseService {
|
|
231
231
|
params: req.params,
|
232
232
|
headers: req.headers,
|
233
233
|
endpoint: ep,
|
234
|
-
files: req.files ?? null
|
234
|
+
files: req.files ?? null,
|
235
|
+
referer: req.get("Referer"),
|
235
236
|
};
|
236
237
|
if (this.options.preproducer) {
|
237
238
|
try {
|
@@ -240,7 +241,7 @@ class APIService extends BaseService_1.BaseService {
|
|
240
241
|
httpRequest.preproducerResult = preproducerResult;
|
241
242
|
}
|
242
243
|
catch (e) {
|
243
|
-
this.sendResponse(res, { error: { code: 10002, message: "Internal server error", details: `${e}` }, data: null, httpStatus: 500 }, tme, ep, log, httpRequest);
|
244
|
+
this.sendResponse(req.get("Referer") ?? "", res, { error: { code: 10002, message: "Internal server error", details: `${e}` }, data: null, httpStatus: 500 }, tme, ep, log, httpRequest);
|
244
245
|
return;
|
245
246
|
}
|
246
247
|
}
|
@@ -251,7 +252,7 @@ class APIService extends BaseService_1.BaseService {
|
|
251
252
|
if (this.options.interceptor) {
|
252
253
|
interceptorResult = await this.options.interceptor.execute(httpRequest);
|
253
254
|
if (interceptorResult.error && !j.allowInterceptorError) {
|
254
|
-
this.sendResponse(res, interceptorResult, tme, ep, log, httpRequest);
|
255
|
+
this.sendResponse(req.get("Referer") ?? "", res, interceptorResult, tme, ep, log, httpRequest);
|
255
256
|
return;
|
256
257
|
}
|
257
258
|
httpRequest.interceptorResult = interceptorResult;
|
@@ -261,7 +262,7 @@ class APIService extends BaseService_1.BaseService {
|
|
261
262
|
httpRequest.precheck = { data: this.options.monitor };
|
262
263
|
const precheck = await i.precheck(httpRequest);
|
263
264
|
if (precheck && precheck.error) {
|
264
|
-
this.sendResponse(res, precheck, tme, ep, log, httpRequest);
|
265
|
+
this.sendResponse(req.get("Referer") ?? "", res, precheck, tme, ep, log, httpRequest);
|
265
266
|
return;
|
266
267
|
}
|
267
268
|
httpRequest.precheck = precheck;
|
@@ -273,7 +274,7 @@ class APIService extends BaseService_1.BaseService {
|
|
273
274
|
this.options.onError(e);
|
274
275
|
if (this.monitor)
|
275
276
|
this.monitor.registrateFatalError(ep);
|
276
|
-
this.sendResponse(res, {
|
277
|
+
this.sendResponse(req.get("Referer") ?? "", res, {
|
277
278
|
httpStatus: 500,
|
278
279
|
error: {
|
279
280
|
code: 10002,
|
@@ -283,7 +284,7 @@ class APIService extends BaseService_1.BaseService {
|
|
283
284
|
}, tme, ep, log, httpRequest);
|
284
285
|
return;
|
285
286
|
}
|
286
|
-
this.sendResponse(res, result, tme, ep, log, httpRequest);
|
287
|
+
this.sendResponse(req.get("Referer") ?? "", res, result, tme, ep, log, httpRequest);
|
287
288
|
};
|
288
289
|
execute();
|
289
290
|
});
|
@@ -311,7 +312,7 @@ class APIService extends BaseService_1.BaseService {
|
|
311
312
|
res.status(200).send(this.monitorIndexFile);
|
312
313
|
}
|
313
314
|
catch (e) {
|
314
|
-
this.sendResponse(res, {
|
315
|
+
this.sendResponse(req.get("Referer") ?? "", res, {
|
315
316
|
error: {
|
316
317
|
code: 10002,
|
317
318
|
message: "Internal server error",
|
@@ -325,7 +326,7 @@ class APIService extends BaseService_1.BaseService {
|
|
325
326
|
}
|
326
327
|
}
|
327
328
|
}
|
328
|
-
this.sendResponse(res, {
|
329
|
+
this.sendResponse(req.get("Referer") ?? "", res, {
|
329
330
|
error: DefaultErrors_1.default.UNKNOWN_REQUEST,
|
330
331
|
data: null,
|
331
332
|
httpStatus: 404
|
@@ -335,7 +336,7 @@ class APIService extends BaseService_1.BaseService {
|
|
335
336
|
(0, LogService_1.logCrit)('${APIService.js}', 'API Service started at: ' + this.options.port + ", with base endpoint:" + this.options.baseEndPoint + ", ver.: " + this.version);
|
336
337
|
});
|
337
338
|
}
|
338
|
-
async sendResponse(res, data, requestTime, endpoint, log, req) {
|
339
|
+
async sendResponse(ref, res, data, requestTime, endpoint, log, req) {
|
339
340
|
if (this.options.postproducer) {
|
340
341
|
try {
|
341
342
|
data = await this.options.postproducer(req, res, data, requestTime, endpoint, log);
|
@@ -351,8 +352,10 @@ class APIService extends BaseService_1.BaseService {
|
|
351
352
|
data.endpoint = endpoint ?? "no_endpoint";
|
352
353
|
if (this.options.appVersion)
|
353
354
|
data.version = this.options.appVersion;
|
354
|
-
if (log)
|
355
|
+
if (log) {
|
355
356
|
log.time = data.responseTime;
|
357
|
+
log.referer = ref;
|
358
|
+
}
|
356
359
|
if (this.monitor)
|
357
360
|
this.monitor.registrateResponse(data.endpoint, data.responseTime);
|
358
361
|
if (res.destroyed || res.closed) {
|
@@ -374,7 +377,7 @@ class APIService extends BaseService_1.BaseService {
|
|
374
377
|
this.options.onError("Can't send file: " + data.file, err);
|
375
378
|
if (this.monitor && data.endpoint)
|
376
379
|
this.monitor.registrateAPIError(data.endpoint);
|
377
|
-
this.sendResponse(res, {
|
380
|
+
this.sendResponse(ref, res, {
|
378
381
|
error: DefaultErrors_1.default.CANT_SEND_FILE,
|
379
382
|
data: null,
|
380
383
|
httpStatus: 500
|
@@ -1,6 +1,6 @@
|
|
1
|
-
import { FieldInfo, MysqlError, Pool, PoolConnection } from "mysql";
|
2
1
|
import { BaseService } from "./BaseService";
|
3
2
|
import Signal, { Req } from "badmfck-signal";
|
3
|
+
import * as mysql from "mysql2/promise";
|
4
4
|
export declare const S_MYSQL_STARTED: Signal<void>;
|
5
5
|
export declare const REQ_MYSQL_QUERY: Req<MySqlQuery | MySqlQuery[], MysqlResult[]>;
|
6
6
|
export declare const executeQuery: (query: MySqlQuery | MySqlQuery[]) => Promise<MysqlResult[]>;
|
@@ -11,20 +11,30 @@ export interface MysqlServiceOptions {
|
|
11
11
|
password: string;
|
12
12
|
port: number;
|
13
13
|
database: string;
|
14
|
+
queueLimit?: number;
|
14
15
|
migrations?: {
|
15
16
|
dir: string;
|
16
17
|
callback: () => void;
|
17
18
|
} | null;
|
18
19
|
}
|
20
|
+
export interface MysqlError {
|
21
|
+
code: string;
|
22
|
+
errno: number;
|
23
|
+
sql: string;
|
24
|
+
name: string;
|
25
|
+
message: string;
|
26
|
+
fatal?: boolean;
|
27
|
+
}
|
19
28
|
export interface MysqlResult {
|
20
29
|
error?: MysqlError | null;
|
30
|
+
rollbackError?: MysqlError | null;
|
21
31
|
isDuplicateError?: boolean;
|
22
|
-
fields?: FieldInfo[] | null;
|
23
32
|
data: any;
|
24
33
|
}
|
25
34
|
export interface MySqlQuery {
|
26
35
|
query: string;
|
27
36
|
fields: MysqlQueryField[] | MysqlQueryFieldObject;
|
37
|
+
rollbackQuery?: string | null;
|
28
38
|
}
|
29
39
|
export interface MysqlQueryField {
|
30
40
|
name: string;
|
@@ -46,7 +56,7 @@ export interface MysqlQueryFieldObject extends Record<string, string | number |
|
|
46
56
|
export declare class MysqlService extends BaseService {
|
47
57
|
reconnectionTimeout: number;
|
48
58
|
reconnecting: boolean;
|
49
|
-
pool: Pool | null;
|
59
|
+
pool: mysql.Pool | null;
|
50
60
|
options: MysqlServiceOptions;
|
51
61
|
serviceStarted: boolean;
|
52
62
|
timeoutID: any;
|
@@ -54,14 +64,17 @@ export declare class MysqlService extends BaseService {
|
|
54
64
|
constructor(options: MysqlServiceOptions);
|
55
65
|
static executeQuery(query: MySqlQuery | MySqlQuery[]): Promise<MysqlResult[]>;
|
56
66
|
init(): Promise<void>;
|
57
|
-
recreatePool(): Promise<
|
67
|
+
recreatePool(): Promise<boolean>;
|
58
68
|
onApplicationReady(): Promise<void>;
|
59
69
|
static fieldsToObject(fields: MysqlQueryField[] | MysqlQueryFieldObject, ignoreSystemParameters?: boolean): MysqlQueryFieldObject;
|
60
70
|
static objectToFields(obj: MysqlQueryFieldObject | MysqlQueryField[]): MysqlQueryField[];
|
61
71
|
static prepareQuery(query: string, fields: MysqlQueryField[] | MysqlQueryFieldObject): string;
|
62
72
|
static prepareQueryFieldValue(value: string | number | boolean | null | undefined, system?: boolean): string | number | boolean | null | undefined;
|
63
|
-
execute(query: string): Promise<MysqlResult>;
|
64
|
-
sendQuery(conn: PoolConnection, query: string, resolve: (data: MysqlResult) => void): void
|
65
|
-
|
73
|
+
execute(query: string, rollbackQuery: string | null): Promise<MysqlResult>;
|
74
|
+
sendQuery(conn: mysql.PoolConnection, query: string, resolve: (data: MysqlResult) => void, rollback: string | null): Promise<void>;
|
75
|
+
queryAsync(conn: mysql.PoolConnection, query: string): Promise<{
|
76
|
+
err: MysqlError | null;
|
77
|
+
results?: any;
|
78
|
+
}>;
|
66
79
|
}
|
67
80
|
export default MysqlService;
|
@@ -22,16 +22,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
22
22
|
__setModuleDefault(result, mod);
|
23
23
|
return result;
|
24
24
|
};
|
25
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
27
|
-
};
|
28
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
29
26
|
exports.MysqlService = exports.executeQuery = exports.REQ_MYSQL_QUERY = exports.S_MYSQL_STARTED = void 0;
|
30
|
-
const mysql_1 = __importDefault(require("mysql"));
|
31
27
|
const BaseService_1 = require("./BaseService");
|
32
28
|
const badmfck_signal_1 = __importStar(require("badmfck-signal"));
|
33
29
|
const crypto_1 = require("crypto");
|
34
30
|
const LogService_1 = require("./LogService");
|
31
|
+
const mysql = __importStar(require("mysql2/promise"));
|
35
32
|
exports.S_MYSQL_STARTED = new badmfck_signal_1.default();
|
36
33
|
exports.REQ_MYSQL_QUERY = new badmfck_signal_1.Req(undefined, "REQ_MYSQL_QUERY");
|
37
34
|
const executeQuery = async (query) => { return await exports.REQ_MYSQL_QUERY.request(query); };
|
@@ -58,34 +55,98 @@ class MysqlService extends BaseService_1.BaseService {
|
|
58
55
|
}
|
59
56
|
static async executeQuery(query) { return await exports.REQ_MYSQL_QUERY.request(query); }
|
60
57
|
async init() {
|
58
|
+
super.init();
|
59
|
+
process.on('SIGINT', async () => {
|
60
|
+
console.log('1. Received SIGINT. Performing cleanup...');
|
61
|
+
if (this.pool) {
|
62
|
+
try {
|
63
|
+
await this.pool.end();
|
64
|
+
}
|
65
|
+
catch (e) {
|
66
|
+
(0, LogService_1.logCrit)("${MysqlService.js}", "Can't close MYSQL pool!");
|
67
|
+
}
|
68
|
+
}
|
69
|
+
process.exit(0);
|
70
|
+
});
|
71
|
+
process.on('SIGTERM', () => {
|
72
|
+
console.log('2. Received SIGTERM. Performing cleanup...');
|
73
|
+
process.exit(0);
|
74
|
+
});
|
61
75
|
this.serviceStarted = false;
|
62
|
-
|
76
|
+
let poolCreated = false;
|
77
|
+
while (!poolCreated) {
|
78
|
+
(0, LogService_1.logInfo)("${MysqlService.js}", "Connecting to MYSQL!");
|
79
|
+
poolCreated = await this.recreatePool();
|
80
|
+
if (!poolCreated) {
|
81
|
+
(0, LogService_1.logCrit)("${MysqlService.js}", "Can't connect to MYSQL! Retrying in 3 seconds...");
|
82
|
+
await new Promise((resolve) => setTimeout(resolve, 3000));
|
83
|
+
}
|
84
|
+
}
|
63
85
|
exports.REQ_MYSQL_QUERY.listener = async (data) => {
|
64
86
|
if (!Array.isArray(data))
|
65
87
|
data = [data];
|
66
88
|
const promises = [];
|
67
89
|
for (let i of data) {
|
68
90
|
const query = MysqlService.prepareQuery(i.query, i.fields);
|
69
|
-
promises.push(this.execute(query));
|
91
|
+
promises.push(this.execute(query, i.rollbackQuery ?? null));
|
70
92
|
}
|
71
93
|
return await Promise.all(promises);
|
72
94
|
};
|
73
95
|
}
|
74
96
|
async recreatePool() {
|
75
|
-
(0, LogService_1.logInfo)("${MysqlService.js}", "
|
76
|
-
this.
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
97
|
+
(0, LogService_1.logInfo)("${MysqlService.js}", "Connecting to mysql: \n HOST: " + this.options.host + '\n PORT:' + this.options.port);
|
98
|
+
if (this.pool) {
|
99
|
+
this.pool.removeAllListeners();
|
100
|
+
try {
|
101
|
+
await this.pool.end();
|
102
|
+
}
|
103
|
+
catch (e) {
|
104
|
+
(0, LogService_1.logCrit)("${MysqlService.js}", "Can't close MYSQL pool!");
|
105
|
+
}
|
106
|
+
this.pool = null;
|
83
107
|
}
|
84
|
-
|
85
|
-
this.
|
86
|
-
|
87
|
-
|
108
|
+
try {
|
109
|
+
this.pool = mysql.createPool({
|
110
|
+
host: this.options.host,
|
111
|
+
user: this.options.user,
|
112
|
+
password: this.options.password,
|
113
|
+
database: this.options.database,
|
114
|
+
port: this.options.port,
|
115
|
+
connectionLimit: this.options.connectionLimit,
|
116
|
+
queueLimit: 10
|
117
|
+
});
|
88
118
|
}
|
119
|
+
catch (e) {
|
120
|
+
(0, LogService_1.logCrit)("${MysqlService.js}", "Can't connect to MYSQL!");
|
121
|
+
return false;
|
122
|
+
}
|
123
|
+
this.pool?.on('connection', (connection) => {
|
124
|
+
(0, LogService_1.logInfo)("${MysqlService.js}", "MYSQL CONNECTION CREATED");
|
125
|
+
});
|
126
|
+
this.pool?.on('acquire', (connection) => {
|
127
|
+
(0, LogService_1.logInfo)("${MysqlService.js}", "MYSQL CONNECTION ACQUIRED");
|
128
|
+
});
|
129
|
+
this.pool?.on('release', (connection) => {
|
130
|
+
(0, LogService_1.logInfo)("${MysqlService.js}", "MYSQL CONNECTION RELEASED");
|
131
|
+
});
|
132
|
+
this.pool?.on('enqueue', () => {
|
133
|
+
(0, LogService_1.logInfo)("${MysqlService.js}", "MYSQL CONNECTION ENQUEUED");
|
134
|
+
});
|
135
|
+
return new Promise(async (resolve, reject) => {
|
136
|
+
try {
|
137
|
+
const conn = await this.pool?.getConnection();
|
138
|
+
if (conn) {
|
139
|
+
conn?.release();
|
140
|
+
resolve(true);
|
141
|
+
}
|
142
|
+
else
|
143
|
+
resolve(false);
|
144
|
+
}
|
145
|
+
catch (e) {
|
146
|
+
(0, LogService_1.logCrit)("${MysqlService.js}", "Can't connect to MYSQL!");
|
147
|
+
resolve(false);
|
148
|
+
}
|
149
|
+
});
|
89
150
|
}
|
90
151
|
async onApplicationReady() { }
|
91
152
|
static fieldsToObject(fields, ignoreSystemParameters) {
|
@@ -206,8 +267,8 @@ class MysqlService extends BaseService_1.BaseService {
|
|
206
267
|
return "NULL";
|
207
268
|
return value;
|
208
269
|
}
|
209
|
-
async execute(query) {
|
210
|
-
return new Promise((resolve, reject) => {
|
270
|
+
async execute(query, rollbackQuery) {
|
271
|
+
return new Promise(async (resolve, reject) => {
|
211
272
|
if (!this.pool) {
|
212
273
|
(0, LogService_1.logError)("${MysqlService.js}", "No pool");
|
213
274
|
resolve({
|
@@ -220,23 +281,11 @@ class MysqlService extends BaseService_1.BaseService {
|
|
220
281
|
message: "Mysql pool not created"
|
221
282
|
},
|
222
283
|
data: null,
|
223
|
-
fields: null
|
224
284
|
});
|
225
285
|
return;
|
226
286
|
}
|
227
|
-
|
228
|
-
|
229
|
-
(0, LogService_1.logError)("${MysqlService.js}", err);
|
230
|
-
if (`${err}`.indexOf('ECONNREFUSED') !== -1) {
|
231
|
-
this.recreatePool();
|
232
|
-
}
|
233
|
-
resolve({
|
234
|
-
error: err,
|
235
|
-
data: null,
|
236
|
-
fields: null
|
237
|
-
});
|
238
|
-
return;
|
239
|
-
}
|
287
|
+
try {
|
288
|
+
const conn = await this.pool.getConnection();
|
240
289
|
if (!conn) {
|
241
290
|
(0, LogService_1.logCrit)("${MysqlService.js}", `No connection created!`);
|
242
291
|
resolve({
|
@@ -249,43 +298,43 @@ class MysqlService extends BaseService_1.BaseService {
|
|
249
298
|
message: "Mysql pool cant get connection"
|
250
299
|
},
|
251
300
|
data: null,
|
252
|
-
fields: null
|
253
|
-
});
|
254
|
-
}
|
255
|
-
try {
|
256
|
-
this.sendQuery(conn, query, resolve);
|
257
|
-
}
|
258
|
-
catch (e) {
|
259
|
-
try {
|
260
|
-
conn.removeAllListeners();
|
261
|
-
conn.release();
|
262
|
-
}
|
263
|
-
catch (e) { }
|
264
|
-
(0, LogService_1.logError)("${MysqlService.js}", "QUERY_ERR: " + e);
|
265
|
-
resolve({
|
266
|
-
error: {
|
267
|
-
code: "QUERY_ERR",
|
268
|
-
errno: 100002,
|
269
|
-
fatal: true,
|
270
|
-
sql: query,
|
271
|
-
name: "QUERY_ERR",
|
272
|
-
message: "Error: " + e
|
273
|
-
},
|
274
|
-
data: null,
|
275
|
-
fields: null
|
276
301
|
});
|
302
|
+
return;
|
277
303
|
}
|
278
|
-
|
304
|
+
this.sendQuery(conn, query, resolve, rollbackQuery);
|
305
|
+
}
|
306
|
+
catch (e) {
|
307
|
+
(0, LogService_1.logError)("${MysqlService.js}", e);
|
308
|
+
if (`${e}`.indexOf('ECONNREFUSED') !== -1)
|
309
|
+
this.recreatePool();
|
310
|
+
resolve({
|
311
|
+
error: {
|
312
|
+
code: "NO_CONN",
|
313
|
+
errno: 100001,
|
314
|
+
fatal: true,
|
315
|
+
sql: query,
|
316
|
+
name: "NO_CONN",
|
317
|
+
message: (e && typeof e === "object" && "message" in e) ? e.message : "Mysql cant get connection"
|
318
|
+
},
|
319
|
+
data: null
|
320
|
+
});
|
321
|
+
return;
|
322
|
+
}
|
279
323
|
});
|
280
324
|
}
|
281
|
-
sendQuery(conn, query, resolve) {
|
325
|
+
async sendQuery(conn, query, resolve, rollback) {
|
282
326
|
let errCatched = false;
|
283
|
-
conn.on("error", err => {
|
327
|
+
conn.on("error", async (err) => {
|
284
328
|
errCatched = true;
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
conn.
|
329
|
+
let rollbackError = null;
|
330
|
+
if (rollback)
|
331
|
+
rollbackError = (await this.queryAsync(conn, rollback)).err;
|
332
|
+
(0, LogService_1.logError)("${MysqlService.js}->conn.on('error')", err);
|
333
|
+
try {
|
334
|
+
conn.release();
|
335
|
+
conn.removeAllListeners();
|
336
|
+
}
|
337
|
+
catch (e) { }
|
289
338
|
resolve({
|
290
339
|
error: {
|
291
340
|
code: "CONN_ERR",
|
@@ -296,87 +345,71 @@ class MysqlService extends BaseService_1.BaseService {
|
|
296
345
|
message: "Error: " + err
|
297
346
|
},
|
298
347
|
data: null,
|
299
|
-
|
348
|
+
rollbackError: rollbackError
|
300
349
|
});
|
301
350
|
});
|
302
351
|
(0, LogService_1.logInfo)("${MysqlService.js}", query);
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
if (
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
resolve({
|
312
|
-
error: err,
|
313
|
-
data: null,
|
314
|
-
fields: null,
|
315
|
-
isDuplicateError: dup
|
316
|
-
});
|
317
|
-
return;
|
352
|
+
const queryResult = await this.queryAsync(conn, query);
|
353
|
+
if (queryResult.err) {
|
354
|
+
let rollbackError = null;
|
355
|
+
if (rollback)
|
356
|
+
rollbackError = (await this.queryAsync(conn, rollback)).err;
|
357
|
+
try {
|
358
|
+
conn.release();
|
359
|
+
conn.removeAllListeners();
|
318
360
|
}
|
361
|
+
catch (e) { }
|
362
|
+
const dup = `${queryResult.err}`.toLowerCase().indexOf("er_dup_entry") !== -1;
|
363
|
+
(0, LogService_1.logError)("${MysqlService.js}->query error", queryResult.err);
|
319
364
|
resolve({
|
320
|
-
error: err,
|
321
|
-
data:
|
322
|
-
|
365
|
+
error: queryResult.err,
|
366
|
+
data: null,
|
367
|
+
rollbackError: rollbackError,
|
368
|
+
isDuplicateError: dup
|
323
369
|
});
|
324
|
-
|
370
|
+
}
|
371
|
+
try {
|
372
|
+
conn.release();
|
373
|
+
conn.removeAllListeners();
|
374
|
+
}
|
375
|
+
catch (e) { }
|
376
|
+
resolve({
|
377
|
+
error: queryResult.err,
|
378
|
+
data: queryResult.results,
|
325
379
|
});
|
326
380
|
}
|
327
|
-
async
|
328
|
-
(0, LogService_1.logInfo)("${MysqlService.js}", "Connecting to mysql: \n HOST: " + this.options.host + '\n PORT:' + this.options.port);
|
329
|
-
let err = false;
|
330
|
-
if (this.pool) {
|
331
|
-
try {
|
332
|
-
this.pool.removeAllListeners();
|
333
|
-
this.pool.end(err => {
|
334
|
-
if (err)
|
335
|
-
(0, LogService_1.logError)("${MysqlService.js}", err);
|
336
|
-
});
|
337
|
-
}
|
338
|
-
catch (e) {
|
339
|
-
(0, LogService_1.logCrit)("${MysqlService.js}", e);
|
340
|
-
}
|
341
|
-
}
|
381
|
+
async queryAsync(conn, query) {
|
342
382
|
try {
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
port: this.options.port,
|
349
|
-
database: this.options.database,
|
350
|
-
multipleStatements: true
|
351
|
-
});
|
383
|
+
const result = await conn.query(query);
|
384
|
+
return {
|
385
|
+
err: null,
|
386
|
+
results: result[0],
|
387
|
+
};
|
352
388
|
}
|
353
389
|
catch (e) {
|
354
|
-
|
355
|
-
err
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
return;
|
366
|
-
}
|
367
|
-
if (!this.pool) {
|
368
|
-
res(false);
|
369
|
-
return;
|
390
|
+
const err = e;
|
391
|
+
if (err && typeof err === "object" && "code" in err && "errno" in err && "sql" in err && "name" in err && "message" in err) {
|
392
|
+
return {
|
393
|
+
err: {
|
394
|
+
code: err.code,
|
395
|
+
errno: err.errno,
|
396
|
+
sql: query,
|
397
|
+
name: err.name,
|
398
|
+
message: err.message
|
399
|
+
}
|
400
|
+
};
|
370
401
|
}
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
402
|
+
return {
|
403
|
+
err: {
|
404
|
+
code: "QUERY_ERR",
|
405
|
+
errno: 100002,
|
406
|
+
fatal: true,
|
407
|
+
sql: query,
|
408
|
+
name: "QUERY_ERR",
|
409
|
+
message: "Error: " + e
|
376
410
|
}
|
377
|
-
|
378
|
-
|
379
|
-
});
|
411
|
+
};
|
412
|
+
}
|
380
413
|
}
|
381
414
|
}
|
382
415
|
exports.MysqlService = MysqlService;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "badmfck-api-server",
|
3
|
-
"version": "2.1.
|
3
|
+
"version": "2.1.4",
|
4
4
|
"description": "Simple API http server based on express",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"types": "dist/index.d.ts",
|
@@ -25,7 +25,7 @@
|
|
25
25
|
"cors": "^2.8.5",
|
26
26
|
"express": "^4.19.2",
|
27
27
|
"express-fileupload": "^1.5.0",
|
28
|
-
"
|
28
|
+
"mysql2": "^3.11.3",
|
29
29
|
"ws": "^8.18.0"
|
30
30
|
},
|
31
31
|
"devDependencies": {
|