badmfck-api-server 2.1.3 → 2.1.5

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.
@@ -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.3";
86
+ version = "2.1.5";
87
87
  options;
88
88
  monitor;
89
89
  monitorIndexFile;
@@ -1,8 +1,9 @@
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
+ export declare const REQ_MYSQL_TRANSACTION: Req<MySqlQuery[], MysqlResult>;
6
7
  export declare const executeQuery: (query: MySqlQuery | MySqlQuery[]) => Promise<MysqlResult[]>;
7
8
  export interface MysqlServiceOptions {
8
9
  connectionLimit: number;
@@ -11,16 +12,24 @@ export interface MysqlServiceOptions {
11
12
  password: string;
12
13
  port: number;
13
14
  database: string;
15
+ queueLimit?: number;
14
16
  migrations?: {
15
17
  dir: string;
16
18
  callback: () => void;
17
19
  } | null;
18
20
  }
21
+ export interface MysqlError {
22
+ code: string;
23
+ errno: number;
24
+ sql: string;
25
+ name: string;
26
+ message: string;
27
+ fatal?: boolean;
28
+ }
19
29
  export interface MysqlResult {
20
30
  error?: MysqlError | null;
21
31
  rollbackError?: MysqlError | null;
22
32
  isDuplicateError?: boolean;
23
- fields?: FieldInfo[] | null;
24
33
  data: any;
25
34
  }
26
35
  export interface MySqlQuery {
@@ -48,7 +57,7 @@ export interface MysqlQueryFieldObject extends Record<string, string | number |
48
57
  export declare class MysqlService extends BaseService {
49
58
  reconnectionTimeout: number;
50
59
  reconnecting: boolean;
51
- pool: Pool | null;
60
+ pool: mysql.Pool | null;
52
61
  options: MysqlServiceOptions;
53
62
  serviceStarted: boolean;
54
63
  timeoutID: any;
@@ -56,19 +65,18 @@ export declare class MysqlService extends BaseService {
56
65
  constructor(options: MysqlServiceOptions);
57
66
  static executeQuery(query: MySqlQuery | MySqlQuery[]): Promise<MysqlResult[]>;
58
67
  init(): Promise<void>;
59
- recreatePool(): Promise<void>;
68
+ recreatePool(): Promise<boolean>;
60
69
  onApplicationReady(): Promise<void>;
61
70
  static fieldsToObject(fields: MysqlQueryField[] | MysqlQueryFieldObject, ignoreSystemParameters?: boolean): MysqlQueryFieldObject;
62
71
  static objectToFields(obj: MysqlQueryFieldObject | MysqlQueryField[]): MysqlQueryField[];
63
72
  static prepareQuery(query: string, fields: MysqlQueryField[] | MysqlQueryFieldObject): string;
64
73
  static prepareQueryFieldValue(value: string | number | boolean | null | undefined, system?: boolean): string | number | boolean | null | undefined;
65
74
  execute(query: string, rollbackQuery: string | null): Promise<MysqlResult>;
66
- sendQuery(conn: PoolConnection, query: string, resolve: (data: MysqlResult) => void, rollback: string | null): Promise<void>;
67
- queryAsync(conn: PoolConnection, query: string): Promise<{
75
+ sendQuery(conn: mysql.PoolConnection, query: string, resolve: (data: MysqlResult) => void, rollback: string | null): Promise<void>;
76
+ queryAsync(conn: mysql.PoolConnection, query: string): Promise<{
68
77
  err: MysqlError | null;
69
78
  results?: any;
70
- fields?: FieldInfo[];
71
79
  }>;
72
- createPool(): Promise<boolean>;
80
+ createMysqlQueryError(err: any): MysqlError;
73
81
  }
74
82
  export default MysqlService;
@@ -22,18 +22,16 @@ 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
- exports.MysqlService = exports.executeQuery = exports.REQ_MYSQL_QUERY = exports.S_MYSQL_STARTED = void 0;
30
- const mysql_1 = __importDefault(require("mysql"));
26
+ exports.MysqlService = exports.executeQuery = exports.REQ_MYSQL_TRANSACTION = exports.REQ_MYSQL_QUERY = exports.S_MYSQL_STARTED = void 0;
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");
34
+ exports.REQ_MYSQL_TRANSACTION = new badmfck_signal_1.Req(undefined, "REQ_MYSQL_TRANSACTION");
37
35
  const executeQuery = async (query) => { return await exports.REQ_MYSQL_QUERY.request(query); };
38
36
  exports.executeQuery = executeQuery;
39
37
  class MysqlService extends BaseService_1.BaseService {
@@ -58,8 +56,33 @@ class MysqlService extends BaseService_1.BaseService {
58
56
  }
59
57
  static async executeQuery(query) { return await exports.REQ_MYSQL_QUERY.request(query); }
60
58
  async init() {
59
+ super.init();
60
+ process.on('SIGINT', async () => {
61
+ console.log('1. Received SIGINT. Performing cleanup...');
62
+ if (this.pool) {
63
+ try {
64
+ await this.pool.end();
65
+ }
66
+ catch (e) {
67
+ (0, LogService_1.logCrit)("${MysqlService.js}", "Can't close MYSQL pool!");
68
+ }
69
+ }
70
+ process.exit(0);
71
+ });
72
+ process.on('SIGTERM', () => {
73
+ console.log('2. Received SIGTERM. Performing cleanup...');
74
+ process.exit(0);
75
+ });
61
76
  this.serviceStarted = false;
62
- await this.recreatePool();
77
+ let poolCreated = false;
78
+ while (!poolCreated) {
79
+ (0, LogService_1.logInfo)("${MysqlService.js}", "Connecting to MYSQL!");
80
+ poolCreated = await this.recreatePool();
81
+ if (!poolCreated) {
82
+ (0, LogService_1.logCrit)("${MysqlService.js}", "Can't connect to MYSQL! Retrying in 3 seconds...");
83
+ await new Promise((resolve) => setTimeout(resolve, 3000));
84
+ }
85
+ }
63
86
  exports.REQ_MYSQL_QUERY.listener = async (data) => {
64
87
  if (!Array.isArray(data))
65
88
  data = [data];
@@ -70,22 +93,97 @@ class MysqlService extends BaseService_1.BaseService {
70
93
  }
71
94
  return await Promise.all(promises);
72
95
  };
96
+ exports.REQ_MYSQL_TRANSACTION.listener = async (data) => {
97
+ if (!this.pool)
98
+ return { error: { code: "NO_POOL", errno: 100000, fatal: true, sql: "", name: "NO_POOL", message: "Mysql pool not created" }, data: null };
99
+ const conn = await this.pool.getConnection();
100
+ if (!conn)
101
+ return { error: { code: "NO_CONN", errno: 100001, fatal: true, sql: "", name: "NO_CONN", message: "Mysql pool cant get connection" }, data: null };
102
+ let result = null;
103
+ let income = [];
104
+ try {
105
+ await conn.beginTransaction();
106
+ await conn.query("SET autocommit=0");
107
+ for (let i of data) {
108
+ const d = await conn.query(MysqlService.prepareQuery(i.query, i.fields));
109
+ income.push(d[0]);
110
+ }
111
+ await conn.commit();
112
+ }
113
+ catch (e) {
114
+ let rollbackError = null;
115
+ try {
116
+ await conn.rollback();
117
+ }
118
+ catch (e2) {
119
+ (0, LogService_1.logCrit)("${MysqlService.js}", "Can't rollback transaction!");
120
+ rollbackError = this.createMysqlQueryError(e2);
121
+ }
122
+ result = { error: this.createMysqlQueryError(e), data: null, rollbackError: rollbackError };
123
+ }
124
+ try {
125
+ conn.release();
126
+ }
127
+ catch (e) { }
128
+ if (!result)
129
+ result = { error: null, data: income };
130
+ return result;
131
+ };
73
132
  }
74
133
  async recreatePool() {
75
- (0, LogService_1.logInfo)("${MysqlService.js}", "Mysql server trying to create pool");
76
- this.serviceStarted = false;
77
- const ok = await this.createPool();
78
- if (!ok) {
79
- (0, LogService_1.logWarn)("${MysqlService.js}", "Mysql server not connected, retrying in 3 sec");
80
- if (this.timeoutID)
81
- clearTimeout(this.timeoutID);
82
- this.timeoutID = setTimeout(() => { this.recreatePool(); }, 3000);
134
+ (0, LogService_1.logInfo)("${MysqlService.js}", "Connecting to mysql: \n HOST: " + this.options.host + '\n PORT:' + this.options.port);
135
+ if (this.pool) {
136
+ this.pool.removeAllListeners();
137
+ try {
138
+ await this.pool.end();
139
+ }
140
+ catch (e) {
141
+ (0, LogService_1.logCrit)("${MysqlService.js}", "Can't close MYSQL pool!");
142
+ }
143
+ this.pool = null;
83
144
  }
84
- else {
85
- this.serviceStarted = true;
86
- (0, LogService_1.logInfo)("${MysqlService.js}", "Mysql Service started!");
87
- exports.S_MYSQL_STARTED.invoke();
145
+ try {
146
+ this.pool = mysql.createPool({
147
+ host: this.options.host,
148
+ user: this.options.user,
149
+ password: this.options.password,
150
+ database: this.options.database,
151
+ port: this.options.port,
152
+ connectionLimit: this.options.connectionLimit,
153
+ queueLimit: 10
154
+ });
155
+ }
156
+ catch (e) {
157
+ (0, LogService_1.logCrit)("${MysqlService.js}", "Can't connect to MYSQL!");
158
+ return false;
88
159
  }
160
+ this.pool?.on('connection', (connection) => {
161
+ (0, LogService_1.logInfo)("${MysqlService.js}", "MYSQL CONNECTION CREATED");
162
+ });
163
+ this.pool?.on('acquire', (connection) => {
164
+ (0, LogService_1.logInfo)("${MysqlService.js}", "MYSQL CONNECTION ACQUIRED");
165
+ });
166
+ this.pool?.on('release', (connection) => {
167
+ (0, LogService_1.logInfo)("${MysqlService.js}", "MYSQL CONNECTION RELEASED");
168
+ });
169
+ this.pool?.on('enqueue', () => {
170
+ (0, LogService_1.logInfo)("${MysqlService.js}", "MYSQL CONNECTION ENQUEUED");
171
+ });
172
+ return new Promise(async (resolve, reject) => {
173
+ try {
174
+ const conn = await this.pool?.getConnection();
175
+ if (conn) {
176
+ conn?.release();
177
+ resolve(true);
178
+ }
179
+ else
180
+ resolve(false);
181
+ }
182
+ catch (e) {
183
+ (0, LogService_1.logCrit)("${MysqlService.js}", "Can't connect to MYSQL!");
184
+ resolve(false);
185
+ }
186
+ });
89
187
  }
90
188
  async onApplicationReady() { }
91
189
  static fieldsToObject(fields, ignoreSystemParameters) {
@@ -207,7 +305,7 @@ class MysqlService extends BaseService_1.BaseService {
207
305
  return value;
208
306
  }
209
307
  async execute(query, rollbackQuery) {
210
- return new Promise((resolve, reject) => {
308
+ return new Promise(async (resolve, reject) => {
211
309
  if (!this.pool) {
212
310
  (0, LogService_1.logError)("${MysqlService.js}", "No pool");
213
311
  resolve({
@@ -220,23 +318,11 @@ class MysqlService extends BaseService_1.BaseService {
220
318
  message: "Mysql pool not created"
221
319
  },
222
320
  data: null,
223
- fields: null
224
321
  });
225
322
  return;
226
323
  }
227
- this.pool.getConnection((err, conn) => {
228
- if (err) {
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
- }
324
+ try {
325
+ const conn = await this.pool.getConnection();
240
326
  if (!conn) {
241
327
  (0, LogService_1.logCrit)("${MysqlService.js}", `No connection created!`);
242
328
  resolve({
@@ -249,11 +335,28 @@ class MysqlService extends BaseService_1.BaseService {
249
335
  message: "Mysql pool cant get connection"
250
336
  },
251
337
  data: null,
252
- fields: null
253
338
  });
339
+ return;
254
340
  }
255
341
  this.sendQuery(conn, query, resolve, rollbackQuery);
256
- });
342
+ }
343
+ catch (e) {
344
+ (0, LogService_1.logError)("${MysqlService.js}", e);
345
+ if (`${e}`.indexOf('ECONNREFUSED') !== -1)
346
+ this.recreatePool();
347
+ resolve({
348
+ error: {
349
+ code: "NO_CONN",
350
+ errno: 100001,
351
+ fatal: true,
352
+ sql: query,
353
+ name: "NO_CONN",
354
+ message: (e && typeof e === "object" && "message" in e) ? e.message : "Mysql cant get connection"
355
+ },
356
+ data: null
357
+ });
358
+ return;
359
+ }
257
360
  });
258
361
  }
259
362
  async sendQuery(conn, query, resolve, rollback) {
@@ -279,7 +382,6 @@ class MysqlService extends BaseService_1.BaseService {
279
382
  message: "Error: " + err
280
383
  },
281
384
  data: null,
282
- fields: null,
283
385
  rollbackError: rollbackError
284
386
  });
285
387
  });
@@ -299,7 +401,6 @@ class MysqlService extends BaseService_1.BaseService {
299
401
  resolve({
300
402
  error: queryResult.err,
301
403
  data: null,
302
- fields: null,
303
404
  rollbackError: rollbackError,
304
405
  isDuplicateError: dup
305
406
  });
@@ -312,87 +413,40 @@ class MysqlService extends BaseService_1.BaseService {
312
413
  resolve({
313
414
  error: queryResult.err,
314
415
  data: queryResult.results,
315
- fields: queryResult.fields
316
416
  });
317
417
  }
318
418
  async queryAsync(conn, query) {
319
- return new Promise((resolve, reject) => {
320
- try {
321
- conn.query(query, (err, results, fields) => {
322
- resolve({
323
- err: err,
324
- results: results,
325
- fields: fields
326
- });
327
- });
328
- }
329
- catch (e) {
330
- resolve({
331
- err: {
332
- code: "QUERY_ERR",
333
- errno: 100002,
334
- fatal: true,
335
- sql: query,
336
- name: "QUERY_ERR",
337
- message: "Error: " + e
338
- }
339
- });
340
- }
341
- });
342
- }
343
- async createPool() {
344
- (0, LogService_1.logInfo)("${MysqlService.js}", "Connecting to mysql: \n HOST: " + this.options.host + '\n PORT:' + this.options.port);
345
- let err = false;
346
- if (this.pool) {
347
- try {
348
- this.pool.removeAllListeners();
349
- this.pool.end(err => {
350
- if (err)
351
- (0, LogService_1.logError)("${MysqlService.js}", err);
352
- });
353
- }
354
- catch (e) {
355
- (0, LogService_1.logCrit)("${MysqlService.js}", e);
356
- }
357
- }
358
419
  try {
359
- this.pool = mysql_1.default.createPool({
360
- connectionLimit: this.options.connectionLimit,
361
- host: this.options.host,
362
- user: this.options.user,
363
- password: this.options.password,
364
- port: this.options.port,
365
- database: this.options.database,
366
- multipleStatements: true
367
- });
420
+ const result = await conn.query(query);
421
+ return {
422
+ err: null,
423
+ results: result[0],
424
+ };
368
425
  }
369
426
  catch (e) {
370
- (0, LogService_1.logCrit)("${MysqlService.js}", "Can't connect to MYSQL!");
371
- err = true;
427
+ return { err: this.createMysqlQueryError(e) };
372
428
  }
373
- if (!err && this.pool) {
374
- this.pool.on("error", (evt) => {
375
- (0, LogService_1.logError)("${MysqlService.js}", evt);
376
- });
429
+ }
430
+ createMysqlQueryError(err) {
431
+ if (err && typeof err === "object" && "code" in err && "errno" in err && "sql" in err && "name" in err && "message" in err) {
432
+ return {
433
+ code: err.code,
434
+ errno: err.errno,
435
+ sql: err.sql,
436
+ name: err.name,
437
+ message: err.message
438
+ };
439
+ }
440
+ else {
441
+ return {
442
+ code: "QUERY_ERR",
443
+ errno: 100002,
444
+ fatal: true,
445
+ sql: "no query",
446
+ name: "QUERY_ERR",
447
+ message: "Error: " + (err) ? err : ""
448
+ };
377
449
  }
378
- return new Promise((res, rej) => {
379
- if (err) {
380
- res(false);
381
- return;
382
- }
383
- if (!this.pool) {
384
- res(false);
385
- return;
386
- }
387
- this.pool.getConnection((e, cnn) => {
388
- if (e) {
389
- (0, LogService_1.logError)("${MysqlService.js}", e.message);
390
- res(false);
391
- return;
392
- }
393
- res(true);
394
- });
395
- });
396
450
  }
397
451
  }
398
452
  exports.MysqlService = MysqlService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "badmfck-api-server",
3
- "version": "2.1.3",
3
+ "version": "2.1.5",
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
- "mysql": "^2.18.1",
28
+ "mysql2": "^3.11.3",
29
29
  "ws": "^8.18.0"
30
30
  },
31
31
  "devDependencies": {