badmfck-api-server 1.0.2 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -43,7 +43,7 @@ async function Initializer(services) {
43
43
  exports.Initializer = Initializer;
44
44
  class APIService extends BaseService_1.BaseService {
45
45
  static nextLogID = 0;
46
- version = "1.2.0";
46
+ version = "1.2.1";
47
47
  options;
48
48
  netLog = [];
49
49
  constructor(options) {
@@ -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 = exports.HTTP_STATUS || (exports.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
- export { APIService, Initializer, LocalRequest };
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.2",
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