mssql 9.2.1 → 9.3.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/README.md CHANGED
@@ -574,11 +574,50 @@ In addition to configuration object there is an option to pass config as a conne
574
574
 
575
575
  ##### Classic Connection String
576
576
 
577
+ ###### Standard configuration using tedious driver
578
+
577
579
  ```
578
580
  Server=localhost,1433;Database=database;User Id=username;Password=password;Encrypt=true
581
+ ```
582
+ ###### Standard configuration using msnodesqlv8 driver
583
+ ```
579
584
  Driver=msnodesqlv8;Server=(local)\INSTANCE;Database=database;UID=DOMAIN\username;PWD=password;Encrypt=true
580
585
  ```
581
586
 
587
+ ##### Azure Active Directory Authentication Connection String
588
+
589
+ Several types of Azure Authentication are supported:
590
+
591
+ ###### Authentication using Active Directory Integrated
592
+ ```
593
+ Server=*.database.windows.net;Database=database;Authentication=Active Directory Integrated;Client secret=clientsecret;Client Id=clientid;Tenant Id=tenantid;Encrypt=true
594
+ ```
595
+ Note: Internally, the 'Active Directory Integrated' will change its type depending on the other parameters you add to it. On the example above, it will change to azure-active-directory-service-principal-secret because we supplied a Client Id, Client secret and Tenant Id.
596
+
597
+ If you want to utilize Authentication tokens (azure-active-directory-access-token) Just remove the unnecessary additional parameters and supply only a token parameter, such as in this example:
598
+
599
+ ```
600
+ Server=*.database.windows.net;Database=database;Authentication=Active Directory Integrated;token=token;Encrypt=true
601
+ ```
602
+
603
+ Finally if you want to utilize managed identity services such as managed identity service app service you can follow this example below:
604
+ ```
605
+ Server=*.database.windows.net;Database=database;Authentication=Active Directory Integrated;msi endpoint=msiendpoint;Client Id=clientid;msi secret=msisecret;Encrypt=true
606
+ ```
607
+ or if its managed identity service virtual machines, then follow this:
608
+ ```
609
+ Server=*.database.windows.net;Database=database;Authentication=Active Directory Integrated;msi endpoint=msiendpoint;Client Id=clientid;Encrypt=true
610
+ ```
611
+
612
+ We can also utilizes Active Directory Password but unlike the previous examples, it is not part of the Active Directory Integrated Authentication.
613
+
614
+ ###### Authentication using Active Directory Password
615
+ ```
616
+ Server=*.database.windows.net;Database=database;Authentication=Active Directory Password;User Id=username;Password=password;Client Id=clientid;Tenant Id=tenantid;Encrypt=true
617
+ ```
618
+
619
+ For more reference, you can consult [here](https://tediousjs.github.io/tedious/api-connection.html#function_newConnection). Under the authentication.type parameter.
620
+
582
621
  ## Drivers
583
622
 
584
623
  ### Tedious
@@ -99,6 +99,28 @@ class ConnectionPool extends EventEmitter {
99
99
  return this._parseConnectionString(connectionString)
100
100
  }
101
101
 
102
+ static _parseAuthenticationType (type, entries) {
103
+ switch (type.toLowerCase()) {
104
+ case 'active directory integrated':
105
+ if (entries.includes('token')) {
106
+ return 'azure-active-directory-access-token'
107
+ } else if (['client id', 'client secret', 'tenant id'].every(entry => entries.includes(entry))) {
108
+ return 'azure-active-directory-service-principal-secret'
109
+ } else if (['client id', 'msi endpoint', 'msi secret'].every(entry => entries.includes(entry))) {
110
+ return 'azure-active-directory-msi-app-service'
111
+ } else if (['client id', 'msi endpoint'].every(entry => entries.includes(entry))) {
112
+ return 'azure-active-directory-msi-vm'
113
+ }
114
+ return 'azure-active-directory-default'
115
+ case 'active directory password':
116
+ return 'azure-active-directory-password'
117
+ case 'ntlm':
118
+ return 'ntlm'
119
+ default:
120
+ return 'default'
121
+ }
122
+ }
123
+
102
124
  static _parseConnectionString (connectionString) {
103
125
  const parsed = parseSqlConnectionString(connectionString, true, true)
104
126
  return Object.entries(parsed).reduce((config, [key, value]) => {
@@ -115,6 +137,9 @@ class ConnectionPool extends EventEmitter {
115
137
  case 'attachdbfilename':
116
138
  break
117
139
  case 'authentication':
140
+ Object.assign(config, {
141
+ authentication_type: this._parseAuthenticationType(value, Object.keys(parsed))
142
+ })
118
143
  break
119
144
  case 'column encryption setting':
120
145
  break
@@ -134,6 +159,16 @@ class ConnectionPool extends EventEmitter {
134
159
  break
135
160
  case 'context connection':
136
161
  break
162
+ case 'client id':
163
+ Object.assign(config, {
164
+ clientId: value
165
+ })
166
+ break
167
+ case 'client secret':
168
+ Object.assign(config, {
169
+ clientSecret: value
170
+ })
171
+ break
137
172
  case 'current language':
138
173
  Object.assign(config.options, {
139
174
  language: value
@@ -173,9 +208,11 @@ class ConnectionPool extends EventEmitter {
173
208
  port,
174
209
  server
175
210
  })
176
- Object.assign(config.options, {
177
- instanceName
178
- })
211
+ if (instanceName) {
212
+ Object.assign(config.options, {
213
+ instanceName
214
+ })
215
+ }
179
216
  break
180
217
  }
181
218
  case 'encrypt':
@@ -204,6 +241,16 @@ class ConnectionPool extends EventEmitter {
204
241
  min: value
205
242
  })
206
243
  break
244
+ case 'msi endpoint':
245
+ Object.assign(config, {
246
+ msiEndpoint: value
247
+ })
248
+ break
249
+ case 'msi secret':
250
+ Object.assign(config, {
251
+ msiSecret: value
252
+ })
253
+ break
207
254
  case 'multipleactiveresultsets':
208
255
  break
209
256
  case 'multisubnetfailover':
@@ -231,6 +278,16 @@ class ConnectionPool extends EventEmitter {
231
278
  break
232
279
  case 'replication':
233
280
  break
281
+ case 'tenant id':
282
+ Object.assign(config, {
283
+ tenantId: value
284
+ })
285
+ break
286
+ case 'token':
287
+ Object.assign(config, {
288
+ token: value
289
+ })
290
+ break
234
291
  case 'transaction binding':
235
292
  Object.assign(config.options, {
236
293
  enableImplicitTransactions: value.toLowerCase() === 'implicit unbind'
@@ -253,10 +310,16 @@ class ConnectionPool extends EventEmitter {
253
310
  domain = domainUser[1]
254
311
  user = domainUser[2]
255
312
  }
256
- Object.assign(config, {
257
- domain,
258
- user
259
- })
313
+ if (domain) {
314
+ Object.assign(config, {
315
+ domain
316
+ })
317
+ }
318
+ if (user) {
319
+ Object.assign(config, {
320
+ user
321
+ })
322
+ }
260
323
  break
261
324
  }
262
325
  case 'user instance':
@@ -8,6 +8,61 @@ const shared = require('../shared')
8
8
  const ConnectionError = require('../error/connection-error')
9
9
 
10
10
  class ConnectionPool extends BaseConnectionPool {
11
+ _config () {
12
+ const cfg = {
13
+ server: this.config.server,
14
+ options: Object.assign({
15
+ encrypt: typeof this.config.encrypt === 'boolean' ? this.config.encrypt : true,
16
+ trustServerCertificate: typeof this.config.trustServerCertificate === 'boolean' ? this.config.trustServerCertificate : false
17
+ }, this.config.options),
18
+ authentication: Object.assign({
19
+ type: this.config.domain !== undefined ? 'ntlm' : this.config.authentication_type !== undefined ? this.config.authentication_type : 'default',
20
+ options: Object.entries({
21
+ userName: this.config.user,
22
+ password: this.config.password,
23
+ domain: this.config.domain,
24
+ clientId: this.config.clientId,
25
+ clientSecret: this.config.clientSecret,
26
+ tenantId: this.config.tenantId,
27
+ token: this.config.token,
28
+ msiEndpoint: this.config.msiEndpoint,
29
+ msiSecret: this.config.msiSecret
30
+ }).reduce((acc, [key, val]) => {
31
+ if (typeof val !== 'undefined') {
32
+ return { ...acc, [key]: val }
33
+ }
34
+ return acc
35
+ }, {})
36
+ }, this.config.authentication)
37
+ }
38
+
39
+ cfg.options.database = cfg.options.database || this.config.database
40
+ cfg.options.port = cfg.options.port || this.config.port
41
+ cfg.options.connectTimeout = cfg.options.connectTimeout ?? this.config.connectionTimeout ?? this.config.timeout ?? 15000
42
+ cfg.options.requestTimeout = cfg.options.requestTimeout ?? this.config.requestTimeout ?? this.config.timeout ?? 15000
43
+ cfg.options.tdsVersion = cfg.options.tdsVersion || '7_4'
44
+ cfg.options.rowCollectionOnDone = cfg.options.rowCollectionOnDone || false
45
+ cfg.options.rowCollectionOnRequestCompletion = cfg.options.rowCollectionOnRequestCompletion || false
46
+ cfg.options.useColumnNames = cfg.options.useColumnNames || false
47
+ cfg.options.appName = cfg.options.appName || 'node-mssql'
48
+
49
+ // tedious always connect via tcp when port is specified
50
+ if (cfg.options.instanceName) delete cfg.options.port
51
+
52
+ if (isNaN(cfg.options.requestTimeout)) cfg.options.requestTimeout = 15000
53
+ if (cfg.options.requestTimeout === Infinity || cfg.options.requestTimeout < 0) cfg.options.requestTimeout = 0
54
+
55
+ if (!cfg.options.debug && this.config.debug) {
56
+ cfg.options.debug = {
57
+ packet: true,
58
+ token: true,
59
+ data: true,
60
+ payload: true
61
+ }
62
+ }
63
+ return cfg
64
+ }
65
+
11
66
  _poolCreate () {
12
67
  return new shared.Promise((resolve, reject) => {
13
68
  const resolveOnce = (v) => {
@@ -18,49 +73,9 @@ class ConnectionPool extends BaseConnectionPool {
18
73
  reject(e)
19
74
  resolve = reject = () => {}
20
75
  }
21
- const cfg = {
22
- server: this.config.server,
23
- options: Object.assign({
24
- encrypt: typeof this.config.encrypt === 'boolean' ? this.config.encrypt : true,
25
- trustServerCertificate: typeof this.config.trustServerCertificate === 'boolean' ? this.config.trustServerCertificate : false
26
- }, this.config.options),
27
- authentication: Object.assign({
28
- type: this.config.domain !== undefined ? 'ntlm' : 'default',
29
- options: {
30
- userName: this.config.user,
31
- password: this.config.password,
32
- domain: this.config.domain
33
- }
34
- }, this.config.authentication)
35
- }
36
-
37
- cfg.options.database = cfg.options.database || this.config.database
38
- cfg.options.port = cfg.options.port || this.config.port
39
- cfg.options.connectTimeout = cfg.options.connectTimeout ?? this.config.connectionTimeout ?? this.config.timeout ?? 15000
40
- cfg.options.requestTimeout = cfg.options.requestTimeout ?? this.config.requestTimeout ?? this.config.timeout ?? 15000
41
- cfg.options.tdsVersion = cfg.options.tdsVersion || '7_4'
42
- cfg.options.rowCollectionOnDone = cfg.options.rowCollectionOnDone || false
43
- cfg.options.rowCollectionOnRequestCompletion = cfg.options.rowCollectionOnRequestCompletion || false
44
- cfg.options.useColumnNames = cfg.options.useColumnNames || false
45
- cfg.options.appName = cfg.options.appName || 'node-mssql'
46
-
47
- // tedious always connect via tcp when port is specified
48
- if (cfg.options.instanceName) delete cfg.options.port
49
-
50
- if (isNaN(cfg.options.requestTimeout)) cfg.options.requestTimeout = 15000
51
- if (cfg.options.requestTimeout === Infinity || cfg.options.requestTimeout < 0) cfg.options.requestTimeout = 0
52
-
53
- if (!cfg.options.debug && this.config.debug) {
54
- cfg.options.debug = {
55
- packet: true,
56
- token: true,
57
- data: true,
58
- payload: true
59
- }
60
- }
61
76
  let tedious
62
77
  try {
63
- tedious = new tds.Connection(cfg)
78
+ tedious = new tds.Connection(this._config())
64
79
  } catch (err) {
65
80
  rejectOnce(err)
66
81
  return
package/package.json CHANGED
@@ -21,7 +21,7 @@
21
21
  "azure",
22
22
  "node-mssql"
23
23
  ],
24
- "version": "9.2.1",
24
+ "version": "9.3.1",
25
25
  "main": "index.js",
26
26
  "repository": "github:tediousjs/node-mssql",
27
27
  "license": "MIT",
@@ -31,7 +31,7 @@
31
31
  "debug": "^4.3.3",
32
32
  "rfdc": "^1.3.0",
33
33
  "tarn": "^3.0.2",
34
- "tedious": "^15.0.1"
34
+ "tedious": "^16.4.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@commitlint/cli": "^17.6.6",