@pi-r/mssql 0.7.3 → 0.8.1

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,42 +1,15 @@
1
1
  "use strict";
2
- exports.DB_SOURCE_TYPE = exports.DB_SOURCE_CLIENT = exports.checkTimeout = exports.executeBatchQuery = exports.executeQuery = exports.setCredential = void 0;
2
+ exports.DB_SOURCE_TYPE = exports.DB_SOURCE_CLIENT = void 0;
3
+ exports.setCredential = setCredential;
4
+ exports.executeQuery = executeQuery;
5
+ exports.executeBatchQuery = executeBatchQuery;
6
+ exports.checkTimeout = checkTimeout;
3
7
  const tedious = require("tedious");
8
+ const Db = require("@e-mc/db");
4
9
  const types_1 = require("@e-mc/types");
5
10
  const util_1 = require("@e-mc/db/util");
6
- const Db = require("@e-mc/db");
11
+ const DbPool = require("@pi-r/mssql/client/pool");
7
12
  const TediousPool = require('tedious-connection-pool2');
8
- const DbPool = require('@e-mc/db/pool');
9
- class MSSQLPool extends DbPool {
10
- async getConnection() {
11
- return new Promise((resolve, reject) => {
12
- this.client.acquire((err, connection) => {
13
- if (err) {
14
- reject(err);
15
- }
16
- else {
17
- resolve(connection);
18
- }
19
- });
20
- });
21
- }
22
- async close() {
23
- return new Promise((resolve, reject) => {
24
- try {
25
- this.client.drain();
26
- resolve();
27
- }
28
- catch (err) {
29
- reject(err);
30
- }
31
- });
32
- }
33
- isEmpty() {
34
- return this.closed || (0, util_1.checkEmpty)(this.client.connections) && (0, util_1.checkEmpty)(this.client.waiting);
35
- }
36
- get closed() {
37
- return !!this.client.drained;
38
- }
39
- }
40
13
  const POOL_STATE = {};
41
14
  function convertParameters(sql, params, output) {
42
15
  if ((0, types_1.isPlainObject)(params)) {
@@ -57,9 +30,9 @@ function convertParameters(sql, params, output) {
57
30
  }
58
31
  const columns = value.columns;
59
32
  if ((0, types_1.isArray)(columns)) {
60
- columns.forEach(col => {
33
+ for (const col of columns) {
61
34
  col.type = convertType(sql, col.type, col.value, col.options ||= {});
62
- });
35
+ }
63
36
  }
64
37
  }
65
38
  this[output ? 'addOutputParameter' : 'addParameter'](name, type, value, options);
@@ -72,7 +45,10 @@ function convertType(sql, type, value, options) {
72
45
  if (typeof type === 'string') {
73
46
  result = sql[type];
74
47
  }
75
- else if ((0, types_1.isObject)(type) && type.name) {
48
+ else if ((0, types_1.isObject)(type)) {
49
+ if (typeof type.id === 'number' && typeof type.declaration === 'function' && typeof type.validate === 'function') {
50
+ return type;
51
+ }
76
52
  result = sql[type.name];
77
53
  }
78
54
  if (result) {
@@ -111,32 +87,6 @@ function convertType(sql, type, value, options) {
111
87
  return sql.VarChar;
112
88
  }
113
89
  }
114
- function getPoolKey(credential) {
115
- const auth = credential.authentication?.options;
116
- if (!credential.server || !(auth?.userName && auth.password)) {
117
- return;
118
- }
119
- const tls = credential.options?.cryptoCredentialsDetails;
120
- if (tls) {
121
- if (!(0, types_1.isObject)(tls)) {
122
- delete credential.options.cryptoCredentialsDetails;
123
- }
124
- else if (tls.ca || tls.cert || tls.key) {
125
- credential = { ...credential };
126
- if ('uuidKey' in credential) {
127
- delete credential.uuidKey;
128
- }
129
- credential.options = { ...credential.options };
130
- delete credential.options.cryptoCredentialsDetails;
131
- return JSON.stringify(credential) + '_tls';
132
- }
133
- }
134
- if ('uuidKey' in credential) {
135
- credential = { ...credential };
136
- delete credential.uuidKey;
137
- }
138
- return JSON.stringify(credential);
139
- }
140
90
  const isOutputParameters = (params) => (0, types_1.isPlainObject)(params) && Object.keys(params).length === 2 && 'input' in params && 'output' in params;
141
91
  function setCredential(item) {
142
92
  let credential = this.getCredential(item), hostname, username, password, port, database;
@@ -171,17 +121,65 @@ function setCredential(item) {
171
121
  options.port ||= +port;
172
122
  }
173
123
  }
174
- if (username || password) {
175
- authOptions.userName ||= username;
176
- authOptions.password ||= password;
124
+ let flags = 0;
125
+ switch (auth.type) {
126
+ case 'default':
127
+ flags = 1;
128
+ break;
129
+ case 'ntlm':
130
+ flags = 1;
131
+ if (!(0, types_1.isString)(authOptions.domain)) {
132
+ errors.push('authentication.options.domain');
133
+ }
134
+ break;
135
+ case 'azure-active-directory-password':
136
+ flags = 1 | 4;
137
+ break;
138
+ case 'token-credential':
139
+ if (!(0, types_1.isObject)(authOptions.credential)) {
140
+ errors.push('authentication.options.credential');
141
+ }
142
+ break;
143
+ case 'azure-active-directory-access-token':
144
+ if (!(0, types_1.isString)(authOptions.token)) {
145
+ errors.push('authentication.options.token');
146
+ }
147
+ break;
148
+ case 'azure-active-directory-msi-vm':
149
+ flags = 8;
150
+ break;
151
+ case 'azure-active-directory-msi-app-service':
152
+ flags = 4 | 8;
153
+ if (!(0, types_1.isString)(authOptions.msiSecret)) {
154
+ errors.push('authentication.options.msiSecret');
155
+ }
156
+ break;
157
+ case 'azure-active-directory-service-principal-secret':
158
+ flags = 4;
159
+ if (!(0, types_1.isString)(authOptions.clientSecret)) {
160
+ errors.push('authentication.options.clientSecret');
161
+ }
162
+ break;
177
163
  }
178
- if (!authOptions.userName) {
179
- errors.push('authentication.options.userName');
164
+ if (flags & 1) {
165
+ if (username || password) {
166
+ authOptions.userName ||= username;
167
+ authOptions.password ||= password;
168
+ }
169
+ if (!(0, types_1.isString)(authOptions.userName)) {
170
+ errors.push('authentication.options.userName');
171
+ }
172
+ if (!(0, types_1.isString)(authOptions.password)) {
173
+ errors.push('authentication.options.password');
174
+ }
180
175
  }
181
- if (!authOptions.password) {
182
- errors.push('authentication.options.password');
176
+ if ((flags & 4) && !(0, types_1.isString)(authOptions.clientId)) {
177
+ errors.push('authentication.options.clientId');
183
178
  }
184
- if (errors.length) {
179
+ if ((flags & 8) && !(0, types_1.isString)(authOptions.msiEndpoint)) {
180
+ errors.push('authentication.options.msiEndpoint');
181
+ }
182
+ if (errors.length > 0) {
185
183
  throw (0, types_1.errorMessage)("mssql", 'Not defined - ' + errors.join(' | '));
186
184
  }
187
185
  const options = credential.options;
@@ -235,18 +233,19 @@ function setCredential(item) {
235
233
  poolConfig.acquireTimeout ??= queue_idle;
236
234
  }
237
235
  }
238
- const poolKey = getPoolKey(credential);
236
+ const poolKey = DbPool.asString(credential);
239
237
  if ((pool = POOL_STATE[poolKey]) && !pool.closed) {
240
238
  pool.add(item);
241
239
  return;
242
240
  }
243
- new MSSQLPool(new TediousPool(poolConfig, credential), poolKey, username && password ? { username, password } : undefined).add(item).parent = POOL_STATE;
241
+ const client = new TediousPool(poolConfig, credential);
242
+ new DbPool(client, poolKey, username && password ? { username, password } : undefined)
243
+ .add(item)
244
+ .parent = POOL_STATE;
244
245
  }
245
- exports.setCredential = setCredential;
246
246
  async function executeQuery(item, options) {
247
247
  return (await executeBatchQuery.call(this, [item], options))[0] || [];
248
248
  }
249
- exports.executeQuery = executeQuery;
250
249
  async function executeBatchQuery(batch, options = '', outResult) {
251
250
  const length = batch.length;
252
251
  if (length === 0) {
@@ -285,7 +284,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
285
284
  item.transactionState &= ~64;
286
285
  return client;
287
286
  }
288
- const pool = item.usePool && DbPool.findKey(POOL_STATE, item.usePool, getPoolKey(credential), ...connectOnce ? [item, batch[0]] : [item]);
287
+ const pool = item.usePool && DbPool.findKey(POOL_STATE, item.usePool, DbPool.asString(credential), ...connectOnce ? [item, batch[0]] : [item]);
289
288
  if (pool) {
290
289
  try {
291
290
  client = await pool.getConnection();
@@ -401,7 +400,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
401
400
  mssqlClient = undefined;
402
401
  }
403
402
  commandType = this.commandType.SELECT;
404
- const processRow = typeof streamRow === 'function' && streamRow;
403
+ const processRow = typeof streamRow === 'function' ? streamRow : null;
405
404
  const rows = [];
406
405
  let recordset = 1, resume, output;
407
406
  const request = new tedious.Request(query, () => {
@@ -441,7 +440,9 @@ async function executeBatchQuery(batch, options = '', outResult) {
441
440
  try {
442
441
  const items = JSON.parse(data.value);
443
442
  if ((0, types_1.isArray)(items)) {
444
- items.forEach((col) => col.__recordset__ = recordset);
443
+ for (const col of items) {
444
+ col.__recordset__ = recordset;
445
+ }
445
446
  rows.push(...items);
446
447
  }
447
448
  }
@@ -516,21 +517,19 @@ async function executeBatchQuery(batch, options = '', outResult) {
516
517
  }
517
518
  }
518
519
  return this.processRows(batch, tasks, {
519
- disconnect: () => {
520
- clients.forEach(item => {
520
+ parallel,
521
+ disconnect() {
522
+ for (const item of clients) {
521
523
  item.close();
522
- });
523
- pools.forEach(item => {
524
+ }
525
+ for (const item of pools) {
524
526
  item.release();
525
- });
526
- },
527
- parallel
527
+ }
528
+ }
528
529
  }, outResult);
529
530
  }
530
- exports.executeBatchQuery = executeBatchQuery;
531
531
  async function checkTimeout(value, limit = 0) {
532
532
  return DbPool.checkTimeout(POOL_STATE, value, limit);
533
533
  }
534
- exports.checkTimeout = checkTimeout;
535
534
  exports.DB_SOURCE_CLIENT = true;
536
535
  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, MSSQLDataSource } from '../types';
4
+
5
+ import type * as mssql_pool from '../types/pool';
6
+
7
+ declare const MSSQLPool: DbPoolConstructor<MSSQLDataSource, mssql_pool, mssql_pool.PooledConnection, DbPoolCredential>;
8
+
9
+ export = MSSQLPool;
package/client/pool.js ADDED
@@ -0,0 +1,63 @@
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
+ class MSSQLPool extends DbPool {
6
+ static asString(credential) {
7
+ const auth = credential.authentication?.options;
8
+ if (!credential.server || !(auth?.userName && auth.password)) {
9
+ return super.asString(credential);
10
+ }
11
+ const options = credential.options;
12
+ let tls;
13
+ if (options && (tls = options.cryptoCredentialsDetails)) {
14
+ if (!(0, types_1.isObject)(tls)) {
15
+ delete options.cryptoCredentialsDetails;
16
+ }
17
+ else if (tls.ca || tls.cert || tls.key) {
18
+ credential = { ...credential };
19
+ if ('uuidKey' in credential) {
20
+ delete credential.uuidKey;
21
+ }
22
+ credential.options = { ...options };
23
+ delete credential.options.cryptoCredentialsDetails;
24
+ return JSON.stringify(credential) + '_tls';
25
+ }
26
+ }
27
+ if ('uuidKey' in credential) {
28
+ credential = { ...credential };
29
+ delete credential.uuidKey;
30
+ }
31
+ return JSON.stringify(credential);
32
+ }
33
+ async getConnection() {
34
+ return new Promise((resolve, reject) => {
35
+ this.client.acquire((err, connection) => {
36
+ if (err) {
37
+ reject(err);
38
+ }
39
+ else {
40
+ resolve(connection);
41
+ }
42
+ });
43
+ });
44
+ }
45
+ async close() {
46
+ return new Promise((resolve, reject) => {
47
+ try {
48
+ this.client.drain();
49
+ resolve();
50
+ }
51
+ catch (err) {
52
+ reject(err);
53
+ }
54
+ });
55
+ }
56
+ isEmpty() {
57
+ return this.closed || (0, util_1.checkEmpty)(this.client.connections) && (0, util_1.checkEmpty)(this.client.waiting);
58
+ }
59
+ get closed() {
60
+ return !!this.client.drained;
61
+ }
62
+ }
63
+ module.exports = MSSQLPool;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-r/mssql",
3
- "version": "0.7.3",
3
+ "version": "0.8.1",
4
4
  "description": "MSSQL client driver for E-mc.",
5
5
  "main": "client/index.js",
6
6
  "types": "client/index.d.ts",
@@ -21,9 +21,9 @@
21
21
  "license": "MIT",
22
22
  "homepage": "https://github.com/anpham6/pi-r#readme",
23
23
  "dependencies": {
24
- "@e-mc/db": "^0.9.6",
25
- "@e-mc/types": "^0.9.6",
26
- "tedious": "^16.7.1",
24
+ "@e-mc/db": "^0.10.0",
25
+ "@e-mc/types": "^0.10.0",
26
+ "tedious": "^18.6.2",
27
27
  "tedious-connection-pool2": "^2.1.0"
28
28
  }
29
29
  }
package/types/index.d.ts CHANGED
@@ -1,5 +1,8 @@
1
+ /// <reference lib="es2022" />
2
+
1
3
  import type { DbDataSource } from '@e-mc/types/lib/squared';
2
4
 
5
+ import type { IdentifierAction } from '@e-mc/types/lib/core';
3
6
  import type { ExecuteAction, ServerAuth } from '@e-mc/types/lib/db';
4
7
 
5
8
  import type { ConnectionConfiguration, TYPES } from 'tedious';
@@ -27,4 +30,5 @@ export interface MSSQLRequestParameterValue {
27
30
  }
28
31
 
29
32
  export type MSSQLRequestParameters = Null<MSSQLRequestParameterValue[] | ObjectMap<Omit<MSSQLRequestParameterValue, "name">>>;
30
- export type MSSQLDataType = keyof typeof TYPES;
33
+ export type MSSQLDataType = keyof typeof TYPES;
34
+ export type DbPoolCredential = ConnectionConfiguration & IdentifierAction;
package/types/pool.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- /* eslint @typescript-eslint/consistent-type-imports: "off" */
2
-
3
1
  import type { Connection, ConnectionConfiguration } from 'tedious';
4
2
 
5
3
  import type * as EventEmitter from 'events';