@pi-r/mysql 0.7.2 → 0.8.0

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/client/index.js CHANGED
@@ -1,57 +1,17 @@
1
1
  "use strict";
2
- exports.DB_SOURCE_TYPE = exports.DB_SOURCE_CLIENT = exports.checkTimeout = exports.executeBatchQuery = exports.executeQuery = exports.setCredential = exports.setAuthentication = void 0;
2
+ exports.DB_SOURCE_TYPE = exports.DB_SOURCE_CLIENT = void 0;
3
+ exports.setAuthentication = setAuthentication;
4
+ exports.setCredential = setCredential;
5
+ exports.executeQuery = executeQuery;
6
+ exports.executeBatchQuery = executeBatchQuery;
7
+ exports.checkTimeout = checkTimeout;
3
8
  const main = require("mysql2");
4
9
  const mysql = require("mysql2/promise");
10
+ const Db = require("@e-mc/db");
5
11
  const util_1 = require("@e-mc/db/util");
6
12
  const types_1 = require("@e-mc/types");
7
- const Db = require("@e-mc/db");
8
- const DbPool = require('@e-mc/db/pool');
9
- class MySQLPool extends DbPool {
10
- async getConnection() {
11
- return this.client.getConnection();
12
- }
13
- async close() {
14
- return this.client.end();
15
- }
16
- isEmpty() {
17
- const pool = this.client.pool;
18
- return this.closed || (0, util_1.checkEmpty)(pool._allConnections) && (0, util_1.checkEmpty)(pool._connectionQueue);
19
- }
20
- get closed() {
21
- return !!this.client.pool._closed;
22
- }
23
- }
13
+ const DbPool = require("@pi-r/mysql/client/pool");
24
14
  const POOL_STATE = {};
25
- const POOL_UNUSED = ['ssl', 'connectTimeout', 'queueLimit', 'waitForConnections', 'connectionLimit', 'maxIdle', 'idleTimeout', 'enableKeepAlive', 'keepAliveInitialDelay', 'Promise'];
26
- const POOL_ACTIVE = new WeakSet();
27
- function removePoolProperties(credential) {
28
- if (!credential.uuidKey && POOL_ACTIVE.has(credential)) {
29
- let result;
30
- for (let i = 0, length = POOL_UNUSED.length; i < length; ++i) {
31
- const attr = POOL_UNUSED[i];
32
- if (attr in credential) {
33
- result ||= { ...credential };
34
- if (attr !== 'ssl') {
35
- delete result[attr];
36
- }
37
- else if ((0, types_1.isObject)(result.ssl)) {
38
- result[attr] = true;
39
- }
40
- }
41
- }
42
- if (result) {
43
- return result;
44
- }
45
- }
46
- return credential;
47
- }
48
- function removeUUIDKey(credential) {
49
- if ('uuidKey' in credential) {
50
- credential = { ...credential };
51
- delete credential.uuidKey;
52
- }
53
- return credential;
54
- }
55
15
  function isResultSetHeader(value) {
56
16
  const result = Array.isArray(value) ? value[0] : value;
57
17
  if (result && !Array.isArray(result)) {
@@ -63,11 +23,6 @@ function isResultSetHeader(value) {
63
23
  }
64
24
  return false;
65
25
  }
66
- function getPoolKey(credential) {
67
- if ((credential.host || credential.socketPath) && credential.user) {
68
- return JSON.stringify(removeUUIDKey(credential));
69
- }
70
- }
71
26
  function setAuthentication(credential) {
72
27
  const auth = (0, util_1.parseServerAuth)(credential);
73
28
  credential.host ||= auth.hostname;
@@ -76,7 +31,6 @@ function setAuthentication(credential) {
76
31
  this.readTLSConfig(credential.ssl);
77
32
  }
78
33
  }
79
- exports.setAuthentication = setAuthentication;
80
34
  function setCredential(item) {
81
35
  let credential = this.getCredential(item);
82
36
  if (credential) {
@@ -86,18 +40,37 @@ function setCredential(item) {
86
40
  credential = { uri: item.uri };
87
41
  item.credential = credential;
88
42
  }
43
+ let host;
89
44
  if (!credential.uri) {
90
45
  const errors = [];
91
- if (!credential.host && !credential.socketPath) {
46
+ if (!(host = credential.host) && !credential.socketPath) {
92
47
  errors.push('host');
93
48
  }
94
49
  if (!credential.user) {
95
50
  errors.push('user');
96
51
  }
97
- if (errors.length) {
52
+ if (errors.length > 0) {
98
53
  throw (0, types_1.errorMessage)("mysql", 'Not defined - ' + errors.join(' | '));
99
54
  }
100
55
  }
56
+ else {
57
+ try {
58
+ ({ host } = new URL(credential.uri));
59
+ }
60
+ catch {
61
+ }
62
+ }
63
+ if (host?.endsWith('.rds.amazonaws.com')) {
64
+ try {
65
+ const ssl = credential.ssl ||= {};
66
+ if ((0, types_1.isPlainObject)(ssl) && !ssl.ca) {
67
+ const bundle = require('aws-ssl-profiles');
68
+ ssl.ca = bundle.ca;
69
+ }
70
+ }
71
+ catch {
72
+ }
73
+ }
101
74
  const usePool = item.usePool;
102
75
  if (!usePool) {
103
76
  return;
@@ -132,18 +105,19 @@ function setCredential(item) {
132
105
  credential.connectTimeout ??= timeout;
133
106
  }
134
107
  }
135
- const poolKey = getPoolKey(credential);
108
+ const poolKey = DbPool.asString(credential);
136
109
  if ((pool = POOL_STATE[poolKey]) && !pool.closed) {
137
110
  pool.add(item);
138
111
  return;
139
112
  }
140
- new MySQLPool(mysql.createPool(removeUUIDKey(credential)), poolKey, username && password ? { username, password } : undefined).add(item).parent = POOL_STATE;
113
+ const client = mysql.createPool(DbPool.removeUUIDKey(credential));
114
+ new DbPool(client, poolKey, username && password ? { username, password } : undefined)
115
+ .add(item)
116
+ .parent = POOL_STATE;
141
117
  }
142
- exports.setCredential = setCredential;
143
118
  async function executeQuery(item, options) {
144
119
  return (await executeBatchQuery.call(this, [item], options))[0] || [];
145
120
  }
146
- exports.executeQuery = executeQuery;
147
121
  async function executeBatchQuery(batch, options = '', outResult) {
148
122
  const length = batch.length;
149
123
  if (length === 0) {
@@ -178,20 +152,18 @@ async function executeBatchQuery(batch, options = '', outResult) {
178
152
  item.transactionState = 64;
179
153
  let client;
180
154
  if (mysqlPool) {
181
- pools.push(client = await mysqlPool.getConnection());
155
+ pools.push(client = await mysqlPool.getConnection(credential));
182
156
  item.transactionState &= ~64;
183
- POOL_ACTIVE.add(credential);
184
157
  return client;
185
158
  }
186
- const pool = item.usePool && DbPool.findKey(POOL_STATE, item.usePool, getPoolKey(credential), ...connectOnce ? [item, batch[0]] : [item]);
159
+ const pool = item.usePool && DbPool.findKey(POOL_STATE, item.usePool, DbPool.asString(credential), ...connectOnce ? [item, batch[0]] : [item]);
187
160
  if (pool) {
188
161
  try {
189
- pools.push(client = await pool.getConnection());
162
+ pools.push(client = await pool.getConnection(credential));
190
163
  if (connectOnce) {
191
164
  mysqlPool = pool;
192
165
  }
193
166
  pool.connected = true;
194
- POOL_ACTIVE.add(credential);
195
167
  }
196
168
  catch (err) {
197
169
  let close;
@@ -216,7 +188,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
216
188
  }
217
189
  }
218
190
  if (!client) {
219
- clients.push(client = await mysql.createConnection(removeUUIDKey(mysqlCredential || credential)));
191
+ clients.push(client = await mysql.createConnection(DbPool.removeUUIDKey(mysqlCredential || credential)));
220
192
  }
221
193
  if (connectOnce) {
222
194
  if (!parallel) {
@@ -266,7 +238,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
266
238
  if (caching && ignoreCache !== true && !streamRow) {
267
239
  queryString = Db.asString(query, true) + '_' + Db.asString(params, true);
268
240
  if (ignoreCache !== 1) {
269
- const result = this.getQueryResult(source, removePoolProperties(credential), queryString, cacheValue);
241
+ const result = this.getQueryResult(source, DbPool.sanitize(credential), queryString, cacheValue);
270
242
  if (result) {
271
243
  if (parallel) {
272
244
  tasks[i] = Promise.resolve(result);
@@ -297,8 +269,8 @@ async function executeBatchQuery(batch, options = '', outResult) {
297
269
  try {
298
270
  if (streamRow) {
299
271
  const rows = [];
300
- const processRow = typeof streamRow === 'function' && streamRow;
301
- const client = mysql2Client || main.createConnection(removeUUIDKey(mysql2Credential || credential));
272
+ const processRow = typeof streamRow === 'function' ? streamRow : null;
273
+ const client = mysql2Client || main.createConnection(DbPool.removeUUIDKey(mysql2Credential || credential));
302
274
  clients.push(client);
303
275
  if (connectOnce) {
304
276
  if (!parallel) {
@@ -329,7 +301,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
329
301
  }
330
302
  else {
331
303
  this.add(item, 4);
332
- resolve(!error ? this.setQueryResult(source, removePoolProperties(credential), queryString, rows, cacheValue) : rows.length ? rows : null);
304
+ resolve(!error ? this.setQueryResult(source, DbPool.sanitize(credential), queryString, rows, cacheValue) : rows.length > 0 ? rows : null);
333
305
  }
334
306
  });
335
307
  }
@@ -347,7 +319,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
347
319
  resolve(row1);
348
320
  }
349
321
  else {
350
- resolve(!isResultSetHeader(row1) ? this.setQueryResult(source, removePoolProperties(credential), queryString, rows, cacheValue) : null);
322
+ resolve(!isResultSetHeader(row1) ? this.setQueryResult(source, DbPool.sanitize(credential), queryString, rows, cacheValue) : null);
351
323
  }
352
324
  }
353
325
  else {
@@ -375,25 +347,23 @@ async function executeBatchQuery(batch, options = '', outResult) {
375
347
  }
376
348
  }
377
349
  return this.processRows(batch, tasks, {
350
+ parallel,
378
351
  disconnect: () => {
379
- clients.forEach(item => {
380
- item.end(err => {
352
+ for (const item of clients) {
353
+ void item.end(err => {
381
354
  if (err) {
382
355
  this.writeFail(["Unable to close connnection", "mysql"], err, { type: 65536, fatal: false });
383
356
  }
384
357
  });
385
- });
386
- pools.forEach(item => {
358
+ }
359
+ for (const item of pools) {
387
360
  item.release();
388
- });
389
- },
390
- parallel
361
+ }
362
+ }
391
363
  }, outResult);
392
364
  }
393
- exports.executeBatchQuery = executeBatchQuery;
394
365
  async function checkTimeout(value, limit = 0) {
395
366
  return DbPool.checkTimeout(POOL_STATE, value, limit);
396
367
  }
397
- exports.checkTimeout = checkTimeout;
398
368
  exports.DB_SOURCE_CLIENT = true;
399
369
  exports.DB_SOURCE_TYPE = types_1.DB_TYPE.SQL;
@@ -0,0 +1,9 @@
1
+ import type { DbPoolConstructor } from '@e-mc/types/lib/db';
2
+
3
+ import type { DbPoolCredential, MySQLDataSource } from '../types';
4
+
5
+ import type { Pool, PoolConnection } from 'mysql2/promise';
6
+
7
+ declare const MySQLPool: DbPoolConstructor<MySQLDataSource, Pool, PoolConnection, DbPoolCredential>;
8
+
9
+ export = MySQLPool;
package/client/pool.js ADDED
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ const util_1 = require("@e-mc/db/util");
3
+ const types_1 = require("@e-mc/types");
4
+ const DbPool = require('@e-mc/db/pool');
5
+ const POOL_ACTIVE = new WeakSet();
6
+ class MySQLPool extends DbPool {
7
+ static CACHE_UNUSED = ['connectTimeout', 'queueLimit', 'waitForConnections', 'connectionLimit', 'maxIdle', 'idleTimeout', 'enableKeepAlive', 'keepAliveInitialDelay', 'Promise'];
8
+ static asString(credential) {
9
+ if ((credential.host || credential.socketPath) && credential.user) {
10
+ return JSON.stringify(this.removeUUIDKey(credential));
11
+ }
12
+ return super.asString(credential);
13
+ }
14
+ static sanitize(credential) {
15
+ if (!POOL_ACTIVE.has(credential) || credential.uuidKey) {
16
+ return credential;
17
+ }
18
+ const ssl = credential.ssl;
19
+ let result = super.sanitize(credential);
20
+ if ((0, types_1.isObject)(ssl)) {
21
+ if (result === credential) {
22
+ result = { ...credential };
23
+ }
24
+ const cert = ssl.cert;
25
+ if ((0, types_1.isString)(cert)) {
26
+ result.ssl = cert;
27
+ }
28
+ else if (Buffer.isBuffer(cert)) {
29
+ result.ssl = cert.toString('utf-8');
30
+ }
31
+ else if ((0, types_1.isArray)(cert)) {
32
+ result.ssl = cert.reduce((a, b) => a + (Buffer.isBuffer(b) ? b.toString('utf-8') : b), '');
33
+ }
34
+ else {
35
+ result.ssl = "Unknown";
36
+ }
37
+ }
38
+ return result;
39
+ }
40
+ async getConnection(credential) {
41
+ if (credential) {
42
+ POOL_ACTIVE.add(credential);
43
+ }
44
+ return this.client.getConnection();
45
+ }
46
+ async close() {
47
+ return this.client.end();
48
+ }
49
+ isEmpty() {
50
+ const pool = this.client.pool;
51
+ return this.closed || (0, util_1.checkEmpty)(pool._allConnections) && (0, util_1.checkEmpty)(pool._connectionQueue);
52
+ }
53
+ get closed() {
54
+ return !!this.client.pool._closed;
55
+ }
56
+ }
57
+ module.exports = MySQLPool;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-r/mysql",
3
- "version": "0.7.2",
3
+ "version": "0.8.0",
4
4
  "description": "MySQL client driver for E-mc.",
5
5
  "main": "client/index.js",
6
6
  "types": "client/index.d.ts",
@@ -21,8 +21,8 @@
21
21
  "license": "MIT",
22
22
  "homepage": "https://github.com/anpham6/pi-r#readme",
23
23
  "dependencies": {
24
- "@e-mc/db": "^0.9.4",
25
- "@e-mc/types": "^0.9.4",
26
- "mysql2": "^3.10.1"
24
+ "@e-mc/db": "^0.10.0",
25
+ "@e-mc/types": "^0.10.0",
26
+ "mysql2": "^3.11.0"
27
27
  }
28
28
  }
package/types/index.d.ts CHANGED
@@ -1,15 +1,13 @@
1
1
  import type { DbDataSource } from '@e-mc/types/lib/squared';
2
2
 
3
+ import type { IdentifierAction } from '@e-mc/types/lib/core';
3
4
  import type { ExecuteAction, ServerAuth } from '@e-mc/types/lib/db';
4
5
 
5
- import type { SecureContextOptions } from 'tls';
6
-
7
6
  import type { PoolOptions, QueryOptions } from 'mysql2/promise';
8
7
 
9
8
  export interface MySQLDataSource<T = unknown> extends DbDataSource<string | QueryOptions, unknown, unknown, MySQLCredential, string>, ExecuteAction<T> {
10
9
  source: "mysql";
11
10
  }
12
11
 
13
- export interface MySQLCredential extends ServerAuth, Omit<PoolOptions, "ssl"> {
14
- ssl?: boolean | string | SecureContextOptions & { rejectUnauthorized?: boolean };
15
- }
12
+ export type MySQLCredential = PoolOptions & ServerAuth;
13
+ export type DbPoolCredential = PoolOptions & IdentifierAction;