@prisma/adapter-mssql 6.15.0-dev.28 → 6.15.0-dev.29
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/dist/index.d.mts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +224 -72
- package/dist/index.mjs +209 -57
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -26,11 +26,10 @@ declare class MssqlQueryable implements SqlQueryable {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export declare class PrismaMssql implements SqlDriverAdapterFactory {
|
|
29
|
-
private
|
|
30
|
-
private readonly options?;
|
|
29
|
+
#private;
|
|
31
30
|
readonly provider = "sqlserver";
|
|
32
31
|
readonly adapterName: string;
|
|
33
|
-
constructor(
|
|
32
|
+
constructor(configOrString: sql.config | string, options?: PrismaMssqlOptions);
|
|
34
33
|
connect(): Promise<PrismaMssqlAdapter>;
|
|
35
34
|
}
|
|
36
35
|
|
package/dist/index.d.ts
CHANGED
|
@@ -26,11 +26,10 @@ declare class MssqlQueryable implements SqlQueryable {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export declare class PrismaMssql implements SqlDriverAdapterFactory {
|
|
29
|
-
private
|
|
30
|
-
private readonly options?;
|
|
29
|
+
#private;
|
|
31
30
|
readonly provider = "sqlserver";
|
|
32
31
|
readonly adapterName: string;
|
|
33
|
-
constructor(
|
|
32
|
+
constructor(configOrString: sql.config | string, options?: PrismaMssqlOptions);
|
|
34
33
|
connect(): Promise<PrismaMssqlAdapter>;
|
|
35
34
|
}
|
|
36
35
|
|
package/dist/index.js
CHANGED
|
@@ -35,60 +35,201 @@ __export(index_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
37
|
// src/mssql.ts
|
|
38
|
-
var
|
|
38
|
+
var import_driver_adapter_utils3 = require("@prisma/driver-adapter-utils");
|
|
39
39
|
var import_async_mutex = require("async-mutex");
|
|
40
|
-
var
|
|
40
|
+
var import_mssql3 = __toESM(require("mssql"));
|
|
41
41
|
|
|
42
42
|
// package.json
|
|
43
43
|
var name = "@prisma/adapter-mssql";
|
|
44
44
|
|
|
45
|
-
// src/
|
|
45
|
+
// src/connection-string.ts
|
|
46
46
|
var import_driver_adapter_utils = require("@prisma/driver-adapter-utils");
|
|
47
47
|
var import_mssql = __toESM(require("mssql"));
|
|
48
|
+
function mapIsolationLevelFromString(level) {
|
|
49
|
+
const normalizedLevel = level.toUpperCase().replace(/\s+/g, "");
|
|
50
|
+
switch (normalizedLevel) {
|
|
51
|
+
case "READCOMMITTED":
|
|
52
|
+
return import_mssql.default.ISOLATION_LEVEL.READ_COMMITTED;
|
|
53
|
+
case "READUNCOMMITTED":
|
|
54
|
+
return import_mssql.default.ISOLATION_LEVEL.READ_UNCOMMITTED;
|
|
55
|
+
case "REPEATABLEREAD":
|
|
56
|
+
return import_mssql.default.ISOLATION_LEVEL.REPEATABLE_READ;
|
|
57
|
+
case "SERIALIZABLE":
|
|
58
|
+
return import_mssql.default.ISOLATION_LEVEL.SERIALIZABLE;
|
|
59
|
+
case "SNAPSHOT":
|
|
60
|
+
return import_mssql.default.ISOLATION_LEVEL.SNAPSHOT;
|
|
61
|
+
default:
|
|
62
|
+
throw new Error(`Invalid isolation level: ${level}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
var debug = (0, import_driver_adapter_utils.Debug)("prisma:driver-adapter:mssql:connection-string");
|
|
66
|
+
function extractSchemaFromConnectionString(connectionString) {
|
|
67
|
+
const withoutProtocol = connectionString.replace(/^sqlserver:\/\//, "");
|
|
68
|
+
const parts = withoutProtocol.split(";");
|
|
69
|
+
for (const part of parts) {
|
|
70
|
+
const [key, value] = part.split("=", 2);
|
|
71
|
+
if (key?.trim() === "schema") {
|
|
72
|
+
return value?.trim();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return void 0;
|
|
76
|
+
}
|
|
77
|
+
function parseConnectionString(connectionString) {
|
|
78
|
+
const withoutProtocol = connectionString.replace(/^sqlserver:\/\//, "");
|
|
79
|
+
const [hostPart, ...paramParts] = withoutProtocol.split(";");
|
|
80
|
+
const config = {
|
|
81
|
+
server: "",
|
|
82
|
+
options: {},
|
|
83
|
+
pool: {}
|
|
84
|
+
};
|
|
85
|
+
const [host, portStr] = hostPart.split(":");
|
|
86
|
+
config.server = host.trim();
|
|
87
|
+
if (portStr) {
|
|
88
|
+
const port = parseInt(portStr, 10);
|
|
89
|
+
if (isNaN(port)) {
|
|
90
|
+
throw new Error(`Invalid port number: ${portStr}`);
|
|
91
|
+
}
|
|
92
|
+
config.port = port;
|
|
93
|
+
}
|
|
94
|
+
for (const part of paramParts) {
|
|
95
|
+
const [key, value] = part.split("=", 2);
|
|
96
|
+
if (!key) continue;
|
|
97
|
+
const trimmedKey = key.trim();
|
|
98
|
+
const trimmedValue = value.trim();
|
|
99
|
+
switch (trimmedKey) {
|
|
100
|
+
case "database":
|
|
101
|
+
case "initial catalog":
|
|
102
|
+
config.database = trimmedValue;
|
|
103
|
+
break;
|
|
104
|
+
case "user":
|
|
105
|
+
case "username":
|
|
106
|
+
case "uid":
|
|
107
|
+
case "userid":
|
|
108
|
+
config.user = trimmedValue;
|
|
109
|
+
break;
|
|
110
|
+
case "password":
|
|
111
|
+
case "pwd":
|
|
112
|
+
config.password = trimmedValue;
|
|
113
|
+
break;
|
|
114
|
+
case "encrypt":
|
|
115
|
+
config.options = config.options || {};
|
|
116
|
+
config.options.encrypt = trimmedValue.toLowerCase() === "true";
|
|
117
|
+
break;
|
|
118
|
+
case "trustServerCertificate":
|
|
119
|
+
config.options = config.options || {};
|
|
120
|
+
config.options.trustServerCertificate = trimmedValue.toLowerCase() === "true";
|
|
121
|
+
break;
|
|
122
|
+
case "connectionLimit": {
|
|
123
|
+
config.pool = config.pool || {};
|
|
124
|
+
const limit = parseInt(trimmedValue, 10);
|
|
125
|
+
if (isNaN(limit)) {
|
|
126
|
+
throw new Error(`Invalid connection limit: ${trimmedValue}`);
|
|
127
|
+
}
|
|
128
|
+
config.pool.max = limit;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
case "connectTimeout":
|
|
132
|
+
case "connectionTimeout": {
|
|
133
|
+
const connectTimeout = parseInt(trimmedValue, 10);
|
|
134
|
+
if (isNaN(connectTimeout)) {
|
|
135
|
+
throw new Error(`Invalid connection timeout: ${trimmedValue}`);
|
|
136
|
+
}
|
|
137
|
+
config.connectionTimeout = connectTimeout;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case "loginTimeout": {
|
|
141
|
+
const loginTimeout = parseInt(trimmedValue, 10);
|
|
142
|
+
if (isNaN(loginTimeout)) {
|
|
143
|
+
throw new Error(`Invalid login timeout: ${trimmedValue}`);
|
|
144
|
+
}
|
|
145
|
+
config.connectionTimeout = loginTimeout;
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
case "socketTimeout": {
|
|
149
|
+
const socketTimeout = parseInt(trimmedValue, 10);
|
|
150
|
+
if (isNaN(socketTimeout)) {
|
|
151
|
+
throw new Error(`Invalid socket timeout: ${trimmedValue}`);
|
|
152
|
+
}
|
|
153
|
+
config.requestTimeout = socketTimeout;
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
case "poolTimeout": {
|
|
157
|
+
const poolTimeout = parseInt(trimmedValue, 10);
|
|
158
|
+
if (isNaN(poolTimeout)) {
|
|
159
|
+
throw new Error(`Invalid pool timeout: ${trimmedValue}`);
|
|
160
|
+
}
|
|
161
|
+
config.pool = config.pool || {};
|
|
162
|
+
config.pool.acquireTimeoutMillis = poolTimeout * 1e3;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case "applicationName":
|
|
166
|
+
case "application name":
|
|
167
|
+
config.options = config.options || {};
|
|
168
|
+
config.options.appName = trimmedValue;
|
|
169
|
+
break;
|
|
170
|
+
case "isolationLevel":
|
|
171
|
+
config.options = config.options || {};
|
|
172
|
+
config.options.isolationLevel = mapIsolationLevelFromString(trimmedValue);
|
|
173
|
+
break;
|
|
174
|
+
case "schema":
|
|
175
|
+
break;
|
|
176
|
+
default:
|
|
177
|
+
debug(`Unknown connection string parameter: ${trimmedKey}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (!config.server || config.server.trim() === "") {
|
|
181
|
+
throw new Error("Server host is required in connection string");
|
|
182
|
+
}
|
|
183
|
+
return config;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// src/conversion.ts
|
|
187
|
+
var import_driver_adapter_utils2 = require("@prisma/driver-adapter-utils");
|
|
188
|
+
var import_mssql2 = __toESM(require("mssql"));
|
|
48
189
|
function mapColumnType(col) {
|
|
49
190
|
switch (col.type) {
|
|
50
|
-
case
|
|
51
|
-
case
|
|
52
|
-
case
|
|
53
|
-
case
|
|
54
|
-
case
|
|
55
|
-
case
|
|
56
|
-
case
|
|
57
|
-
return
|
|
58
|
-
case
|
|
59
|
-
return
|
|
60
|
-
case
|
|
61
|
-
case
|
|
62
|
-
case
|
|
63
|
-
return
|
|
64
|
-
case
|
|
65
|
-
return
|
|
66
|
-
case
|
|
67
|
-
case
|
|
68
|
-
case
|
|
69
|
-
case
|
|
70
|
-
return
|
|
71
|
-
case
|
|
72
|
-
return
|
|
73
|
-
case
|
|
74
|
-
case
|
|
75
|
-
case
|
|
76
|
-
return
|
|
77
|
-
case
|
|
78
|
-
return
|
|
79
|
-
case
|
|
80
|
-
case
|
|
81
|
-
return
|
|
82
|
-
case
|
|
83
|
-
return
|
|
84
|
-
case
|
|
85
|
-
return
|
|
86
|
-
case
|
|
87
|
-
case
|
|
88
|
-
case
|
|
89
|
-
return
|
|
191
|
+
case import_mssql2.default.VarChar:
|
|
192
|
+
case import_mssql2.default.Char:
|
|
193
|
+
case import_mssql2.default.NVarChar:
|
|
194
|
+
case import_mssql2.default.NChar:
|
|
195
|
+
case import_mssql2.default.Text:
|
|
196
|
+
case import_mssql2.default.NText:
|
|
197
|
+
case import_mssql2.default.Xml:
|
|
198
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Text;
|
|
199
|
+
case import_mssql2.default.Bit:
|
|
200
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Boolean;
|
|
201
|
+
case import_mssql2.default.TinyInt:
|
|
202
|
+
case import_mssql2.default.SmallInt:
|
|
203
|
+
case import_mssql2.default.Int:
|
|
204
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Int32;
|
|
205
|
+
case import_mssql2.default.BigInt:
|
|
206
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Int64;
|
|
207
|
+
case import_mssql2.default.DateTime2:
|
|
208
|
+
case import_mssql2.default.SmallDateTime:
|
|
209
|
+
case import_mssql2.default.DateTime:
|
|
210
|
+
case import_mssql2.default.DateTimeOffset:
|
|
211
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.DateTime;
|
|
212
|
+
case import_mssql2.default.Real:
|
|
213
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Float;
|
|
214
|
+
case import_mssql2.default.Float:
|
|
215
|
+
case import_mssql2.default.Money:
|
|
216
|
+
case import_mssql2.default.SmallMoney:
|
|
217
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Double;
|
|
218
|
+
case import_mssql2.default.UniqueIdentifier:
|
|
219
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Uuid;
|
|
220
|
+
case import_mssql2.default.Decimal:
|
|
221
|
+
case import_mssql2.default.Numeric:
|
|
222
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Numeric;
|
|
223
|
+
case import_mssql2.default.Date:
|
|
224
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Date;
|
|
225
|
+
case import_mssql2.default.Time:
|
|
226
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Time;
|
|
227
|
+
case import_mssql2.default.VarBinary:
|
|
228
|
+
case import_mssql2.default.Binary:
|
|
229
|
+
case import_mssql2.default.Image:
|
|
230
|
+
return import_driver_adapter_utils2.ColumnTypeEnum.Bytes;
|
|
90
231
|
default:
|
|
91
|
-
throw new
|
|
232
|
+
throw new import_driver_adapter_utils2.DriverAdapterError({
|
|
92
233
|
kind: "UnsupportedNativeDataType",
|
|
93
234
|
type: col["udt"]?.name ?? "N/A"
|
|
94
235
|
});
|
|
@@ -97,17 +238,17 @@ function mapColumnType(col) {
|
|
|
97
238
|
function mapIsolationLevel(level) {
|
|
98
239
|
switch (level) {
|
|
99
240
|
case "READ COMMITTED":
|
|
100
|
-
return
|
|
241
|
+
return import_mssql2.default.ISOLATION_LEVEL.READ_COMMITTED;
|
|
101
242
|
case "READ UNCOMMITTED":
|
|
102
|
-
return
|
|
243
|
+
return import_mssql2.default.ISOLATION_LEVEL.READ_UNCOMMITTED;
|
|
103
244
|
case "REPEATABLE READ":
|
|
104
|
-
return
|
|
245
|
+
return import_mssql2.default.ISOLATION_LEVEL.REPEATABLE_READ;
|
|
105
246
|
case "SERIALIZABLE":
|
|
106
|
-
return
|
|
247
|
+
return import_mssql2.default.ISOLATION_LEVEL.SERIALIZABLE;
|
|
107
248
|
case "SNAPSHOT":
|
|
108
|
-
return
|
|
249
|
+
return import_mssql2.default.ISOLATION_LEVEL.SNAPSHOT;
|
|
109
250
|
default:
|
|
110
|
-
throw new
|
|
251
|
+
throw new import_driver_adapter_utils2.DriverAdapterError({
|
|
111
252
|
kind: "InvalidIsolationLevel",
|
|
112
253
|
level
|
|
113
254
|
});
|
|
@@ -154,12 +295,12 @@ function mapRow(row, columns) {
|
|
|
154
295
|
return row.map((value, i) => {
|
|
155
296
|
const type = columns?.[i]?.type;
|
|
156
297
|
if (value instanceof Date) {
|
|
157
|
-
if (type ===
|
|
298
|
+
if (type === import_mssql2.default.Time) {
|
|
158
299
|
return value.toISOString().split("T")[1].replace("Z", "");
|
|
159
300
|
}
|
|
160
301
|
return value.toISOString();
|
|
161
302
|
}
|
|
162
|
-
if (typeof value === "number" && type ===
|
|
303
|
+
if (typeof value === "number" && type === import_mssql2.default.Real) {
|
|
163
304
|
for (let digits = 7; digits <= 9; digits++) {
|
|
164
305
|
const parsed = Number.parseFloat(value.toPrecision(digits));
|
|
165
306
|
if (value === new Float32Array([parsed])[0]) {
|
|
@@ -171,10 +312,10 @@ function mapRow(row, columns) {
|
|
|
171
312
|
if (Buffer.isBuffer(value)) {
|
|
172
313
|
return Array.from(value);
|
|
173
314
|
}
|
|
174
|
-
if (typeof value === "string" && type ===
|
|
315
|
+
if (typeof value === "string" && type === import_mssql2.default.UniqueIdentifier) {
|
|
175
316
|
return value.toLowerCase();
|
|
176
317
|
}
|
|
177
|
-
if (typeof value === "boolean" && type ===
|
|
318
|
+
if (typeof value === "boolean" && type === import_mssql2.default.Bit) {
|
|
178
319
|
return value ? 1 : 0;
|
|
179
320
|
}
|
|
180
321
|
return value;
|
|
@@ -380,7 +521,7 @@ function isDriverError(error) {
|
|
|
380
521
|
}
|
|
381
522
|
|
|
382
523
|
// src/mssql.ts
|
|
383
|
-
var
|
|
524
|
+
var debug2 = (0, import_driver_adapter_utils3.Debug)("prisma:driver-adapter:mssql");
|
|
384
525
|
var MssqlQueryable = class {
|
|
385
526
|
constructor(conn) {
|
|
386
527
|
this.conn = conn;
|
|
@@ -389,7 +530,7 @@ var MssqlQueryable = class {
|
|
|
389
530
|
adapterName = name;
|
|
390
531
|
async queryRaw(query) {
|
|
391
532
|
const tag = "[js::query_raw]";
|
|
392
|
-
|
|
533
|
+
debug2(`${tag} %O`, query);
|
|
393
534
|
const { recordset, columns: columnsList } = await this.performIO(query);
|
|
394
535
|
const columns = columnsList?.[0];
|
|
395
536
|
return {
|
|
@@ -400,7 +541,7 @@ var MssqlQueryable = class {
|
|
|
400
541
|
}
|
|
401
542
|
async executeRaw(query) {
|
|
402
543
|
const tag = "[js::execute_raw]";
|
|
403
|
-
|
|
544
|
+
debug2(`${tag} %O`, query);
|
|
404
545
|
return (await this.performIO(query)).rowsAffected?.[0] ?? 0;
|
|
405
546
|
}
|
|
406
547
|
async performIO(query) {
|
|
@@ -417,8 +558,8 @@ var MssqlQueryable = class {
|
|
|
417
558
|
}
|
|
418
559
|
}
|
|
419
560
|
onError(error) {
|
|
420
|
-
|
|
421
|
-
throw new
|
|
561
|
+
debug2("Error in performIO: %O", error);
|
|
562
|
+
throw new import_driver_adapter_utils3.DriverAdapterError(convertDriverError(error));
|
|
422
563
|
}
|
|
423
564
|
};
|
|
424
565
|
var MssqlTransaction = class extends MssqlQueryable {
|
|
@@ -439,14 +580,14 @@ var MssqlTransaction = class extends MssqlQueryable {
|
|
|
439
580
|
}
|
|
440
581
|
}
|
|
441
582
|
async commit() {
|
|
442
|
-
|
|
583
|
+
debug2(`[js::commit]`);
|
|
443
584
|
await this.transaction.commit();
|
|
444
585
|
}
|
|
445
586
|
async rollback() {
|
|
446
|
-
|
|
587
|
+
debug2(`[js::rollback]`);
|
|
447
588
|
await this.transaction.rollback().catch((e) => {
|
|
448
589
|
if (e.code === "EABORT") {
|
|
449
|
-
|
|
590
|
+
debug2(`[js::rollback] Transaction already aborted`);
|
|
450
591
|
return;
|
|
451
592
|
}
|
|
452
593
|
throw e;
|
|
@@ -467,10 +608,10 @@ var PrismaMssqlAdapter = class extends MssqlQueryable {
|
|
|
467
608
|
usePhantomQuery: true
|
|
468
609
|
};
|
|
469
610
|
const tag = "[js::startTransaction]";
|
|
470
|
-
|
|
611
|
+
debug2("%s options: %O", tag, options);
|
|
471
612
|
const tx = this.pool.transaction();
|
|
472
613
|
tx.on("error", (err) => {
|
|
473
|
-
|
|
614
|
+
debug2("Error from pool connection: %O", err);
|
|
474
615
|
this.options?.onConnectionError?.(err);
|
|
475
616
|
});
|
|
476
617
|
try {
|
|
@@ -495,20 +636,31 @@ var PrismaMssqlAdapter = class extends MssqlQueryable {
|
|
|
495
636
|
}
|
|
496
637
|
};
|
|
497
638
|
var PrismaMssqlAdapterFactory = class {
|
|
498
|
-
constructor(config, options) {
|
|
499
|
-
this.config = config;
|
|
500
|
-
this.options = options;
|
|
501
|
-
}
|
|
502
639
|
provider = "sqlserver";
|
|
503
640
|
adapterName = name;
|
|
641
|
+
#config;
|
|
642
|
+
#options;
|
|
643
|
+
constructor(configOrString, options) {
|
|
644
|
+
if (typeof configOrString === "string") {
|
|
645
|
+
this.#config = parseConnectionString(configOrString);
|
|
646
|
+
const extractedSchema = extractSchemaFromConnectionString(configOrString);
|
|
647
|
+
this.#options = {
|
|
648
|
+
...options,
|
|
649
|
+
schema: options?.schema ?? extractedSchema
|
|
650
|
+
};
|
|
651
|
+
} else {
|
|
652
|
+
this.#config = configOrString;
|
|
653
|
+
this.#options = options ?? {};
|
|
654
|
+
}
|
|
655
|
+
}
|
|
504
656
|
async connect() {
|
|
505
|
-
const pool = new
|
|
657
|
+
const pool = new import_mssql3.default.ConnectionPool(this.#config);
|
|
506
658
|
pool.on("error", (err) => {
|
|
507
|
-
|
|
508
|
-
this
|
|
659
|
+
debug2("Error from pool client: %O", err);
|
|
660
|
+
this.#options?.onPoolError?.(err);
|
|
509
661
|
});
|
|
510
662
|
await pool.connect();
|
|
511
|
-
return new PrismaMssqlAdapter(pool, this
|
|
663
|
+
return new PrismaMssqlAdapter(pool, this.#options);
|
|
512
664
|
}
|
|
513
665
|
};
|
|
514
666
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/index.mjs
CHANGED
|
@@ -1,61 +1,202 @@
|
|
|
1
1
|
// src/mssql.ts
|
|
2
2
|
import {
|
|
3
|
-
Debug,
|
|
3
|
+
Debug as Debug2,
|
|
4
4
|
DriverAdapterError as DriverAdapterError2
|
|
5
5
|
} from "@prisma/driver-adapter-utils";
|
|
6
6
|
import { Mutex } from "async-mutex";
|
|
7
|
-
import
|
|
7
|
+
import sql3 from "mssql";
|
|
8
8
|
|
|
9
9
|
// package.json
|
|
10
10
|
var name = "@prisma/adapter-mssql";
|
|
11
11
|
|
|
12
|
+
// src/connection-string.ts
|
|
13
|
+
import { Debug } from "@prisma/driver-adapter-utils";
|
|
14
|
+
import sql from "mssql";
|
|
15
|
+
function mapIsolationLevelFromString(level) {
|
|
16
|
+
const normalizedLevel = level.toUpperCase().replace(/\s+/g, "");
|
|
17
|
+
switch (normalizedLevel) {
|
|
18
|
+
case "READCOMMITTED":
|
|
19
|
+
return sql.ISOLATION_LEVEL.READ_COMMITTED;
|
|
20
|
+
case "READUNCOMMITTED":
|
|
21
|
+
return sql.ISOLATION_LEVEL.READ_UNCOMMITTED;
|
|
22
|
+
case "REPEATABLEREAD":
|
|
23
|
+
return sql.ISOLATION_LEVEL.REPEATABLE_READ;
|
|
24
|
+
case "SERIALIZABLE":
|
|
25
|
+
return sql.ISOLATION_LEVEL.SERIALIZABLE;
|
|
26
|
+
case "SNAPSHOT":
|
|
27
|
+
return sql.ISOLATION_LEVEL.SNAPSHOT;
|
|
28
|
+
default:
|
|
29
|
+
throw new Error(`Invalid isolation level: ${level}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
var debug = Debug("prisma:driver-adapter:mssql:connection-string");
|
|
33
|
+
function extractSchemaFromConnectionString(connectionString) {
|
|
34
|
+
const withoutProtocol = connectionString.replace(/^sqlserver:\/\//, "");
|
|
35
|
+
const parts = withoutProtocol.split(";");
|
|
36
|
+
for (const part of parts) {
|
|
37
|
+
const [key, value] = part.split("=", 2);
|
|
38
|
+
if (key?.trim() === "schema") {
|
|
39
|
+
return value?.trim();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return void 0;
|
|
43
|
+
}
|
|
44
|
+
function parseConnectionString(connectionString) {
|
|
45
|
+
const withoutProtocol = connectionString.replace(/^sqlserver:\/\//, "");
|
|
46
|
+
const [hostPart, ...paramParts] = withoutProtocol.split(";");
|
|
47
|
+
const config = {
|
|
48
|
+
server: "",
|
|
49
|
+
options: {},
|
|
50
|
+
pool: {}
|
|
51
|
+
};
|
|
52
|
+
const [host, portStr] = hostPart.split(":");
|
|
53
|
+
config.server = host.trim();
|
|
54
|
+
if (portStr) {
|
|
55
|
+
const port = parseInt(portStr, 10);
|
|
56
|
+
if (isNaN(port)) {
|
|
57
|
+
throw new Error(`Invalid port number: ${portStr}`);
|
|
58
|
+
}
|
|
59
|
+
config.port = port;
|
|
60
|
+
}
|
|
61
|
+
for (const part of paramParts) {
|
|
62
|
+
const [key, value] = part.split("=", 2);
|
|
63
|
+
if (!key) continue;
|
|
64
|
+
const trimmedKey = key.trim();
|
|
65
|
+
const trimmedValue = value.trim();
|
|
66
|
+
switch (trimmedKey) {
|
|
67
|
+
case "database":
|
|
68
|
+
case "initial catalog":
|
|
69
|
+
config.database = trimmedValue;
|
|
70
|
+
break;
|
|
71
|
+
case "user":
|
|
72
|
+
case "username":
|
|
73
|
+
case "uid":
|
|
74
|
+
case "userid":
|
|
75
|
+
config.user = trimmedValue;
|
|
76
|
+
break;
|
|
77
|
+
case "password":
|
|
78
|
+
case "pwd":
|
|
79
|
+
config.password = trimmedValue;
|
|
80
|
+
break;
|
|
81
|
+
case "encrypt":
|
|
82
|
+
config.options = config.options || {};
|
|
83
|
+
config.options.encrypt = trimmedValue.toLowerCase() === "true";
|
|
84
|
+
break;
|
|
85
|
+
case "trustServerCertificate":
|
|
86
|
+
config.options = config.options || {};
|
|
87
|
+
config.options.trustServerCertificate = trimmedValue.toLowerCase() === "true";
|
|
88
|
+
break;
|
|
89
|
+
case "connectionLimit": {
|
|
90
|
+
config.pool = config.pool || {};
|
|
91
|
+
const limit = parseInt(trimmedValue, 10);
|
|
92
|
+
if (isNaN(limit)) {
|
|
93
|
+
throw new Error(`Invalid connection limit: ${trimmedValue}`);
|
|
94
|
+
}
|
|
95
|
+
config.pool.max = limit;
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case "connectTimeout":
|
|
99
|
+
case "connectionTimeout": {
|
|
100
|
+
const connectTimeout = parseInt(trimmedValue, 10);
|
|
101
|
+
if (isNaN(connectTimeout)) {
|
|
102
|
+
throw new Error(`Invalid connection timeout: ${trimmedValue}`);
|
|
103
|
+
}
|
|
104
|
+
config.connectionTimeout = connectTimeout;
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
case "loginTimeout": {
|
|
108
|
+
const loginTimeout = parseInt(trimmedValue, 10);
|
|
109
|
+
if (isNaN(loginTimeout)) {
|
|
110
|
+
throw new Error(`Invalid login timeout: ${trimmedValue}`);
|
|
111
|
+
}
|
|
112
|
+
config.connectionTimeout = loginTimeout;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
case "socketTimeout": {
|
|
116
|
+
const socketTimeout = parseInt(trimmedValue, 10);
|
|
117
|
+
if (isNaN(socketTimeout)) {
|
|
118
|
+
throw new Error(`Invalid socket timeout: ${trimmedValue}`);
|
|
119
|
+
}
|
|
120
|
+
config.requestTimeout = socketTimeout;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
case "poolTimeout": {
|
|
124
|
+
const poolTimeout = parseInt(trimmedValue, 10);
|
|
125
|
+
if (isNaN(poolTimeout)) {
|
|
126
|
+
throw new Error(`Invalid pool timeout: ${trimmedValue}`);
|
|
127
|
+
}
|
|
128
|
+
config.pool = config.pool || {};
|
|
129
|
+
config.pool.acquireTimeoutMillis = poolTimeout * 1e3;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
case "applicationName":
|
|
133
|
+
case "application name":
|
|
134
|
+
config.options = config.options || {};
|
|
135
|
+
config.options.appName = trimmedValue;
|
|
136
|
+
break;
|
|
137
|
+
case "isolationLevel":
|
|
138
|
+
config.options = config.options || {};
|
|
139
|
+
config.options.isolationLevel = mapIsolationLevelFromString(trimmedValue);
|
|
140
|
+
break;
|
|
141
|
+
case "schema":
|
|
142
|
+
break;
|
|
143
|
+
default:
|
|
144
|
+
debug(`Unknown connection string parameter: ${trimmedKey}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (!config.server || config.server.trim() === "") {
|
|
148
|
+
throw new Error("Server host is required in connection string");
|
|
149
|
+
}
|
|
150
|
+
return config;
|
|
151
|
+
}
|
|
152
|
+
|
|
12
153
|
// src/conversion.ts
|
|
13
154
|
import {
|
|
14
155
|
ColumnTypeEnum,
|
|
15
156
|
DriverAdapterError
|
|
16
157
|
} from "@prisma/driver-adapter-utils";
|
|
17
|
-
import
|
|
158
|
+
import sql2 from "mssql";
|
|
18
159
|
function mapColumnType(col) {
|
|
19
160
|
switch (col.type) {
|
|
20
|
-
case
|
|
21
|
-
case
|
|
22
|
-
case
|
|
23
|
-
case
|
|
24
|
-
case
|
|
25
|
-
case
|
|
26
|
-
case
|
|
161
|
+
case sql2.VarChar:
|
|
162
|
+
case sql2.Char:
|
|
163
|
+
case sql2.NVarChar:
|
|
164
|
+
case sql2.NChar:
|
|
165
|
+
case sql2.Text:
|
|
166
|
+
case sql2.NText:
|
|
167
|
+
case sql2.Xml:
|
|
27
168
|
return ColumnTypeEnum.Text;
|
|
28
|
-
case
|
|
169
|
+
case sql2.Bit:
|
|
29
170
|
return ColumnTypeEnum.Boolean;
|
|
30
|
-
case
|
|
31
|
-
case
|
|
32
|
-
case
|
|
171
|
+
case sql2.TinyInt:
|
|
172
|
+
case sql2.SmallInt:
|
|
173
|
+
case sql2.Int:
|
|
33
174
|
return ColumnTypeEnum.Int32;
|
|
34
|
-
case
|
|
175
|
+
case sql2.BigInt:
|
|
35
176
|
return ColumnTypeEnum.Int64;
|
|
36
|
-
case
|
|
37
|
-
case
|
|
38
|
-
case
|
|
39
|
-
case
|
|
177
|
+
case sql2.DateTime2:
|
|
178
|
+
case sql2.SmallDateTime:
|
|
179
|
+
case sql2.DateTime:
|
|
180
|
+
case sql2.DateTimeOffset:
|
|
40
181
|
return ColumnTypeEnum.DateTime;
|
|
41
|
-
case
|
|
182
|
+
case sql2.Real:
|
|
42
183
|
return ColumnTypeEnum.Float;
|
|
43
|
-
case
|
|
44
|
-
case
|
|
45
|
-
case
|
|
184
|
+
case sql2.Float:
|
|
185
|
+
case sql2.Money:
|
|
186
|
+
case sql2.SmallMoney:
|
|
46
187
|
return ColumnTypeEnum.Double;
|
|
47
|
-
case
|
|
188
|
+
case sql2.UniqueIdentifier:
|
|
48
189
|
return ColumnTypeEnum.Uuid;
|
|
49
|
-
case
|
|
50
|
-
case
|
|
190
|
+
case sql2.Decimal:
|
|
191
|
+
case sql2.Numeric:
|
|
51
192
|
return ColumnTypeEnum.Numeric;
|
|
52
|
-
case
|
|
193
|
+
case sql2.Date:
|
|
53
194
|
return ColumnTypeEnum.Date;
|
|
54
|
-
case
|
|
195
|
+
case sql2.Time:
|
|
55
196
|
return ColumnTypeEnum.Time;
|
|
56
|
-
case
|
|
57
|
-
case
|
|
58
|
-
case
|
|
197
|
+
case sql2.VarBinary:
|
|
198
|
+
case sql2.Binary:
|
|
199
|
+
case sql2.Image:
|
|
59
200
|
return ColumnTypeEnum.Bytes;
|
|
60
201
|
default:
|
|
61
202
|
throw new DriverAdapterError({
|
|
@@ -67,15 +208,15 @@ function mapColumnType(col) {
|
|
|
67
208
|
function mapIsolationLevel(level) {
|
|
68
209
|
switch (level) {
|
|
69
210
|
case "READ COMMITTED":
|
|
70
|
-
return
|
|
211
|
+
return sql2.ISOLATION_LEVEL.READ_COMMITTED;
|
|
71
212
|
case "READ UNCOMMITTED":
|
|
72
|
-
return
|
|
213
|
+
return sql2.ISOLATION_LEVEL.READ_UNCOMMITTED;
|
|
73
214
|
case "REPEATABLE READ":
|
|
74
|
-
return
|
|
215
|
+
return sql2.ISOLATION_LEVEL.REPEATABLE_READ;
|
|
75
216
|
case "SERIALIZABLE":
|
|
76
|
-
return
|
|
217
|
+
return sql2.ISOLATION_LEVEL.SERIALIZABLE;
|
|
77
218
|
case "SNAPSHOT":
|
|
78
|
-
return
|
|
219
|
+
return sql2.ISOLATION_LEVEL.SNAPSHOT;
|
|
79
220
|
default:
|
|
80
221
|
throw new DriverAdapterError({
|
|
81
222
|
kind: "InvalidIsolationLevel",
|
|
@@ -124,12 +265,12 @@ function mapRow(row, columns) {
|
|
|
124
265
|
return row.map((value, i) => {
|
|
125
266
|
const type = columns?.[i]?.type;
|
|
126
267
|
if (value instanceof Date) {
|
|
127
|
-
if (type ===
|
|
268
|
+
if (type === sql2.Time) {
|
|
128
269
|
return value.toISOString().split("T")[1].replace("Z", "");
|
|
129
270
|
}
|
|
130
271
|
return value.toISOString();
|
|
131
272
|
}
|
|
132
|
-
if (typeof value === "number" && type ===
|
|
273
|
+
if (typeof value === "number" && type === sql2.Real) {
|
|
133
274
|
for (let digits = 7; digits <= 9; digits++) {
|
|
134
275
|
const parsed = Number.parseFloat(value.toPrecision(digits));
|
|
135
276
|
if (value === new Float32Array([parsed])[0]) {
|
|
@@ -141,10 +282,10 @@ function mapRow(row, columns) {
|
|
|
141
282
|
if (Buffer.isBuffer(value)) {
|
|
142
283
|
return Array.from(value);
|
|
143
284
|
}
|
|
144
|
-
if (typeof value === "string" && type ===
|
|
285
|
+
if (typeof value === "string" && type === sql2.UniqueIdentifier) {
|
|
145
286
|
return value.toLowerCase();
|
|
146
287
|
}
|
|
147
|
-
if (typeof value === "boolean" && type ===
|
|
288
|
+
if (typeof value === "boolean" && type === sql2.Bit) {
|
|
148
289
|
return value ? 1 : 0;
|
|
149
290
|
}
|
|
150
291
|
return value;
|
|
@@ -350,7 +491,7 @@ function isDriverError(error) {
|
|
|
350
491
|
}
|
|
351
492
|
|
|
352
493
|
// src/mssql.ts
|
|
353
|
-
var
|
|
494
|
+
var debug2 = Debug2("prisma:driver-adapter:mssql");
|
|
354
495
|
var MssqlQueryable = class {
|
|
355
496
|
constructor(conn) {
|
|
356
497
|
this.conn = conn;
|
|
@@ -359,7 +500,7 @@ var MssqlQueryable = class {
|
|
|
359
500
|
adapterName = name;
|
|
360
501
|
async queryRaw(query) {
|
|
361
502
|
const tag = "[js::query_raw]";
|
|
362
|
-
|
|
503
|
+
debug2(`${tag} %O`, query);
|
|
363
504
|
const { recordset, columns: columnsList } = await this.performIO(query);
|
|
364
505
|
const columns = columnsList?.[0];
|
|
365
506
|
return {
|
|
@@ -370,7 +511,7 @@ var MssqlQueryable = class {
|
|
|
370
511
|
}
|
|
371
512
|
async executeRaw(query) {
|
|
372
513
|
const tag = "[js::execute_raw]";
|
|
373
|
-
|
|
514
|
+
debug2(`${tag} %O`, query);
|
|
374
515
|
return (await this.performIO(query)).rowsAffected?.[0] ?? 0;
|
|
375
516
|
}
|
|
376
517
|
async performIO(query) {
|
|
@@ -387,7 +528,7 @@ var MssqlQueryable = class {
|
|
|
387
528
|
}
|
|
388
529
|
}
|
|
389
530
|
onError(error) {
|
|
390
|
-
|
|
531
|
+
debug2("Error in performIO: %O", error);
|
|
391
532
|
throw new DriverAdapterError2(convertDriverError(error));
|
|
392
533
|
}
|
|
393
534
|
};
|
|
@@ -409,14 +550,14 @@ var MssqlTransaction = class extends MssqlQueryable {
|
|
|
409
550
|
}
|
|
410
551
|
}
|
|
411
552
|
async commit() {
|
|
412
|
-
|
|
553
|
+
debug2(`[js::commit]`);
|
|
413
554
|
await this.transaction.commit();
|
|
414
555
|
}
|
|
415
556
|
async rollback() {
|
|
416
|
-
|
|
557
|
+
debug2(`[js::rollback]`);
|
|
417
558
|
await this.transaction.rollback().catch((e) => {
|
|
418
559
|
if (e.code === "EABORT") {
|
|
419
|
-
|
|
560
|
+
debug2(`[js::rollback] Transaction already aborted`);
|
|
420
561
|
return;
|
|
421
562
|
}
|
|
422
563
|
throw e;
|
|
@@ -437,10 +578,10 @@ var PrismaMssqlAdapter = class extends MssqlQueryable {
|
|
|
437
578
|
usePhantomQuery: true
|
|
438
579
|
};
|
|
439
580
|
const tag = "[js::startTransaction]";
|
|
440
|
-
|
|
581
|
+
debug2("%s options: %O", tag, options);
|
|
441
582
|
const tx = this.pool.transaction();
|
|
442
583
|
tx.on("error", (err) => {
|
|
443
|
-
|
|
584
|
+
debug2("Error from pool connection: %O", err);
|
|
444
585
|
this.options?.onConnectionError?.(err);
|
|
445
586
|
});
|
|
446
587
|
try {
|
|
@@ -465,20 +606,31 @@ var PrismaMssqlAdapter = class extends MssqlQueryable {
|
|
|
465
606
|
}
|
|
466
607
|
};
|
|
467
608
|
var PrismaMssqlAdapterFactory = class {
|
|
468
|
-
constructor(config, options) {
|
|
469
|
-
this.config = config;
|
|
470
|
-
this.options = options;
|
|
471
|
-
}
|
|
472
609
|
provider = "sqlserver";
|
|
473
610
|
adapterName = name;
|
|
611
|
+
#config;
|
|
612
|
+
#options;
|
|
613
|
+
constructor(configOrString, options) {
|
|
614
|
+
if (typeof configOrString === "string") {
|
|
615
|
+
this.#config = parseConnectionString(configOrString);
|
|
616
|
+
const extractedSchema = extractSchemaFromConnectionString(configOrString);
|
|
617
|
+
this.#options = {
|
|
618
|
+
...options,
|
|
619
|
+
schema: options?.schema ?? extractedSchema
|
|
620
|
+
};
|
|
621
|
+
} else {
|
|
622
|
+
this.#config = configOrString;
|
|
623
|
+
this.#options = options ?? {};
|
|
624
|
+
}
|
|
625
|
+
}
|
|
474
626
|
async connect() {
|
|
475
|
-
const pool = new
|
|
627
|
+
const pool = new sql3.ConnectionPool(this.#config);
|
|
476
628
|
pool.on("error", (err) => {
|
|
477
|
-
|
|
478
|
-
this
|
|
629
|
+
debug2("Error from pool client: %O", err);
|
|
630
|
+
this.#options?.onPoolError?.(err);
|
|
479
631
|
});
|
|
480
632
|
await pool.connect();
|
|
481
|
-
return new PrismaMssqlAdapter(pool, this
|
|
633
|
+
return new PrismaMssqlAdapter(pool, this.#options);
|
|
482
634
|
}
|
|
483
635
|
};
|
|
484
636
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/adapter-mssql",
|
|
3
|
-
"version": "6.15.0-dev.
|
|
3
|
+
"version": "6.15.0-dev.29",
|
|
4
4
|
"description": "Prisma's driver adapter for \"mssql\"",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"mssql": "^11.0.1",
|
|
35
35
|
"async-mutex": "0.5.0",
|
|
36
|
-
"@prisma/driver-adapter-utils": "6.15.0-dev.
|
|
36
|
+
"@prisma/driver-adapter-utils": "6.15.0-dev.29"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/mssql": "9.1.7",
|