@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 +86 -87
- package/client/pool.d.ts +9 -0
- package/client/pool.js +63 -0
- package/package.json +4 -4
- package/types/index.d.ts +5 -1
- package/types/pool.d.ts +0 -2
package/client/index.js
CHANGED
|
@@ -1,42 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
exports.DB_SOURCE_TYPE = exports.DB_SOURCE_CLIENT =
|
|
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
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
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 (
|
|
179
|
-
|
|
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.
|
|
182
|
-
errors.push('authentication.options.
|
|
176
|
+
if ((flags & 4) && !(0, types_1.isString)(authOptions.clientId)) {
|
|
177
|
+
errors.push('authentication.options.clientId');
|
|
183
178
|
}
|
|
184
|
-
if (
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
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'
|
|
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
|
-
|
|
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
|
-
|
|
520
|
-
|
|
520
|
+
parallel,
|
|
521
|
+
disconnect() {
|
|
522
|
+
for (const item of clients) {
|
|
521
523
|
item.close();
|
|
522
|
-
}
|
|
523
|
-
|
|
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;
|
package/client/pool.d.ts
ADDED
|
@@ -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.
|
|
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.
|
|
25
|
-
"@e-mc/types": "^0.
|
|
26
|
-
"tedious": "^
|
|
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;
|