@prisma/client-engine-runtime 6.6.0-dev.9 → 6.6.0-dev.90
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/QueryPlan.d.ts +31 -2
- package/dist/crypto.d.ts +1 -0
- package/dist/index.d.mts +55 -21
- package/dist/index.d.ts +55 -21
- package/dist/index.js +248 -240
- package/dist/index.mjs +244 -238
- package/dist/interpreter/QueryInterpreter.d.ts +11 -4
- package/dist/interpreter/generators.d.ts +21 -0
- package/dist/interpreter/renderQuery.d.ts +3 -2
- package/dist/interpreter/renderQuery.test.d.ts +1 -0
- package/dist/transactionManager/Transaction.d.ts +1 -7
- package/dist/transactionManager/TransactionManager.d.ts +7 -6
- package/package.json +9 -4
- package/dist/interpreter/renderQueryTemplate.d.ts +0 -10
- /package/dist/interpreter/{renderQueryTemplate.test.d.ts → generators.test.d.ts} +0 -0
package/dist/index.js
CHANGED
|
@@ -5,10 +5,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __typeError = (msg) => {
|
|
9
|
-
throw TypeError(msg);
|
|
10
|
-
};
|
|
11
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
12
8
|
var __export = (target, all) => {
|
|
13
9
|
for (var name in all)
|
|
14
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -30,130 +26,134 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
30
26
|
mod
|
|
31
27
|
));
|
|
32
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
34
|
-
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
35
|
-
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
36
|
-
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);
|
|
37
|
-
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
38
|
-
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
39
29
|
|
|
40
30
|
// src/index.ts
|
|
41
31
|
var index_exports = {};
|
|
42
32
|
__export(index_exports, {
|
|
43
|
-
IsolationLevel: () => IsolationLevel,
|
|
44
33
|
QueryInterpreter: () => QueryInterpreter,
|
|
45
34
|
TransactionManager: () => TransactionManager,
|
|
46
35
|
TransactionManagerError: () => TransactionManagerError,
|
|
36
|
+
isPrismaValueGenerator: () => isPrismaValueGenerator,
|
|
47
37
|
isPrismaValuePlaceholder: () => isPrismaValuePlaceholder
|
|
48
38
|
});
|
|
49
39
|
module.exports = __toCommonJS(index_exports);
|
|
50
40
|
|
|
51
|
-
// src/
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
var
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
41
|
+
// src/interpreter/generators.ts
|
|
42
|
+
var import_cuid = __toESM(require("@bugsnag/cuid"));
|
|
43
|
+
var import_cuid2 = require("@paralleldrive/cuid2");
|
|
44
|
+
var import_nanoid = require("nanoid");
|
|
45
|
+
var import_ulid = require("ulid");
|
|
46
|
+
var import_uuid = require("uuid");
|
|
47
|
+
var GeneratorRegistry = class {
|
|
48
|
+
#generators = {};
|
|
49
|
+
constructor() {
|
|
50
|
+
this.register("now", new NowGenerator());
|
|
51
|
+
this.register("uuid", new UuidGenerator());
|
|
52
|
+
this.register("cuid", new CuidGenerator());
|
|
53
|
+
this.register("ulid", new UlidGenerator());
|
|
54
|
+
this.register("nanoid", new NanoIdGenerator());
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Returns a snapshot of the generator registry. It's 'frozen' in time at the moment of this
|
|
58
|
+
* method being called, meaning that the built-in time-based generators will always return
|
|
59
|
+
* the same value on repeated calls as long as the same snapshot is used.
|
|
60
|
+
*/
|
|
61
|
+
snapshot() {
|
|
62
|
+
return Object.create(this.#generators, {
|
|
63
|
+
now: { value: new NowGenerator() }
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Registers a new generator with the given name.
|
|
68
|
+
*/
|
|
69
|
+
register(name, generator) {
|
|
70
|
+
this.#generators[name] = generator;
|
|
65
71
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
state = stateBeforeQuote;
|
|
82
|
-
} else {
|
|
83
|
-
stateBeforeQuote = state;
|
|
84
|
-
state = 1 /* Quoted */;
|
|
85
|
-
}
|
|
86
|
-
result += nextChar;
|
|
87
|
-
templatePos++;
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
if (query.slice(templatePos, templatePos + BEGIN_REPEAT.length) === BEGIN_REPEAT) {
|
|
91
|
-
if (state === 2 /* Repeating */) {
|
|
92
|
-
throw new Error("Nested repetition is not allowed");
|
|
93
|
-
}
|
|
94
|
-
state = 2 /* Repeating */;
|
|
95
|
-
templatePos += BEGIN_REPEAT.length;
|
|
96
|
-
result += "(";
|
|
97
|
-
continue;
|
|
72
|
+
};
|
|
73
|
+
var NowGenerator = class {
|
|
74
|
+
#now = /* @__PURE__ */ new Date();
|
|
75
|
+
generate() {
|
|
76
|
+
return this.#now.toISOString();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
var UuidGenerator = class {
|
|
80
|
+
generate(arg) {
|
|
81
|
+
if (arg === 4) {
|
|
82
|
+
return (0, import_uuid.v4)();
|
|
83
|
+
} else if (arg === 7) {
|
|
84
|
+
return (0, import_uuid.v7)();
|
|
85
|
+
} else {
|
|
86
|
+
throw new Error("Invalid UUID generator arguments");
|
|
98
87
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
var CuidGenerator = class {
|
|
91
|
+
generate(arg) {
|
|
92
|
+
if (arg === 1) {
|
|
93
|
+
return (0, import_cuid.default)();
|
|
94
|
+
} else if (arg === 2) {
|
|
95
|
+
return (0, import_cuid2.createId)();
|
|
96
|
+
} else {
|
|
97
|
+
throw new Error("Invalid CUID generator arguments");
|
|
107
98
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
case 2 /* Repeating */: {
|
|
125
|
-
const paramArray = Array.isArray(paramValue) ? paramValue : [paramValue];
|
|
126
|
-
if (paramArray.length === 0) {
|
|
127
|
-
result += "NULL";
|
|
128
|
-
break;
|
|
129
|
-
}
|
|
130
|
-
paramArray.forEach((value, idx) => {
|
|
131
|
-
flattenedParams.push(value);
|
|
132
|
-
result += `$${lastParamId++}`;
|
|
133
|
-
if (idx !== paramArray.length - 1) {
|
|
134
|
-
result += ", ";
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
default: {
|
|
140
|
-
throw new Error(`Unexpected state: ${state}`);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
continue;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
var UlidGenerator = class {
|
|
102
|
+
generate() {
|
|
103
|
+
return (0, import_ulid.ulid)();
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
var NanoIdGenerator = class {
|
|
107
|
+
generate(arg) {
|
|
108
|
+
if (typeof arg === "number") {
|
|
109
|
+
return (0, import_nanoid.nanoid)(arg);
|
|
110
|
+
} else if (arg === void 0) {
|
|
111
|
+
return (0, import_nanoid.nanoid)();
|
|
112
|
+
} else {
|
|
113
|
+
throw new Error("Invalid Nanoid generator arguments");
|
|
144
114
|
}
|
|
145
|
-
result += nextChar;
|
|
146
|
-
templatePos++;
|
|
147
115
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// src/QueryPlan.ts
|
|
119
|
+
function isPrismaValuePlaceholder(value) {
|
|
120
|
+
return typeof value === "object" && value !== null && value["prisma__type"] === "param";
|
|
121
|
+
}
|
|
122
|
+
function isPrismaValueGenerator(value) {
|
|
123
|
+
return typeof value === "object" && value !== null && value["prisma__type"] === "generatorCall";
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// src/utils.ts
|
|
127
|
+
function assertNever(_, message) {
|
|
128
|
+
throw new Error(message);
|
|
152
129
|
}
|
|
153
130
|
|
|
154
131
|
// src/interpreter/renderQuery.ts
|
|
155
|
-
function renderQuery(
|
|
156
|
-
const
|
|
132
|
+
function renderQuery(dbQuery, scope, generators) {
|
|
133
|
+
const queryType = dbQuery.type;
|
|
134
|
+
switch (queryType) {
|
|
135
|
+
case "rawSql":
|
|
136
|
+
return renderRawSql(dbQuery.sql, substituteParams(dbQuery.params, scope, generators));
|
|
137
|
+
case "templateSql":
|
|
138
|
+
return renderTemplateSql(
|
|
139
|
+
dbQuery.fragments,
|
|
140
|
+
dbQuery.placeholderFormat,
|
|
141
|
+
substituteParams(dbQuery.params, scope, generators)
|
|
142
|
+
);
|
|
143
|
+
default:
|
|
144
|
+
assertNever(queryType, `Invalid query type`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function substituteParams(params, scope, generators) {
|
|
148
|
+
return params.map((param) => {
|
|
149
|
+
if (isPrismaValueGenerator(param)) {
|
|
150
|
+
const { name, args } = param.prisma__value;
|
|
151
|
+
const generator = generators[name];
|
|
152
|
+
if (!generator) {
|
|
153
|
+
throw new Error(`Encountered an unknown generator '${name}'`);
|
|
154
|
+
}
|
|
155
|
+
return generator.generate(...args);
|
|
156
|
+
}
|
|
157
157
|
if (!isPrismaValuePlaceholder(param)) {
|
|
158
158
|
return param;
|
|
159
159
|
}
|
|
@@ -163,11 +163,48 @@ function renderQuery({ query, params }, scope) {
|
|
|
163
163
|
}
|
|
164
164
|
return value;
|
|
165
165
|
});
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
}
|
|
167
|
+
function renderTemplateSql(fragments, placeholderFormat, params) {
|
|
168
|
+
let paramIndex = 0;
|
|
169
|
+
let placeholderNumber = 1;
|
|
170
|
+
const flattenedParams = [];
|
|
171
|
+
const sql = fragments.map((fragment) => {
|
|
172
|
+
const fragmentType = fragment.type;
|
|
173
|
+
switch (fragmentType) {
|
|
174
|
+
case "parameter":
|
|
175
|
+
if (paramIndex >= params.length) {
|
|
176
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
177
|
+
}
|
|
178
|
+
flattenedParams.push(params[paramIndex++]);
|
|
179
|
+
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
180
|
+
case "stringChunk":
|
|
181
|
+
return fragment.value;
|
|
182
|
+
case "parameterTuple": {
|
|
183
|
+
if (paramIndex >= params.length) {
|
|
184
|
+
throw new Error(`Malformed query template. Fragments attempt to read over ${params.length} parameters.`);
|
|
185
|
+
}
|
|
186
|
+
const paramValue = params[paramIndex++];
|
|
187
|
+
const paramArray = Array.isArray(paramValue) ? paramValue : [paramValue];
|
|
188
|
+
const placeholders = paramArray.length == 0 ? "NULL" : paramArray.map((value) => {
|
|
189
|
+
flattenedParams.push(value);
|
|
190
|
+
return formatPlaceholder(placeholderFormat, placeholderNumber++);
|
|
191
|
+
}).join(",");
|
|
192
|
+
return `(${placeholders})`;
|
|
193
|
+
}
|
|
194
|
+
default:
|
|
195
|
+
assertNever(fragmentType, "Invalid fragment type");
|
|
196
|
+
}
|
|
197
|
+
}).join("");
|
|
198
|
+
return renderRawSql(sql, flattenedParams);
|
|
199
|
+
}
|
|
200
|
+
function formatPlaceholder(placeholderFormat, placeholderNumber) {
|
|
201
|
+
return placeholderFormat.hasNumbering ? `${placeholderFormat.prefix}${placeholderNumber}` : placeholderFormat.prefix;
|
|
202
|
+
}
|
|
203
|
+
function renderRawSql(sql, params) {
|
|
204
|
+
const argTypes = params.map((param) => toArgType(param));
|
|
168
205
|
return {
|
|
169
|
-
sql
|
|
170
|
-
args:
|
|
206
|
+
sql,
|
|
207
|
+
args: params,
|
|
171
208
|
argTypes
|
|
172
209
|
};
|
|
173
210
|
}
|
|
@@ -236,24 +273,23 @@ function serialize(resultSet) {
|
|
|
236
273
|
}
|
|
237
274
|
|
|
238
275
|
// src/interpreter/QueryInterpreter.ts
|
|
239
|
-
var _queryable, _placeholderValues, _onQuery, _QueryInterpreter_instances, withQueryEvent_fn;
|
|
240
276
|
var QueryInterpreter = class {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
250
|
-
async run(queryPlan) {
|
|
251
|
-
return this.interpretNode(queryPlan,
|
|
252
|
-
}
|
|
253
|
-
async interpretNode(node, scope) {
|
|
277
|
+
#transactionManager;
|
|
278
|
+
#placeholderValues;
|
|
279
|
+
#onQuery;
|
|
280
|
+
#generators = new GeneratorRegistry();
|
|
281
|
+
constructor({ transactionManager, placeholderValues, onQuery }) {
|
|
282
|
+
this.#transactionManager = transactionManager;
|
|
283
|
+
this.#placeholderValues = placeholderValues;
|
|
284
|
+
this.#onQuery = onQuery;
|
|
285
|
+
}
|
|
286
|
+
async run(queryPlan, queryable) {
|
|
287
|
+
return this.interpretNode(queryPlan, queryable, this.#placeholderValues, this.#generators.snapshot());
|
|
288
|
+
}
|
|
289
|
+
async interpretNode(node, queryable, scope, generators) {
|
|
254
290
|
switch (node.type) {
|
|
255
291
|
case "seq": {
|
|
256
|
-
const results = await Promise.all(node.args.map((arg) => this.interpretNode(arg, scope)));
|
|
292
|
+
const results = await Promise.all(node.args.map((arg) => this.interpretNode(arg, queryable, scope, generators)));
|
|
257
293
|
return results[results.length - 1];
|
|
258
294
|
}
|
|
259
295
|
case "get": {
|
|
@@ -263,10 +299,10 @@ var QueryInterpreter = class {
|
|
|
263
299
|
const nestedScope = Object.create(scope);
|
|
264
300
|
await Promise.all(
|
|
265
301
|
node.args.bindings.map(async (binding) => {
|
|
266
|
-
nestedScope[binding.name] = await this.interpretNode(binding.expr, scope);
|
|
302
|
+
nestedScope[binding.name] = await this.interpretNode(binding.expr, queryable, scope, generators);
|
|
267
303
|
})
|
|
268
304
|
);
|
|
269
|
-
return this.interpretNode(node.args.expr, nestedScope);
|
|
305
|
+
return this.interpretNode(node.args.expr, queryable, nestedScope, generators);
|
|
270
306
|
}
|
|
271
307
|
case "getFirstNonEmpty": {
|
|
272
308
|
for (const name of node.args.names) {
|
|
@@ -278,41 +314,31 @@ var QueryInterpreter = class {
|
|
|
278
314
|
return [];
|
|
279
315
|
}
|
|
280
316
|
case "concat": {
|
|
281
|
-
const parts = await Promise.all(node.args.map((arg) => this.interpretNode(arg, scope)));
|
|
317
|
+
const parts = await Promise.all(node.args.map((arg) => this.interpretNode(arg, queryable, scope, generators)));
|
|
282
318
|
return parts.reduce((acc, part) => acc.concat(asList(part)), []);
|
|
283
319
|
}
|
|
284
320
|
case "sum": {
|
|
285
|
-
const parts = await Promise.all(node.args.map((arg) => this.interpretNode(arg, scope)));
|
|
321
|
+
const parts = await Promise.all(node.args.map((arg) => this.interpretNode(arg, queryable, scope, generators)));
|
|
286
322
|
return parts.reduce((acc, part) => asNumber(acc) + asNumber(part));
|
|
287
323
|
}
|
|
288
324
|
case "execute": {
|
|
289
|
-
const query = renderQuery(node.args, scope);
|
|
290
|
-
return
|
|
291
|
-
|
|
292
|
-
if (result.ok) {
|
|
293
|
-
return result.value;
|
|
294
|
-
} else {
|
|
295
|
-
throw result.error;
|
|
296
|
-
}
|
|
325
|
+
const query = renderQuery(node.args, scope, generators);
|
|
326
|
+
return this.#withQueryEvent(query, async () => {
|
|
327
|
+
return await queryable.executeRaw(query);
|
|
297
328
|
});
|
|
298
329
|
}
|
|
299
330
|
case "query": {
|
|
300
|
-
const query = renderQuery(node.args, scope);
|
|
301
|
-
return
|
|
302
|
-
|
|
303
|
-
if (result.ok) {
|
|
304
|
-
return serialize(result.value);
|
|
305
|
-
} else {
|
|
306
|
-
throw result.error;
|
|
307
|
-
}
|
|
331
|
+
const query = renderQuery(node.args, scope, generators);
|
|
332
|
+
return this.#withQueryEvent(query, async () => {
|
|
333
|
+
return serialize(await queryable.queryRaw(query));
|
|
308
334
|
});
|
|
309
335
|
}
|
|
310
336
|
case "reverse": {
|
|
311
|
-
const value = await this.interpretNode(node.args, scope);
|
|
337
|
+
const value = await this.interpretNode(node.args, queryable, scope, generators);
|
|
312
338
|
return Array.isArray(value) ? value.reverse() : value;
|
|
313
339
|
}
|
|
314
340
|
case "unique": {
|
|
315
|
-
const value = await this.interpretNode(node.args, scope);
|
|
341
|
+
const value = await this.interpretNode(node.args, queryable, scope, generators);
|
|
316
342
|
if (!Array.isArray(value)) {
|
|
317
343
|
return value;
|
|
318
344
|
}
|
|
@@ -322,22 +348,22 @@ var QueryInterpreter = class {
|
|
|
322
348
|
return value[0] ?? null;
|
|
323
349
|
}
|
|
324
350
|
case "required": {
|
|
325
|
-
const value = await this.interpretNode(node.args, scope);
|
|
351
|
+
const value = await this.interpretNode(node.args, queryable, scope, generators);
|
|
326
352
|
if (isEmpty(value)) {
|
|
327
353
|
throw new Error("Required value is empty");
|
|
328
354
|
}
|
|
329
355
|
return value;
|
|
330
356
|
}
|
|
331
357
|
case "mapField": {
|
|
332
|
-
const value = await this.interpretNode(node.args.records, scope);
|
|
358
|
+
const value = await this.interpretNode(node.args.records, queryable, scope, generators);
|
|
333
359
|
return mapField(value, node.args.field);
|
|
334
360
|
}
|
|
335
361
|
case "join": {
|
|
336
|
-
const parent = await this.interpretNode(node.args.parent, scope);
|
|
362
|
+
const parent = await this.interpretNode(node.args.parent, queryable, scope, generators);
|
|
337
363
|
const children = await Promise.all(
|
|
338
364
|
node.args.children.map(async (joinExpr) => ({
|
|
339
365
|
joinExpr,
|
|
340
|
-
childRecords: await this.interpretNode(joinExpr.child, scope)
|
|
366
|
+
childRecords: await this.interpretNode(joinExpr.child, queryable, scope, generators)
|
|
341
367
|
}))
|
|
342
368
|
);
|
|
343
369
|
if (Array.isArray(parent)) {
|
|
@@ -348,30 +374,41 @@ var QueryInterpreter = class {
|
|
|
348
374
|
}
|
|
349
375
|
return attachChildrenToParent(asRecord(parent), children);
|
|
350
376
|
}
|
|
377
|
+
case "transaction": {
|
|
378
|
+
if (!this.#transactionManager.enabled) {
|
|
379
|
+
return this.interpretNode(node.args, queryable, scope, generators);
|
|
380
|
+
}
|
|
381
|
+
const transactionManager = this.#transactionManager.manager;
|
|
382
|
+
const transactionInfo = await transactionManager.startTransaction();
|
|
383
|
+
const transaction = transactionManager.getTransaction(transactionInfo, "new");
|
|
384
|
+
try {
|
|
385
|
+
const value = await this.interpretNode(node.args, transaction, scope, generators);
|
|
386
|
+
await transactionManager.commitTransaction(transactionInfo.id);
|
|
387
|
+
return value;
|
|
388
|
+
} catch (e) {
|
|
389
|
+
await transactionManager.rollbackTransaction(transactionInfo.id);
|
|
390
|
+
throw e;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
351
393
|
default: {
|
|
352
394
|
node;
|
|
353
395
|
throw new Error(`Unexpected node type: ${node.type}`);
|
|
354
396
|
}
|
|
355
397
|
}
|
|
356
398
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
duration: endInstant - startInstant,
|
|
371
|
-
query: query.sql,
|
|
372
|
-
params: query.args
|
|
373
|
-
});
|
|
374
|
-
return result;
|
|
399
|
+
async #withQueryEvent(query, execute) {
|
|
400
|
+
const timestamp = /* @__PURE__ */ new Date();
|
|
401
|
+
const startInstant = performance.now();
|
|
402
|
+
const result = await execute();
|
|
403
|
+
const endInstant = performance.now();
|
|
404
|
+
this.#onQuery?.({
|
|
405
|
+
timestamp,
|
|
406
|
+
duration: endInstant - startInstant,
|
|
407
|
+
query: query.sql,
|
|
408
|
+
params: query.args
|
|
409
|
+
});
|
|
410
|
+
return result;
|
|
411
|
+
}
|
|
375
412
|
};
|
|
376
413
|
function isEmpty(value) {
|
|
377
414
|
if (Array.isArray(value)) {
|
|
@@ -429,22 +466,16 @@ function childRecordMatchesParent(childRecord, parentRecord, joinExpr) {
|
|
|
429
466
|
return true;
|
|
430
467
|
}
|
|
431
468
|
|
|
432
|
-
// src/transactionManager/Transaction.ts
|
|
433
|
-
var IsolationLevel = /* @__PURE__ */ ((IsolationLevel2) => {
|
|
434
|
-
IsolationLevel2["ReadUncommitted"] = "ReadUncommitted";
|
|
435
|
-
IsolationLevel2["ReadCommitted"] = "ReadCommitted";
|
|
436
|
-
IsolationLevel2["RepeatableRead"] = "RepeatableRead";
|
|
437
|
-
IsolationLevel2["Snapshot"] = "Snapshot";
|
|
438
|
-
IsolationLevel2["Serializable"] = "Serializable";
|
|
439
|
-
return IsolationLevel2;
|
|
440
|
-
})(IsolationLevel || {});
|
|
441
|
-
|
|
442
469
|
// src/transactionManager/TransactionManager.ts
|
|
443
|
-
var import_debug =
|
|
470
|
+
var import_debug = require("@prisma/debug");
|
|
444
471
|
|
|
445
|
-
// src/
|
|
446
|
-
function
|
|
447
|
-
|
|
472
|
+
// src/crypto.ts
|
|
473
|
+
async function getCrypto() {
|
|
474
|
+
return globalThis.crypto ?? await import("node:crypto");
|
|
475
|
+
}
|
|
476
|
+
async function randomUUID() {
|
|
477
|
+
const crypto = await getCrypto();
|
|
478
|
+
return crypto.randomUUID();
|
|
448
479
|
}
|
|
449
480
|
|
|
450
481
|
// src/transactionManager/TransactionManagerErrors.ts
|
|
@@ -452,8 +483,8 @@ var TransactionManagerError = class extends Error {
|
|
|
452
483
|
constructor(message, meta) {
|
|
453
484
|
super("Transaction API error: " + message);
|
|
454
485
|
this.meta = meta;
|
|
455
|
-
__publicField(this, "code", "P2028");
|
|
456
486
|
}
|
|
487
|
+
code = "P2028";
|
|
457
488
|
};
|
|
458
489
|
var TransactionDriverAdapterError = class extends TransactionManagerError {
|
|
459
490
|
constructor(message, errorParams) {
|
|
@@ -503,35 +534,25 @@ var InvalidTransactionIsolationLevelError = class extends TransactionManagerErro
|
|
|
503
534
|
|
|
504
535
|
// src/transactionManager/TransactionManager.ts
|
|
505
536
|
var MAX_CLOSED_TRANSACTIONS = 100;
|
|
506
|
-
var
|
|
507
|
-
ReadUncommitted: "READ UNCOMMITTED",
|
|
508
|
-
ReadCommitted: "READ COMMITTED",
|
|
509
|
-
RepeatableRead: "REPEATABLE READ",
|
|
510
|
-
Snapshot: "SNAPSHOT",
|
|
511
|
-
Serializable: "SERIALIZABLE"
|
|
512
|
-
};
|
|
513
|
-
var debug = (0, import_debug.default)("prisma:client:transactionManager");
|
|
537
|
+
var debug = (0, import_debug.Debug)("prisma:client:transactionManager");
|
|
514
538
|
var COMMIT_QUERY = () => ({ sql: "COMMIT", args: [], argTypes: [] });
|
|
515
539
|
var ROLLBACK_QUERY = () => ({ sql: "ROLLBACK", args: [], argTypes: [] });
|
|
516
|
-
var ISOLATION_LEVEL_QUERY = (isolationLevel) => ({
|
|
517
|
-
sql: "SET TRANSACTION ISOLATION LEVEL " + isolationLevelMap[isolationLevel],
|
|
518
|
-
args: [],
|
|
519
|
-
argTypes: []
|
|
520
|
-
});
|
|
521
540
|
var TransactionManager = class {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
541
|
+
// The map of active transactions.
|
|
542
|
+
transactions = /* @__PURE__ */ new Map();
|
|
543
|
+
// List of last closed transactions. Max MAX_CLOSED_TRANSACTIONS entries.
|
|
544
|
+
// Used to provide better error messages than a generic "transaction not found".
|
|
545
|
+
closedTransactions = [];
|
|
546
|
+
driverAdapter;
|
|
547
|
+
transactionOptions;
|
|
548
|
+
constructor({ driverAdapter, transactionOptions }) {
|
|
529
549
|
this.driverAdapter = driverAdapter;
|
|
550
|
+
this.transactionOptions = transactionOptions;
|
|
530
551
|
}
|
|
531
552
|
async startTransaction(options) {
|
|
532
|
-
const validatedOptions = this.validateOptions(options);
|
|
553
|
+
const validatedOptions = options !== void 0 ? this.validateOptions(options) : this.transactionOptions;
|
|
533
554
|
const transaction = {
|
|
534
|
-
id:
|
|
555
|
+
id: await randomUUID(),
|
|
535
556
|
status: "waiting",
|
|
536
557
|
timer: void 0,
|
|
537
558
|
timeout: validatedOptions.timeout,
|
|
@@ -540,28 +561,17 @@ var TransactionManager = class {
|
|
|
540
561
|
};
|
|
541
562
|
this.transactions.set(transaction.id, transaction);
|
|
542
563
|
transaction.timer = this.startTransactionTimeout(transaction.id, validatedOptions.maxWait);
|
|
543
|
-
|
|
544
|
-
|
|
564
|
+
let startedTransaction;
|
|
565
|
+
try {
|
|
566
|
+
startedTransaction = await this.driverAdapter.startTransaction(validatedOptions.isolationLevel);
|
|
567
|
+
} catch (error) {
|
|
545
568
|
throw new TransactionDriverAdapterError("Failed to start transaction.", {
|
|
546
|
-
driverAdapterError:
|
|
569
|
+
driverAdapterError: error
|
|
547
570
|
});
|
|
548
|
-
if (this.requiresSettingIsolationLevelFirst() && validatedOptions.isolationLevel) {
|
|
549
|
-
await txContext.value.executeRaw(ISOLATION_LEVEL_QUERY(validatedOptions.isolationLevel));
|
|
550
|
-
}
|
|
551
|
-
const startedTransaction = await txContext.value.startTransaction();
|
|
552
|
-
if (!startedTransaction.ok)
|
|
553
|
-
throw new TransactionDriverAdapterError("Failed to start transaction.", {
|
|
554
|
-
driverAdapterError: startedTransaction.error
|
|
555
|
-
});
|
|
556
|
-
if (!startedTransaction.value.options.usePhantomQuery) {
|
|
557
|
-
await startedTransaction.value.executeRaw({ sql: "BEGIN", args: [], argTypes: [] });
|
|
558
|
-
if (!this.requiresSettingIsolationLevelFirst() && validatedOptions.isolationLevel) {
|
|
559
|
-
await txContext.value.executeRaw(ISOLATION_LEVEL_QUERY(validatedOptions.isolationLevel));
|
|
560
|
-
}
|
|
561
571
|
}
|
|
562
572
|
switch (transaction.status) {
|
|
563
573
|
case "waiting":
|
|
564
|
-
transaction.transaction = startedTransaction
|
|
574
|
+
transaction.transaction = startedTransaction;
|
|
565
575
|
clearTimeout(transaction.timer);
|
|
566
576
|
transaction.timer = void 0;
|
|
567
577
|
transaction.status = "running";
|
|
@@ -641,20 +651,24 @@ var TransactionManager = class {
|
|
|
641
651
|
debug("Closing transaction.", { transactionId: tx.id, status });
|
|
642
652
|
tx.status = status;
|
|
643
653
|
if (tx.transaction && status === "committed") {
|
|
644
|
-
|
|
645
|
-
|
|
654
|
+
try {
|
|
655
|
+
await tx.transaction.commit();
|
|
656
|
+
} catch (error) {
|
|
646
657
|
throw new TransactionDriverAdapterError("Failed to commit transaction.", {
|
|
647
|
-
driverAdapterError:
|
|
658
|
+
driverAdapterError: error
|
|
648
659
|
});
|
|
660
|
+
}
|
|
649
661
|
if (!tx.transaction.options.usePhantomQuery) {
|
|
650
662
|
await tx.transaction.executeRaw(COMMIT_QUERY());
|
|
651
663
|
}
|
|
652
664
|
} else if (tx.transaction) {
|
|
653
|
-
|
|
654
|
-
|
|
665
|
+
try {
|
|
666
|
+
await tx.transaction.rollback();
|
|
667
|
+
} catch (error) {
|
|
655
668
|
throw new TransactionDriverAdapterError("Failed to rollback transaction.", {
|
|
656
|
-
driverAdapterError:
|
|
669
|
+
driverAdapterError: error
|
|
657
670
|
});
|
|
671
|
+
}
|
|
658
672
|
if (!tx.transaction.options.usePhantomQuery) {
|
|
659
673
|
await tx.transaction.executeRaw(ROLLBACK_QUERY());
|
|
660
674
|
}
|
|
@@ -670,25 +684,19 @@ var TransactionManager = class {
|
|
|
670
684
|
validateOptions(options) {
|
|
671
685
|
if (!options.timeout) throw new TransactionManagerError("timeout is required");
|
|
672
686
|
if (!options.maxWait) throw new TransactionManagerError("maxWait is required");
|
|
673
|
-
if (options.isolationLevel === "
|
|
674
|
-
throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
|
|
675
|
-
if (this.driverAdapter.provider === "sqlite" && options.isolationLevel && options.isolationLevel !== "Serializable" /* Serializable */)
|
|
676
|
-
throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
|
|
687
|
+
if (options.isolationLevel === "SNAPSHOT") throw new InvalidTransactionIsolationLevelError(options.isolationLevel);
|
|
677
688
|
return {
|
|
678
689
|
...options,
|
|
679
690
|
timeout: options.timeout,
|
|
680
691
|
maxWait: options.maxWait
|
|
681
692
|
};
|
|
682
693
|
}
|
|
683
|
-
requiresSettingIsolationLevelFirst() {
|
|
684
|
-
return this.driverAdapter.provider === "mysql";
|
|
685
|
-
}
|
|
686
694
|
};
|
|
687
695
|
// Annotate the CommonJS export names for ESM import in node:
|
|
688
696
|
0 && (module.exports = {
|
|
689
|
-
IsolationLevel,
|
|
690
697
|
QueryInterpreter,
|
|
691
698
|
TransactionManager,
|
|
692
699
|
TransactionManagerError,
|
|
700
|
+
isPrismaValueGenerator,
|
|
693
701
|
isPrismaValuePlaceholder
|
|
694
702
|
});
|