@prisma/client-engine-runtime 6.4.0-dev.48 → 6.4.0-dev.50

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.mjs ADDED
@@ -0,0 +1,652 @@
1
+ var __typeError = (msg) => {
2
+ throw TypeError(msg);
3
+ };
4
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
5
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
6
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
7
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
8
+ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
9
+
10
+ // src/QueryPlan.ts
11
+ function isPrismaValuePlaceholder(value) {
12
+ return typeof value === "object" && value !== null && value["prisma__type"] === "param";
13
+ }
14
+
15
+ // src/interpreter/renderQueryTemplate.ts
16
+ var BEGIN_REPEAT = "/* prisma-comma-repeatable-start */";
17
+ var END_REPEAT = "/* prisma-comma-repeatable-end */";
18
+ function renderQueryTemplate({
19
+ query,
20
+ params
21
+ }) {
22
+ if (!query.includes(BEGIN_REPEAT)) {
23
+ return { query, params };
24
+ }
25
+ const flattenedParams = [];
26
+ let lastParamId = 1;
27
+ let result = "";
28
+ let templatePos = 0;
29
+ let state = 0 /* Normal */;
30
+ let stateBeforeQuote = 0 /* Normal */;
31
+ while (templatePos < query.length) {
32
+ const nextChar = query[templatePos];
33
+ if (state === 1 /* Quoted */ && nextChar !== '"') {
34
+ result += nextChar;
35
+ templatePos++;
36
+ continue;
37
+ }
38
+ if (nextChar === '"') {
39
+ if (state === 1 /* Quoted */) {
40
+ state = stateBeforeQuote;
41
+ } else {
42
+ stateBeforeQuote = state;
43
+ state = 1 /* Quoted */;
44
+ }
45
+ result += nextChar;
46
+ templatePos++;
47
+ continue;
48
+ }
49
+ if (query.slice(templatePos, templatePos + BEGIN_REPEAT.length) === BEGIN_REPEAT) {
50
+ if (state === 2 /* Repeating */) {
51
+ throw new Error("Nested repetition is not allowed");
52
+ }
53
+ state = 2 /* Repeating */;
54
+ templatePos += BEGIN_REPEAT.length;
55
+ result += "(";
56
+ continue;
57
+ }
58
+ if (query.slice(templatePos, templatePos + END_REPEAT.length) === END_REPEAT) {
59
+ if (state === 0 /* Normal */) {
60
+ throw new Error("Unmatched repetition end");
61
+ }
62
+ state = 0 /* Normal */;
63
+ templatePos += END_REPEAT.length;
64
+ result += ")";
65
+ continue;
66
+ }
67
+ if (nextChar === "$") {
68
+ const paramMatch = query.slice(templatePos + 1).match(/^\d+/);
69
+ if (!paramMatch) {
70
+ result += "$";
71
+ templatePos++;
72
+ continue;
73
+ }
74
+ templatePos += paramMatch[0].length + 1;
75
+ const originalParamIdx = parseInt(paramMatch[0]);
76
+ const paramValue = params[originalParamIdx - 1];
77
+ switch (state) {
78
+ case 0 /* Normal */: {
79
+ flattenedParams.push(paramValue);
80
+ result += `$${lastParamId++}`;
81
+ break;
82
+ }
83
+ case 2 /* Repeating */: {
84
+ const paramArray = Array.isArray(paramValue) ? paramValue : [paramValue];
85
+ if (paramArray.length === 0) {
86
+ result += "NULL";
87
+ break;
88
+ }
89
+ paramArray.forEach((value, idx) => {
90
+ flattenedParams.push(value);
91
+ result += `$${lastParamId++}`;
92
+ if (idx !== paramArray.length - 1) {
93
+ result += ", ";
94
+ }
95
+ });
96
+ break;
97
+ }
98
+ default: {
99
+ throw new Error(`Unexpected state: ${state}`);
100
+ }
101
+ }
102
+ continue;
103
+ }
104
+ result += nextChar;
105
+ templatePos++;
106
+ }
107
+ return {
108
+ query: result,
109
+ params: flattenedParams
110
+ };
111
+ }
112
+
113
+ // src/interpreter/renderQuery.ts
114
+ function renderQuery({ query, params }, scope) {
115
+ const substitutedParams = params.map((param) => {
116
+ if (!isPrismaValuePlaceholder(param)) {
117
+ return param;
118
+ }
119
+ const value = scope[param.prisma__value.name];
120
+ if (value === void 0) {
121
+ throw new Error(`Missing value for query variable ${param.prisma__value.name}`);
122
+ }
123
+ return value;
124
+ });
125
+ const { query: renderedQuery, params: expandedParams } = renderQueryTemplate({ query, params: substitutedParams });
126
+ const argTypes = expandedParams.map((param) => toArgType(param));
127
+ return {
128
+ sql: renderedQuery,
129
+ args: expandedParams,
130
+ argTypes
131
+ };
132
+ }
133
+ function toArgType(value) {
134
+ if (value === null) {
135
+ return "Int32";
136
+ }
137
+ if (typeof value === "string") {
138
+ return "Text";
139
+ }
140
+ if (typeof value === "number") {
141
+ return "Numeric";
142
+ }
143
+ if (typeof value === "boolean") {
144
+ return "Boolean";
145
+ }
146
+ if (Array.isArray(value)) {
147
+ return "Array";
148
+ }
149
+ if (isPrismaValuePlaceholder(value)) {
150
+ return placeholderTypeToArgType(value.prisma__value.type);
151
+ }
152
+ return "Json";
153
+ }
154
+ function placeholderTypeToArgType(type) {
155
+ const typeMap = {
156
+ Any: "Json",
157
+ String: "Text",
158
+ Int: "Int32",
159
+ BigInt: "Int64",
160
+ Float: "Double",
161
+ Boolean: "Boolean",
162
+ Decimal: "Numeric",
163
+ Date: "DateTime",
164
+ Object: "Json",
165
+ Bytes: "Bytes",
166
+ Array: "Array"
167
+ };
168
+ const mappedType = typeMap[type];
169
+ if (!mappedType) {
170
+ throw new Error(`Unknown placeholder type: ${type}`);
171
+ }
172
+ return mappedType;
173
+ }
174
+
175
+ // src/interpreter/serialize.ts
176
+ function serialize(resultSet) {
177
+ return resultSet.rows.map(
178
+ (row) => row.reduce((acc, value, index) => {
179
+ const splitByDot = resultSet.columnNames[index].split(".");
180
+ let nested = acc;
181
+ for (let i = 0; i < splitByDot.length; i++) {
182
+ const key = splitByDot[i];
183
+ if (i === splitByDot.length - 1) {
184
+ nested[key] = value;
185
+ } else {
186
+ if (nested[key] === void 0) {
187
+ nested[key] = {};
188
+ }
189
+ nested = nested[key];
190
+ }
191
+ }
192
+ return acc;
193
+ }, {})
194
+ );
195
+ }
196
+
197
+ // src/interpreter/QueryInterpreter.ts
198
+ var _queryable, _placeholderValues, _onQuery, _QueryInterpreter_instances, withQueryEvent_fn;
199
+ var QueryInterpreter = class {
200
+ constructor({ queryable, placeholderValues, onQuery }) {
201
+ __privateAdd(this, _QueryInterpreter_instances);
202
+ __privateAdd(this, _queryable);
203
+ __privateAdd(this, _placeholderValues);
204
+ __privateAdd(this, _onQuery);
205
+ __privateSet(this, _queryable, queryable);
206
+ __privateSet(this, _placeholderValues, placeholderValues);
207
+ __privateSet(this, _onQuery, onQuery);
208
+ }
209
+ async run(queryPlan) {
210
+ return this.interpretNode(queryPlan, __privateGet(this, _placeholderValues));
211
+ }
212
+ async interpretNode(node, scope) {
213
+ switch (node.type) {
214
+ case "seq": {
215
+ const results = await Promise.all(node.args.map((arg) => this.interpretNode(arg, scope)));
216
+ return results[results.length - 1];
217
+ }
218
+ case "get": {
219
+ return scope[node.args.name];
220
+ }
221
+ case "let": {
222
+ const nestedScope = Object.create(scope);
223
+ await Promise.all(
224
+ node.args.bindings.map(async (binding) => {
225
+ nestedScope[binding.name] = await this.interpretNode(binding.expr, scope);
226
+ })
227
+ );
228
+ return this.interpretNode(node.args.expr, nestedScope);
229
+ }
230
+ case "getFirstNonEmpty": {
231
+ for (const name of node.args.names) {
232
+ const value = scope[name];
233
+ if (!isEmpty(value)) {
234
+ return value;
235
+ }
236
+ }
237
+ return [];
238
+ }
239
+ case "concat": {
240
+ const parts = await Promise.all(node.args.map((arg) => this.interpretNode(arg, scope)));
241
+ return parts.reduce((acc, part) => acc.concat(asList(part)), []);
242
+ }
243
+ case "sum": {
244
+ const parts = await Promise.all(node.args.map((arg) => this.interpretNode(arg, scope)));
245
+ return parts.reduce((acc, part) => asNumber(acc) + asNumber(part));
246
+ }
247
+ case "execute": {
248
+ const query = renderQuery(node.args, scope);
249
+ return __privateMethod(this, _QueryInterpreter_instances, withQueryEvent_fn).call(this, query, async () => {
250
+ const result = await __privateGet(this, _queryable).executeRaw(query);
251
+ if (result.ok) {
252
+ return result.value;
253
+ } else {
254
+ throw result.error;
255
+ }
256
+ });
257
+ }
258
+ case "query": {
259
+ const query = renderQuery(node.args, scope);
260
+ return __privateMethod(this, _QueryInterpreter_instances, withQueryEvent_fn).call(this, query, async () => {
261
+ const result = await __privateGet(this, _queryable).queryRaw(query);
262
+ if (result.ok) {
263
+ return serialize(result.value);
264
+ } else {
265
+ throw result.error;
266
+ }
267
+ });
268
+ }
269
+ case "reverse": {
270
+ const value = await this.interpretNode(node.args, scope);
271
+ return Array.isArray(value) ? value.reverse() : value;
272
+ }
273
+ case "unique": {
274
+ const value = await this.interpretNode(node.args, scope);
275
+ if (!Array.isArray(value)) {
276
+ return value;
277
+ }
278
+ if (value.length > 1) {
279
+ throw new Error(`Expected zero or one element, got ${value.length}`);
280
+ }
281
+ return value[0] ?? null;
282
+ }
283
+ case "required": {
284
+ const value = await this.interpretNode(node.args, scope);
285
+ if (isEmpty(value)) {
286
+ throw new Error("Required value is empty");
287
+ }
288
+ return value;
289
+ }
290
+ case "mapField": {
291
+ const value = await this.interpretNode(node.args.records, scope);
292
+ return mapField(value, node.args.field);
293
+ }
294
+ case "join": {
295
+ const parent = await this.interpretNode(node.args.parent, scope);
296
+ const children = await Promise.all(
297
+ node.args.children.map(async (joinExpr) => ({
298
+ joinExpr,
299
+ childRecords: await this.interpretNode(joinExpr.child, scope)
300
+ }))
301
+ );
302
+ if (Array.isArray(parent)) {
303
+ for (const record of parent) {
304
+ attachChildrenToParent(asRecord(record), children);
305
+ }
306
+ return parent;
307
+ }
308
+ return attachChildrenToParent(asRecord(parent), children);
309
+ }
310
+ default: {
311
+ node;
312
+ throw new Error(`Unexpected node type: ${node.type}`);
313
+ }
314
+ }
315
+ }
316
+ };
317
+ _queryable = new WeakMap();
318
+ _placeholderValues = new WeakMap();
319
+ _onQuery = new WeakMap();
320
+ _QueryInterpreter_instances = new WeakSet();
321
+ withQueryEvent_fn = async function(query, execute) {
322
+ var _a;
323
+ const timestamp = /* @__PURE__ */ new Date();
324
+ const startInstant = performance.now();
325
+ const result = await execute();
326
+ const endInstant = performance.now();
327
+ (_a = __privateGet(this, _onQuery)) == null ? void 0 : _a.call(this, {
328
+ timestamp,
329
+ duration: endInstant - startInstant,
330
+ query: query.sql,
331
+ params: query.args
332
+ });
333
+ return result;
334
+ };
335
+ function isEmpty(value) {
336
+ if (Array.isArray(value)) {
337
+ return value.length === 0;
338
+ }
339
+ return value == null;
340
+ }
341
+ function asList(value) {
342
+ return Array.isArray(value) ? value : [value];
343
+ }
344
+ function asNumber(value) {
345
+ if (typeof value === "number") {
346
+ return value;
347
+ }
348
+ if (typeof value === "string") {
349
+ return Number(value);
350
+ }
351
+ throw new Error(`Expected number, got ${typeof value}`);
352
+ }
353
+ function asRecord(value) {
354
+ if (typeof value === "object" && value !== null) {
355
+ return value;
356
+ }
357
+ throw new Error(`Expected object, got ${typeof value}`);
358
+ }
359
+ function mapField(value, field) {
360
+ if (Array.isArray(value)) {
361
+ return value.map((element) => mapField(element, field));
362
+ }
363
+ if (typeof value === "object" && value !== null) {
364
+ return value[field] ?? null;
365
+ }
366
+ return value;
367
+ }
368
+ function attachChildrenToParent(parentRecord, children) {
369
+ for (const { joinExpr, childRecords } of children) {
370
+ parentRecord[joinExpr.parentField] = filterChildRecords(childRecords, parentRecord, joinExpr);
371
+ }
372
+ return parentRecord;
373
+ }
374
+ function filterChildRecords(records, parentRecord, joinExpr) {
375
+ if (Array.isArray(records)) {
376
+ return records.filter((record) => childRecordMatchesParent(asRecord(record), parentRecord, joinExpr));
377
+ } else {
378
+ const record = asRecord(records);
379
+ return childRecordMatchesParent(record, parentRecord, joinExpr) ? record : null;
380
+ }
381
+ }
382
+ function childRecordMatchesParent(childRecord, parentRecord, joinExpr) {
383
+ for (const [parentField, childField] of joinExpr.on) {
384
+ if (parentRecord[parentField] !== childRecord[childField]) {
385
+ return false;
386
+ }
387
+ }
388
+ return true;
389
+ }
390
+
391
+ // src/transactionManager/Transaction.ts
392
+ var IsolationLevel = /* @__PURE__ */ ((IsolationLevel2) => {
393
+ IsolationLevel2["ReadUncommitted"] = "ReadUncommitted";
394
+ IsolationLevel2["ReadCommitted"] = "ReadCommitted";
395
+ IsolationLevel2["RepeatableRead"] = "RepeatableRead";
396
+ IsolationLevel2["Snapshot"] = "Snapshot";
397
+ IsolationLevel2["Serializable"] = "Serializable";
398
+ return IsolationLevel2;
399
+ })(IsolationLevel || {});
400
+
401
+ // src/transactionManager/TransactionManager.ts
402
+ import crypto from "node:crypto";
403
+ import Debug from "@prisma/debug";
404
+
405
+ // src/utils.ts
406
+ function assertNever(_, message) {
407
+ throw new Error(message);
408
+ }
409
+
410
+ // src/transactionManager/TransactionManagerErrors.ts
411
+ var TransactionManagerError = class extends Error {
412
+ constructor(message, meta) {
413
+ super("Transaction API error: " + message);
414
+ this.meta = meta;
415
+ this.code = "P2028";
416
+ }
417
+ };
418
+ var TransactionDriverAdapterError = class extends TransactionManagerError {
419
+ constructor(message, errorParams) {
420
+ super(`Error from Driver Adapter: ${message}`, { ...errorParams.driverAdapterError });
421
+ }
422
+ };
423
+ var TransactionNotFoundError = class extends TransactionManagerError {
424
+ constructor() {
425
+ super(
426
+ "Transaction not found. Transaction ID is invalid, refers to an old closed transaction Prisma doesn't have information about anymore, or was obtained before disconnecting."
427
+ );
428
+ }
429
+ };
430
+ var TransactionClosedError = class extends TransactionManagerError {
431
+ constructor(operation) {
432
+ super(`Transaction already closed: A ${operation} cannot be executed on a committed transaction`);
433
+ }
434
+ };
435
+ var TransactionRolledBackError = class extends TransactionManagerError {
436
+ constructor(operation) {
437
+ super(`Transaction already closed: A ${operation} cannot be executed on a committed transaction`);
438
+ }
439
+ };
440
+ var TransactionStartTimoutError = class extends TransactionManagerError {
441
+ constructor() {
442
+ super("Unable to start a transaction in the given time.");
443
+ }
444
+ };
445
+ var TransactionExecutionTimeoutError = class extends TransactionManagerError {
446
+ constructor(operation, { timeout, timeTaken }) {
447
+ super(
448
+ `A ${operation} cannot be executed on an expired transaction. The timeout for this transaction was ${timeout} ms, however ${timeTaken} ms passed since the start of the transaction. Consider increasing the interactive transaction timeout or doing less work in the transaction`,
449
+ { operation, timeout, timeTaken }
450
+ );
451
+ }
452
+ };
453
+ var TransactionInternalConsistencyError = class extends TransactionManagerError {
454
+ constructor(message) {
455
+ super(`Internal Consistency Error: ${message}`);
456
+ }
457
+ };
458
+ var InvalidTransactionIsolationLevelError = class extends TransactionManagerError {
459
+ constructor(isolationLevel) {
460
+ super(`Invalid isolation level: ${isolationLevel}`, { isolationLevel });
461
+ }
462
+ };
463
+
464
+ // src/transactionManager/TransactionManager.ts
465
+ var MAX_CLOSED_TRANSACTIONS = 100;
466
+ var isolationLevelMap = {
467
+ ReadUncommitted: "READ UNCOMMITTED",
468
+ ReadCommitted: "READ COMMITTED",
469
+ RepeatableRead: "REPEATABLE READ",
470
+ Snapshot: "SNAPSHOT",
471
+ Serializable: "SERIALIZABLE"
472
+ };
473
+ var debug = Debug("prisma:client:transactionManager");
474
+ var COMMIT_QUERY = () => ({ sql: "COMMIT", args: [], argTypes: [] });
475
+ var ROLLBACK_QUERY = () => ({ sql: "ROLLBACK", args: [], argTypes: [] });
476
+ var ISOLATION_LEVEL_QUERY = (isolationLevel) => ({
477
+ sql: "SET TRANSACTION ISOLATION LEVEL " + isolationLevelMap[isolationLevel],
478
+ args: [],
479
+ argTypes: []
480
+ });
481
+ var TransactionManager = class {
482
+ constructor({ driverAdapter }) {
483
+ // The map of active transactions.
484
+ this.transactions = /* @__PURE__ */ new Map();
485
+ // List of last closed transactions. Max MAX_CLOSED_TRANSACTIONS entries.
486
+ // Used to provide better error messages than a generic "transaction not found".
487
+ this.closedTransactions = [];
488
+ this.driverAdapter = driverAdapter;
489
+ }
490
+ async startTransaction(options) {
491
+ const validatedOptions = this.validateOptions(options);
492
+ const transaction = {
493
+ id: crypto.randomUUID(),
494
+ status: "waiting",
495
+ timer: void 0,
496
+ timeout: validatedOptions.timeout,
497
+ startedAt: Date.now(),
498
+ transaction: void 0
499
+ };
500
+ this.transactions.set(transaction.id, transaction);
501
+ transaction.timer = this.startTransactionTimeout(transaction.id, validatedOptions.maxWait);
502
+ const txContext = await this.driverAdapter.transactionContext();
503
+ if (!txContext.ok)
504
+ throw new TransactionDriverAdapterError("Failed to start transaction.", {
505
+ driverAdapterError: txContext.error
506
+ });
507
+ if (this.requiresSettingIsolationLevelFirst() && validatedOptions.isolationLevel) {
508
+ await txContext.value.executeRaw(ISOLATION_LEVEL_QUERY(validatedOptions.isolationLevel));
509
+ }
510
+ const startedTransaction = await txContext.value.startTransaction();
511
+ if (!startedTransaction.ok)
512
+ throw new TransactionDriverAdapterError("Failed to start transaction.", {
513
+ driverAdapterError: startedTransaction.error
514
+ });
515
+ if (!startedTransaction.value.options.usePhantomQuery) {
516
+ await startedTransaction.value.executeRaw({ sql: "BEGIN", args: [], argTypes: [] });
517
+ if (!this.requiresSettingIsolationLevelFirst() && validatedOptions.isolationLevel) {
518
+ await txContext.value.executeRaw(ISOLATION_LEVEL_QUERY(validatedOptions.isolationLevel));
519
+ }
520
+ }
521
+ switch (transaction.status) {
522
+ case "waiting":
523
+ transaction.transaction = startedTransaction.value;
524
+ clearTimeout(transaction.timer);
525
+ transaction.timer = void 0;
526
+ transaction.status = "running";
527
+ transaction.timer = this.startTransactionTimeout(transaction.id, validatedOptions.timeout);
528
+ return { id: transaction.id };
529
+ case "timed_out":
530
+ throw new TransactionStartTimoutError();
531
+ case "running":
532
+ case "committed":
533
+ case "rolled_back":
534
+ throw new TransactionInternalConsistencyError(
535
+ `Transaction in invalid state ${transaction.status} although it just finished startup.`
536
+ );
537
+ default:
538
+ assertNever(transaction.status, "Unknown transaction status.");
539
+ }
540
+ }
541
+ async commitTransaction(transactionId) {
542
+ const txw = this.getActiveTransaction(transactionId, "commit");
543
+ await this.closeTransaction(txw, "committed");
544
+ }
545
+ async rollbackTransaction(transactionId) {
546
+ const txw = this.getActiveTransaction(transactionId, "rollback");
547
+ await this.closeTransaction(txw, "rolled_back");
548
+ }
549
+ getTransaction(txInfo, operation) {
550
+ const tx = this.getActiveTransaction(txInfo.id, operation);
551
+ if (!tx.transaction) throw new TransactionNotFoundError();
552
+ return tx.transaction;
553
+ }
554
+ getActiveTransaction(transactionId, operation) {
555
+ const transaction = this.transactions.get(transactionId);
556
+ if (!transaction) {
557
+ const closedTransaction = this.closedTransactions.find((tx) => tx.id === transactionId);
558
+ if (closedTransaction) {
559
+ debug("Transaction already closed.", { transactionId, status: closedTransaction.status });
560
+ switch (closedTransaction.status) {
561
+ case "waiting":
562
+ case "running":
563
+ throw new TransactionInternalConsistencyError("Active transaction found in closed transactions list.");
564
+ case "committed":
565
+ throw new TransactionClosedError(operation);
566
+ case "rolled_back":
567
+ throw new TransactionRolledBackError(operation);
568
+ case "timed_out":
569
+ throw new TransactionExecutionTimeoutError(operation, {
570
+ timeout: closedTransaction.timeout,
571
+ timeTaken: Date.now() - closedTransaction.startedAt
572
+ });
573
+ }
574
+ } else {
575
+ debug(`Transaction not found.`, transactionId);
576
+ throw new TransactionNotFoundError();
577
+ }
578
+ }
579
+ if (["committed", "rolled_back", "timed_out"].includes(transaction.status)) {
580
+ throw new TransactionInternalConsistencyError("Closed transaction found in active transactions map.");
581
+ }
582
+ return transaction;
583
+ }
584
+ async cancelAllTransactions() {
585
+ await Promise.allSettled([...this.transactions.values()].map((tx) => this.closeTransaction(tx, "rolled_back")));
586
+ }
587
+ startTransactionTimeout(transactionId, timeout) {
588
+ const timeoutStartedAt = Date.now();
589
+ return setTimeout(async () => {
590
+ debug("Transaction timed out.", { transactionId, timeoutStartedAt, timeout });
591
+ const tx = this.transactions.get(transactionId);
592
+ if (tx && ["running", "waiting"].includes(tx.status)) {
593
+ await this.closeTransaction(tx, "timed_out");
594
+ } else {
595
+ debug("Transaction already committed or rolled back when timeout happened.", transactionId);
596
+ }
597
+ }, timeout);
598
+ }
599
+ async closeTransaction(tx, status) {
600
+ debug("Closing transaction.", { transactionId: tx.id, status });
601
+ tx.status = status;
602
+ if (tx.transaction && status === "committed") {
603
+ const result = await tx.transaction.commit();
604
+ if (!result.ok)
605
+ throw new TransactionDriverAdapterError("Failed to commit transaction.", {
606
+ driverAdapterError: result.error
607
+ });
608
+ if (!tx.transaction.options.usePhantomQuery) {
609
+ await tx.transaction.executeRaw(COMMIT_QUERY());
610
+ }
611
+ } else if (tx.transaction) {
612
+ const result = await tx.transaction.rollback();
613
+ if (!result.ok)
614
+ throw new TransactionDriverAdapterError("Failed to rollback transaction.", {
615
+ driverAdapterError: result.error
616
+ });
617
+ if (!tx.transaction.options.usePhantomQuery) {
618
+ await tx.transaction.executeRaw(ROLLBACK_QUERY());
619
+ }
620
+ }
621
+ clearTimeout(tx.timer);
622
+ tx.timer = void 0;
623
+ this.transactions.delete(tx.id);
624
+ this.closedTransactions.push(tx);
625
+ if (this.closedTransactions.length > MAX_CLOSED_TRANSACTIONS) {
626
+ this.closedTransactions.shift();
627
+ }
628
+ }
629
+ validateOptions(options) {
630
+ if (!options.timeout) throw new TransactionManagerError("timeout is required");
631
+ if (!options.maxWait) throw new TransactionManagerError("maxWait is required");
632
+ if (options.isolationLevel === "Snapshot" /* Snapshot */)
633
+ throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
634
+ if (this.driverAdapter.provider === "sqlite" && options.isolationLevel && options.isolationLevel !== "Serializable" /* Serializable */)
635
+ throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
636
+ return {
637
+ ...options,
638
+ timeout: options.timeout,
639
+ maxWait: options.maxWait
640
+ };
641
+ }
642
+ requiresSettingIsolationLevelFirst() {
643
+ return this.driverAdapter.provider === "mysql";
644
+ }
645
+ };
646
+ export {
647
+ IsolationLevel,
648
+ QueryInterpreter,
649
+ TransactionManager,
650
+ TransactionManagerError,
651
+ isPrismaValuePlaceholder
652
+ };
@@ -0,0 +1,14 @@
1
+ import { Queryable } from '@prisma/driver-adapter-utils';
2
+ import { QueryEvent } from '../events';
3
+ import { QueryPlanNode } from '../QueryPlan';
4
+ export type QueryInterpreterOptions = {
5
+ queryable: Queryable;
6
+ placeholderValues: Record<string, unknown>;
7
+ onQuery?: (event: QueryEvent) => void;
8
+ };
9
+ export declare class QueryInterpreter {
10
+ #private;
11
+ constructor({ queryable, placeholderValues, onQuery }: QueryInterpreterOptions);
12
+ run(queryPlan: QueryPlanNode): Promise<unknown>;
13
+ private interpretNode;
14
+ }
@@ -0,0 +1,4 @@
1
+ import { Query } from '@prisma/driver-adapter-utils';
2
+ import { QueryPlanDbQuery } from '../QueryPlan';
3
+ import { ScopeBindings } from './scope';
4
+ export declare function renderQuery({ query, params }: QueryPlanDbQuery, scope: ScopeBindings): Query;
@@ -0,0 +1,10 @@
1
+ import { Value } from './scope';
2
+ /**
3
+ * A `QueryPlanDbQuery` in which all placeholders have been substituted with
4
+ * their values from the environment.
5
+ */
6
+ export type QueryWithSubstitutedPlaceholders = {
7
+ query: string;
8
+ params: Value[];
9
+ };
10
+ export declare function renderQueryTemplate({ query, params, }: QueryWithSubstitutedPlaceholders): QueryWithSubstitutedPlaceholders;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * An object like a record from the database.
3
+ */
4
+ export type PrismaObject = Record<string, unknown>;
5
+ /**
6
+ * The general type of values each node can evaluate to.
7
+ */
8
+ export type Value = unknown;
9
+ /**
10
+ * Scope in which a query plan node is interpreted. The names may come
11
+ * from the query placeholders or from let bindings introduced in the query plan.
12
+ */
13
+ export type ScopeBindings = Record<string, unknown>;