@prisma/client-engine-runtime 6.9.0-dev.2 → 6.9.0-dev.21
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 +36 -1
- package/dist/UserFacingError.d.ts +3 -3
- package/dist/index.d.mts +63 -9
- package/dist/index.d.ts +63 -9
- package/dist/index.js +321 -115
- package/dist/index.mjs +317 -115
- package/dist/interpreter/DataMapper.d.ts +3 -0
- package/dist/interpreter/QueryInterpreter.d.ts +2 -1
- package/dist/interpreter/serializeSql.d.ts +2 -1
- package/dist/transactionManager/TransactionManagerErrors.d.ts +4 -4
- package/dist/utils.d.ts +10 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -30,10 +30,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
DataMapperError: () => DataMapperError,
|
|
33
34
|
QueryInterpreter: () => QueryInterpreter,
|
|
34
35
|
TransactionManager: () => TransactionManager,
|
|
35
36
|
TransactionManagerError: () => TransactionManagerError,
|
|
36
37
|
UserFacingError: () => UserFacingError,
|
|
38
|
+
doKeysMatch: () => doKeysMatch,
|
|
39
|
+
isDeepStrictEqual: () => isDeepStrictEqual,
|
|
40
|
+
isPrismaValueBigInt: () => isPrismaValueBigInt,
|
|
37
41
|
isPrismaValueBytes: () => isPrismaValueBytes,
|
|
38
42
|
isPrismaValueGenerator: () => isPrismaValueGenerator,
|
|
39
43
|
isPrismaValuePlaceholder: () => isPrismaValuePlaceholder,
|
|
@@ -41,13 +45,147 @@ __export(index_exports, {
|
|
|
41
45
|
});
|
|
42
46
|
module.exports = __toCommonJS(index_exports);
|
|
43
47
|
|
|
44
|
-
// src/interpreter/
|
|
45
|
-
var
|
|
48
|
+
// src/interpreter/DataMapper.ts
|
|
49
|
+
var import_decimal2 = __toESM(require("decimal.js"));
|
|
46
50
|
|
|
47
51
|
// src/utils.ts
|
|
52
|
+
var import_decimal = __toESM(require("decimal.js"));
|
|
48
53
|
function assertNever(_, message) {
|
|
49
54
|
throw new Error(message);
|
|
50
55
|
}
|
|
56
|
+
function isDeepStrictEqual(a, b) {
|
|
57
|
+
return a === b || a !== null && b !== null && typeof a === "object" && typeof b === "object" && Object.keys(a).length === Object.keys(b).length && Object.keys(a).every((key) => isDeepStrictEqual(a[key], b[key]));
|
|
58
|
+
}
|
|
59
|
+
function doKeysMatch(lhs, rhs) {
|
|
60
|
+
const lhsKeys = Object.keys(lhs);
|
|
61
|
+
const rhsKeys = Object.keys(rhs);
|
|
62
|
+
const smallerKeyList = lhsKeys.length < rhsKeys.length ? lhsKeys : rhsKeys;
|
|
63
|
+
return smallerKeyList.every((key) => {
|
|
64
|
+
if (typeof lhs[key] !== typeof rhs[key]) {
|
|
65
|
+
if (typeof lhs[key] === "number" || typeof rhs[key] === "number") {
|
|
66
|
+
return `${lhs[key]}` === `${rhs[key]}`;
|
|
67
|
+
} else if (typeof lhs[key] === "bigint" || typeof rhs[key] === "bigint") {
|
|
68
|
+
return BigInt(`${lhs[key]}`.replace(/n$/, "")) === BigInt(`${rhs[key]}`.replace(/n$/, ""));
|
|
69
|
+
} else if (lhs[key] instanceof Date || rhs[key] instanceof Date) {
|
|
70
|
+
return (/* @__PURE__ */ new Date(`${lhs[key]}`)).getTime() === (/* @__PURE__ */ new Date(`${rhs[key]}`)).getTime();
|
|
71
|
+
} else if (import_decimal.default.isDecimal(lhs[key]) || import_decimal.default.isDecimal(rhs[key])) {
|
|
72
|
+
return new import_decimal.default(`${lhs[key]}`).equals(new import_decimal.default(`${rhs[key]}`));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return isDeepStrictEqual(lhs[key], rhs[key]);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/interpreter/DataMapper.ts
|
|
80
|
+
var DataMapperError = class extends Error {
|
|
81
|
+
name = "DataMapperError";
|
|
82
|
+
};
|
|
83
|
+
function applyDataMap(data, structure) {
|
|
84
|
+
switch (structure.type) {
|
|
85
|
+
case "Object":
|
|
86
|
+
return mapArrayOrObject(data, structure.fields);
|
|
87
|
+
case "Value":
|
|
88
|
+
return mapValue(data, structure.resultType);
|
|
89
|
+
default:
|
|
90
|
+
assertNever(structure, `Invalid data mapping type: '${structure.type}'`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function mapArrayOrObject(data, fields) {
|
|
94
|
+
if (data === null) return null;
|
|
95
|
+
if (Array.isArray(data)) {
|
|
96
|
+
const rows = data;
|
|
97
|
+
return rows.map((row) => mapObject(row, fields));
|
|
98
|
+
}
|
|
99
|
+
if (typeof data === "object") {
|
|
100
|
+
const row = data;
|
|
101
|
+
return mapObject(row, fields);
|
|
102
|
+
}
|
|
103
|
+
if (typeof data === "string") {
|
|
104
|
+
let decodedData;
|
|
105
|
+
try {
|
|
106
|
+
decodedData = JSON.parse(data);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
throw new DataMapperError(`Expected an array or object, got a string that is not valid JSON`, {
|
|
109
|
+
cause: error
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return mapArrayOrObject(decodedData, fields);
|
|
113
|
+
}
|
|
114
|
+
throw new DataMapperError(`Expected an array or an object, got: ${typeof data}`);
|
|
115
|
+
}
|
|
116
|
+
function mapObject(data, fields) {
|
|
117
|
+
if (typeof data !== "object") {
|
|
118
|
+
throw new DataMapperError(`Expected an object, but got '${typeof data}'`);
|
|
119
|
+
}
|
|
120
|
+
const result = {};
|
|
121
|
+
for (const [name, node] of Object.entries(fields)) {
|
|
122
|
+
switch (node.type) {
|
|
123
|
+
case "Object": {
|
|
124
|
+
if (!node.flattened && !Object.hasOwn(data, name)) {
|
|
125
|
+
throw new DataMapperError(
|
|
126
|
+
`Missing data field (Object): '${name}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
const target = node.flattened ? data : data[name];
|
|
130
|
+
result[name] = mapArrayOrObject(target, node.fields);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case "Value":
|
|
134
|
+
{
|
|
135
|
+
const dbName = node.dbName;
|
|
136
|
+
if (Object.hasOwn(data, dbName)) {
|
|
137
|
+
result[name] = mapValue(data[dbName], node.resultType);
|
|
138
|
+
} else {
|
|
139
|
+
throw new DataMapperError(
|
|
140
|
+
`Missing data field (Value): '${dbName}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
break;
|
|
145
|
+
default:
|
|
146
|
+
assertNever(node, `DataMapper: Invalid data mapping node type: '${node.type}'`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
function mapValue(value, resultType) {
|
|
152
|
+
if (value === null) return null;
|
|
153
|
+
switch (resultType.type) {
|
|
154
|
+
case "Any":
|
|
155
|
+
return value;
|
|
156
|
+
case "String":
|
|
157
|
+
return typeof value === "string" ? value : `${value}`;
|
|
158
|
+
case "Int":
|
|
159
|
+
return typeof value === "number" ? value : parseInt(`${value}`, 10);
|
|
160
|
+
case "BigInt":
|
|
161
|
+
return typeof value === "bigint" ? value : BigInt(`${value}`);
|
|
162
|
+
case "Float":
|
|
163
|
+
return typeof value === "number" ? value : parseFloat(`${value}`);
|
|
164
|
+
case "Boolean":
|
|
165
|
+
return typeof value === "boolean" ? value : value !== "0";
|
|
166
|
+
case "Decimal":
|
|
167
|
+
return typeof value === "number" ? new import_decimal2.default(value) : new import_decimal2.default(`${value}`);
|
|
168
|
+
case "Date":
|
|
169
|
+
return value instanceof Date ? value : /* @__PURE__ */ new Date(`${value}`);
|
|
170
|
+
case "Array": {
|
|
171
|
+
const values = value;
|
|
172
|
+
return values.map((v) => mapValue(v, resultType.inner));
|
|
173
|
+
}
|
|
174
|
+
case "Object":
|
|
175
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
176
|
+
case "Bytes": {
|
|
177
|
+
if (!Array.isArray(value)) {
|
|
178
|
+
throw new DataMapperError(`Bytes data is invalid, got: ${typeof value}`);
|
|
179
|
+
}
|
|
180
|
+
return new Uint8Array(value);
|
|
181
|
+
}
|
|
182
|
+
default:
|
|
183
|
+
assertNever(resultType, `DataMapper: Unknown result type: ${resultType.type}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/interpreter/QueryInterpreter.ts
|
|
188
|
+
var import_api = require("@opentelemetry/api");
|
|
51
189
|
|
|
52
190
|
// src/tracing.ts
|
|
53
191
|
var noopTracingHelper = {
|
|
@@ -77,7 +215,7 @@ var UserFacingError = class extends Error {
|
|
|
77
215
|
constructor(message, code, meta) {
|
|
78
216
|
super(message);
|
|
79
217
|
this.code = code;
|
|
80
|
-
this.meta = meta;
|
|
218
|
+
this.meta = meta ?? {};
|
|
81
219
|
}
|
|
82
220
|
toQueryResponseErrorObject() {
|
|
83
221
|
return {
|
|
@@ -100,7 +238,7 @@ function rethrowAsUserFacing(error) {
|
|
|
100
238
|
if (!code || !message) {
|
|
101
239
|
throw error;
|
|
102
240
|
}
|
|
103
|
-
throw new UserFacingError(message, code, error);
|
|
241
|
+
throw new UserFacingError(message, code, { driverAdapterError: error });
|
|
104
242
|
}
|
|
105
243
|
function getErrorCode(err) {
|
|
106
244
|
switch (err.cause.kind) {
|
|
@@ -211,100 +349,6 @@ function renderConstraint(constraint) {
|
|
|
211
349
|
return "(not available)";
|
|
212
350
|
}
|
|
213
351
|
|
|
214
|
-
// src/interpreter/DataMapper.ts
|
|
215
|
-
var import_decimal = __toESM(require("decimal.js"));
|
|
216
|
-
function applyDataMap(data, structure) {
|
|
217
|
-
switch (structure.type) {
|
|
218
|
-
case "Object":
|
|
219
|
-
return mapArrayOrObject(data, structure.fields);
|
|
220
|
-
case "Value":
|
|
221
|
-
return mapValue(data, structure.resultType);
|
|
222
|
-
default:
|
|
223
|
-
assertNever(structure, `Invalid data mapping type: '${structure.type}'`);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
function mapArrayOrObject(data, fields) {
|
|
227
|
-
if (data === null) return null;
|
|
228
|
-
if (Array.isArray(data)) {
|
|
229
|
-
const rows = data;
|
|
230
|
-
return rows.map((row) => mapObject(row, fields));
|
|
231
|
-
}
|
|
232
|
-
if (typeof data === "object") {
|
|
233
|
-
const row = data;
|
|
234
|
-
return mapObject(row, fields);
|
|
235
|
-
}
|
|
236
|
-
throw new Error(`DataMapper: Expected an array or an object, got: ${typeof data}`);
|
|
237
|
-
}
|
|
238
|
-
function mapObject(data, fields) {
|
|
239
|
-
if (typeof data !== "object") {
|
|
240
|
-
throw new Error(`DataMapper: Expected an object, but got '${typeof data}'`);
|
|
241
|
-
}
|
|
242
|
-
const result = {};
|
|
243
|
-
for (const [name, node] of Object.entries(fields)) {
|
|
244
|
-
switch (node.type) {
|
|
245
|
-
case "Object":
|
|
246
|
-
if (Object.hasOwn(data, name)) {
|
|
247
|
-
result[name] = mapArrayOrObject(data[name], node.fields);
|
|
248
|
-
} else {
|
|
249
|
-
throw new Error(
|
|
250
|
-
`DataMapper: Missing data field (Object): '${name}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
251
|
-
);
|
|
252
|
-
}
|
|
253
|
-
break;
|
|
254
|
-
case "Value":
|
|
255
|
-
{
|
|
256
|
-
const dbName = node.dbName;
|
|
257
|
-
if (Object.hasOwn(data, dbName)) {
|
|
258
|
-
result[name] = mapValue(data[dbName], node.resultType);
|
|
259
|
-
} else {
|
|
260
|
-
throw new Error(
|
|
261
|
-
`DataMapper: Missing data field (Value): '${dbName}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
262
|
-
);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
break;
|
|
266
|
-
default:
|
|
267
|
-
assertNever(node, `DataMapper: Invalid data mapping node type: '${node.type}'`);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
return result;
|
|
271
|
-
}
|
|
272
|
-
function mapValue(value, resultType) {
|
|
273
|
-
if (value === null) return null;
|
|
274
|
-
switch (resultType.type) {
|
|
275
|
-
case "Any":
|
|
276
|
-
return value;
|
|
277
|
-
case "String":
|
|
278
|
-
return typeof value === "string" ? value : `${value}`;
|
|
279
|
-
case "Int":
|
|
280
|
-
return typeof value === "number" ? value : parseInt(`${value}`, 10);
|
|
281
|
-
case "BigInt":
|
|
282
|
-
return typeof value === "bigint" ? value : BigInt(`${value}`);
|
|
283
|
-
case "Float":
|
|
284
|
-
return typeof value === "number" ? value : parseFloat(`${value}`);
|
|
285
|
-
case "Boolean":
|
|
286
|
-
return typeof value === "boolean" ? value : value !== "0";
|
|
287
|
-
case "Decimal":
|
|
288
|
-
return typeof value === "number" ? new import_decimal.default(value) : new import_decimal.default(`${value}`);
|
|
289
|
-
case "Date":
|
|
290
|
-
return value instanceof Date ? value : /* @__PURE__ */ new Date(`${value}`);
|
|
291
|
-
case "Array": {
|
|
292
|
-
const values = value;
|
|
293
|
-
return values.map((v) => mapValue(v, resultType.inner));
|
|
294
|
-
}
|
|
295
|
-
case "Object":
|
|
296
|
-
return typeof value === "string" ? value : JSON.stringify(value);
|
|
297
|
-
case "Bytes": {
|
|
298
|
-
if (!Array.isArray(value)) {
|
|
299
|
-
throw new Error(`DataMapper: Bytes data is invalid, got: ${typeof value}`);
|
|
300
|
-
}
|
|
301
|
-
return new Uint8Array(value);
|
|
302
|
-
}
|
|
303
|
-
default:
|
|
304
|
-
assertNever(resultType, `DataMapper: Unknown result type: ${resultType.type}`);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
352
|
// src/interpreter/generators.ts
|
|
309
353
|
var import_cuid = __toESM(require("@bugsnag/cuid"));
|
|
310
354
|
var import_cuid2 = require("@paralleldrive/cuid2");
|
|
@@ -409,6 +453,9 @@ function isPrismaValueGenerator(value) {
|
|
|
409
453
|
function isPrismaValueBytes(value) {
|
|
410
454
|
return typeof value === "object" && value !== null && value["prisma__type"] === "bytes";
|
|
411
455
|
}
|
|
456
|
+
function isPrismaValueBigInt(value) {
|
|
457
|
+
return typeof value === "object" && value !== null && value["prisma__type"] === "bigint";
|
|
458
|
+
}
|
|
412
459
|
|
|
413
460
|
// src/interpreter/renderQuery.ts
|
|
414
461
|
function renderQuery(dbQuery, scope, generators) {
|
|
@@ -451,9 +498,10 @@ function evaluateParam(param, scope, generators) {
|
|
|
451
498
|
}
|
|
452
499
|
if (Array.isArray(value)) {
|
|
453
500
|
value = value.map((el) => evaluateParam(el, scope, generators));
|
|
454
|
-
}
|
|
455
|
-
if (isPrismaValueBytes(value)) {
|
|
501
|
+
} else if (isPrismaValueBytes(value)) {
|
|
456
502
|
value = Buffer.from(value.prisma__value, "base64");
|
|
503
|
+
} else if (isPrismaValueBigInt(value)) {
|
|
504
|
+
value = BigInt(value.prisma__value);
|
|
457
505
|
}
|
|
458
506
|
return value;
|
|
459
507
|
}
|
|
@@ -547,6 +595,7 @@ function doesRequireEvaluation(param) {
|
|
|
547
595
|
}
|
|
548
596
|
|
|
549
597
|
// src/interpreter/serializeSql.ts
|
|
598
|
+
var import_driver_adapter_utils2 = require("@prisma/driver-adapter-utils");
|
|
550
599
|
function serializeSql(resultSet) {
|
|
551
600
|
return resultSet.rows.map(
|
|
552
601
|
(row) => row.reduce((acc, value, index) => {
|
|
@@ -567,6 +616,85 @@ function serializeSql(resultSet) {
|
|
|
567
616
|
}, {})
|
|
568
617
|
);
|
|
569
618
|
}
|
|
619
|
+
function serializeRawSql(resultSet) {
|
|
620
|
+
return {
|
|
621
|
+
columns: resultSet.columnNames,
|
|
622
|
+
types: resultSet.columnTypes.map((type) => serializeColumnType(type)),
|
|
623
|
+
rows: resultSet.rows
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
function serializeColumnType(columnType) {
|
|
627
|
+
switch (columnType) {
|
|
628
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Int32:
|
|
629
|
+
return "int";
|
|
630
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Int64:
|
|
631
|
+
return "bigint";
|
|
632
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Float:
|
|
633
|
+
return "float";
|
|
634
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Double:
|
|
635
|
+
return "double";
|
|
636
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Text:
|
|
637
|
+
return "string";
|
|
638
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Enum:
|
|
639
|
+
return "enum";
|
|
640
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Bytes:
|
|
641
|
+
return "bytes";
|
|
642
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Boolean:
|
|
643
|
+
return "bool";
|
|
644
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Character:
|
|
645
|
+
return "char";
|
|
646
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Numeric:
|
|
647
|
+
return "decimal";
|
|
648
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Json:
|
|
649
|
+
return "json";
|
|
650
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Uuid:
|
|
651
|
+
return "uuid";
|
|
652
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.DateTime:
|
|
653
|
+
return "datetime";
|
|
654
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Date:
|
|
655
|
+
return "date";
|
|
656
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Time:
|
|
657
|
+
return "time";
|
|
658
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Int32Array:
|
|
659
|
+
return "int-array";
|
|
660
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Int64Array:
|
|
661
|
+
return "bigint-array";
|
|
662
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.FloatArray:
|
|
663
|
+
return "float-array";
|
|
664
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.DoubleArray:
|
|
665
|
+
return "double-array";
|
|
666
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.TextArray:
|
|
667
|
+
return "string-array";
|
|
668
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.EnumArray:
|
|
669
|
+
return "string-array";
|
|
670
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.BytesArray:
|
|
671
|
+
return "bytes-array";
|
|
672
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.BooleanArray:
|
|
673
|
+
return "bool-array";
|
|
674
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.CharacterArray:
|
|
675
|
+
return "char-array";
|
|
676
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.NumericArray:
|
|
677
|
+
return "decimal-array";
|
|
678
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.JsonArray:
|
|
679
|
+
return "json-array";
|
|
680
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.UuidArray:
|
|
681
|
+
return "uuid-array";
|
|
682
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.DateTimeArray:
|
|
683
|
+
return "datetime-array";
|
|
684
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.DateArray:
|
|
685
|
+
return "date-array";
|
|
686
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.TimeArray:
|
|
687
|
+
return "time-array";
|
|
688
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.UnknownNumber:
|
|
689
|
+
return "unknown";
|
|
690
|
+
/// The following PlanetScale type IDs are mapped into Set:
|
|
691
|
+
/// - SET (SET) -> e.g. `"foo,bar"` (String-encoded, comma-separated)
|
|
692
|
+
case import_driver_adapter_utils2.ColumnTypeEnum.Set:
|
|
693
|
+
return "string";
|
|
694
|
+
default:
|
|
695
|
+
assertNever(columnType, `Unexpected column type: ${columnType}`);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
570
698
|
|
|
571
699
|
// src/interpreter/validation.ts
|
|
572
700
|
function performValidation(data, rules, error) {
|
|
@@ -594,6 +722,8 @@ function doesSatisfyRule(data, rule) {
|
|
|
594
722
|
return rule.args !== 0;
|
|
595
723
|
}
|
|
596
724
|
return rule.args !== 1;
|
|
725
|
+
case "affectedRowCountEq":
|
|
726
|
+
return data === rule.args;
|
|
597
727
|
case "never":
|
|
598
728
|
return false;
|
|
599
729
|
default:
|
|
@@ -611,7 +741,9 @@ function renderMessage(data, error) {
|
|
|
611
741
|
return `An operation failed because it depends on one or more records that were required but not found. No '${error.context.model}' record${hint} was found for ${error.context.operation} on ${error.context.relationType} relation '${error.context.relation}'.`;
|
|
612
742
|
}
|
|
613
743
|
case "INCOMPLETE_CONNECT_INPUT":
|
|
614
|
-
return `An operation failed because it depends on one or more records that were required but not found. Expected ${error.context.expectedRows} records to be connected, found only ${Array.isArray(data) ? data.length :
|
|
744
|
+
return `An operation failed because it depends on one or more records that were required but not found. Expected ${error.context.expectedRows} records to be connected, found only ${Array.isArray(data) ? data.length : data}.`;
|
|
745
|
+
case "INCOMPLETE_CONNECT_OUTPUT":
|
|
746
|
+
return `The required connected records were not found. Expected ${error.context.expectedRows} records to be connected after connect operation on ${error.context.relationType} relation '${error.context.relation}', found ${Array.isArray(data) ? data.length : data}.`;
|
|
615
747
|
case "RECORDS_NOT_CONNECTED":
|
|
616
748
|
return `The records for relation \`${error.context.relation}\` between the \`${error.context.parent}\` and \`${error.context.child}\` models are not connected.`;
|
|
617
749
|
default:
|
|
@@ -624,6 +756,8 @@ function getErrorCode2(error) {
|
|
|
624
756
|
return "P2014";
|
|
625
757
|
case "RECORDS_NOT_CONNECTED":
|
|
626
758
|
return "P2017";
|
|
759
|
+
case "INCOMPLETE_CONNECT_OUTPUT":
|
|
760
|
+
return "P2018";
|
|
627
761
|
case "MISSING_RECORD":
|
|
628
762
|
case "MISSING_RELATED_RECORD":
|
|
629
763
|
case "INCOMPLETE_CONNECT_INPUT":
|
|
@@ -641,12 +775,21 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
641
775
|
#generators = new GeneratorRegistry();
|
|
642
776
|
#tracingHelper;
|
|
643
777
|
#serializer;
|
|
644
|
-
|
|
778
|
+
#rawSerializer;
|
|
779
|
+
constructor({
|
|
780
|
+
transactionManager,
|
|
781
|
+
placeholderValues,
|
|
782
|
+
onQuery,
|
|
783
|
+
tracingHelper,
|
|
784
|
+
serializer,
|
|
785
|
+
rawSerializer
|
|
786
|
+
}) {
|
|
645
787
|
this.#transactionManager = transactionManager;
|
|
646
788
|
this.#placeholderValues = placeholderValues;
|
|
647
789
|
this.#onQuery = onQuery;
|
|
648
790
|
this.#tracingHelper = tracingHelper;
|
|
649
791
|
this.#serializer = serializer;
|
|
792
|
+
this.#rawSerializer = rawSerializer ?? serializer;
|
|
650
793
|
}
|
|
651
794
|
static forSql(options) {
|
|
652
795
|
return new _QueryInterpreter({
|
|
@@ -654,7 +797,8 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
654
797
|
placeholderValues: options.placeholderValues,
|
|
655
798
|
onQuery: options.onQuery,
|
|
656
799
|
tracingHelper: options.tracingHelper,
|
|
657
|
-
serializer: serializeSql
|
|
800
|
+
serializer: serializeSql,
|
|
801
|
+
rawSerializer: serializeRawSql
|
|
658
802
|
});
|
|
659
803
|
}
|
|
660
804
|
async run(queryPlan, queryable) {
|
|
@@ -665,8 +809,11 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
665
809
|
async interpretNode(node, queryable, scope, generators) {
|
|
666
810
|
switch (node.type) {
|
|
667
811
|
case "seq": {
|
|
668
|
-
|
|
669
|
-
|
|
812
|
+
let result;
|
|
813
|
+
for (const arg of node.args) {
|
|
814
|
+
result = await this.interpretNode(arg, queryable, scope, generators);
|
|
815
|
+
}
|
|
816
|
+
return result;
|
|
670
817
|
}
|
|
671
818
|
case "get": {
|
|
672
819
|
return scope[node.args.name];
|
|
@@ -689,11 +836,11 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
689
836
|
}
|
|
690
837
|
case "concat": {
|
|
691
838
|
const parts = await Promise.all(node.args.map((arg) => this.interpretNode(arg, queryable, scope, generators)));
|
|
692
|
-
return parts.reduce((acc, part) => acc.concat(asList(part)), []);
|
|
839
|
+
return parts.length > 0 ? parts.reduce((acc, part) => acc.concat(asList(part)), []) : [];
|
|
693
840
|
}
|
|
694
841
|
case "sum": {
|
|
695
842
|
const parts = await Promise.all(node.args.map((arg) => this.interpretNode(arg, queryable, scope, generators)));
|
|
696
|
-
return parts.reduce((acc, part) => asNumber(acc) + asNumber(part));
|
|
843
|
+
return parts.length > 0 ? parts.reduce((acc, part) => asNumber(acc) + asNumber(part)) : 0;
|
|
697
844
|
}
|
|
698
845
|
case "execute": {
|
|
699
846
|
const query = renderQuery(node.args, scope, generators);
|
|
@@ -704,7 +851,11 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
704
851
|
case "query": {
|
|
705
852
|
const query = renderQuery(node.args, scope, generators);
|
|
706
853
|
return this.#withQueryEvent(query, queryable, async () => {
|
|
707
|
-
|
|
854
|
+
if (node.args.type === "rawSql") {
|
|
855
|
+
return this.#rawSerializer(await queryable.queryRaw(query));
|
|
856
|
+
} else {
|
|
857
|
+
return this.#serializer(await queryable.queryRaw(query));
|
|
858
|
+
}
|
|
708
859
|
});
|
|
709
860
|
}
|
|
710
861
|
case "reverse": {
|
|
@@ -734,6 +885,9 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
734
885
|
}
|
|
735
886
|
case "join": {
|
|
736
887
|
const parent = await this.interpretNode(node.args.parent, queryable, scope, generators);
|
|
888
|
+
if (parent === null) {
|
|
889
|
+
return null;
|
|
890
|
+
}
|
|
737
891
|
const children = await Promise.all(
|
|
738
892
|
node.args.children.map(async (joinExpr) => ({
|
|
739
893
|
joinExpr,
|
|
@@ -790,6 +944,38 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
790
944
|
const toSet = new Set(asList(to));
|
|
791
945
|
return asList(from).filter((item) => !toSet.has(item));
|
|
792
946
|
}
|
|
947
|
+
case "distinctBy": {
|
|
948
|
+
const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
949
|
+
const seen = /* @__PURE__ */ new Set();
|
|
950
|
+
const result = [];
|
|
951
|
+
for (const item of asList(value)) {
|
|
952
|
+
const key = getRecordKey(item, node.args.fields);
|
|
953
|
+
if (!seen.has(key)) {
|
|
954
|
+
seen.add(key);
|
|
955
|
+
result.push(item);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return result;
|
|
959
|
+
}
|
|
960
|
+
case "paginate": {
|
|
961
|
+
const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
962
|
+
const list = asList(value);
|
|
963
|
+
const linkingFields = node.args.pagination.linkingFields;
|
|
964
|
+
if (linkingFields !== null) {
|
|
965
|
+
const groupedByParent = /* @__PURE__ */ new Map();
|
|
966
|
+
for (const item of list) {
|
|
967
|
+
const parentKey = getRecordKey(item, linkingFields);
|
|
968
|
+
if (!groupedByParent.has(parentKey)) {
|
|
969
|
+
groupedByParent.set(parentKey, []);
|
|
970
|
+
}
|
|
971
|
+
groupedByParent.get(parentKey).push(item);
|
|
972
|
+
}
|
|
973
|
+
const groupList = Array.from(groupedByParent.entries());
|
|
974
|
+
groupList.sort(([aId], [bId]) => aId < bId ? -1 : aId > bId ? 1 : 0);
|
|
975
|
+
return groupList.flatMap(([, elems]) => paginate(elems, node.args.pagination));
|
|
976
|
+
}
|
|
977
|
+
return paginate(list, node.args.pagination);
|
|
978
|
+
}
|
|
793
979
|
default:
|
|
794
980
|
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
795
981
|
}
|
|
@@ -861,7 +1047,12 @@ function attachChildrenToParent(parentRecord, children) {
|
|
|
861
1047
|
}
|
|
862
1048
|
function filterChildRecords(records, parentRecord, joinExpr) {
|
|
863
1049
|
if (Array.isArray(records)) {
|
|
864
|
-
|
|
1050
|
+
const filtered = records.filter((record) => childRecordMatchesParent(asRecord(record), parentRecord, joinExpr));
|
|
1051
|
+
if (joinExpr.isRelationUnique) {
|
|
1052
|
+
return filtered.length > 0 ? filtered[0] : null;
|
|
1053
|
+
} else {
|
|
1054
|
+
return filtered;
|
|
1055
|
+
}
|
|
865
1056
|
} else if (records === null) {
|
|
866
1057
|
return null;
|
|
867
1058
|
} else {
|
|
@@ -877,6 +1068,18 @@ function childRecordMatchesParent(childRecord, parentRecord, joinExpr) {
|
|
|
877
1068
|
}
|
|
878
1069
|
return true;
|
|
879
1070
|
}
|
|
1071
|
+
function paginate(list, { cursor, skip, take }) {
|
|
1072
|
+
const cursorIndex = cursor !== null ? list.findIndex((item) => doKeysMatch(item, cursor)) : 0;
|
|
1073
|
+
if (cursorIndex === -1) {
|
|
1074
|
+
return [];
|
|
1075
|
+
}
|
|
1076
|
+
const start = cursorIndex + (skip ?? 0);
|
|
1077
|
+
const end = take !== null ? start + take : list.length;
|
|
1078
|
+
return list.slice(start, end);
|
|
1079
|
+
}
|
|
1080
|
+
function getRecordKey(record, fields) {
|
|
1081
|
+
return JSON.stringify(fields.map((field) => record[field]));
|
|
1082
|
+
}
|
|
880
1083
|
|
|
881
1084
|
// src/transactionManager/TransactionManager.ts
|
|
882
1085
|
var import_debug = require("@prisma/debug");
|
|
@@ -891,12 +1094,11 @@ async function randomUUID() {
|
|
|
891
1094
|
}
|
|
892
1095
|
|
|
893
1096
|
// src/transactionManager/TransactionManagerErrors.ts
|
|
894
|
-
var TransactionManagerError = class extends
|
|
1097
|
+
var TransactionManagerError = class extends UserFacingError {
|
|
1098
|
+
name = "TransactionManagerError";
|
|
895
1099
|
constructor(message, meta) {
|
|
896
|
-
super("Transaction API error: " + message);
|
|
897
|
-
this.meta = meta;
|
|
1100
|
+
super("Transaction API error: " + message, "P2028", meta);
|
|
898
1101
|
}
|
|
899
|
-
code = "P2028";
|
|
900
1102
|
};
|
|
901
1103
|
var TransactionNotFoundError = class extends TransactionManagerError {
|
|
902
1104
|
constructor() {
|
|
@@ -907,12 +1109,12 @@ var TransactionNotFoundError = class extends TransactionManagerError {
|
|
|
907
1109
|
};
|
|
908
1110
|
var TransactionClosedError = class extends TransactionManagerError {
|
|
909
1111
|
constructor(operation) {
|
|
910
|
-
super(`Transaction already closed: A ${operation} cannot be executed on a committed transaction
|
|
1112
|
+
super(`Transaction already closed: A ${operation} cannot be executed on a committed transaction.`);
|
|
911
1113
|
}
|
|
912
1114
|
};
|
|
913
1115
|
var TransactionRolledBackError = class extends TransactionManagerError {
|
|
914
1116
|
constructor(operation) {
|
|
915
|
-
super(`Transaction already closed: A ${operation} cannot be executed on a transaction that was rolled back
|
|
1117
|
+
super(`Transaction already closed: A ${operation} cannot be executed on a transaction that was rolled back.`);
|
|
916
1118
|
}
|
|
917
1119
|
};
|
|
918
1120
|
var TransactionStartTimeoutError = class extends TransactionManagerError {
|
|
@@ -1095,10 +1297,14 @@ var TransactionManager = class {
|
|
|
1095
1297
|
};
|
|
1096
1298
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1097
1299
|
0 && (module.exports = {
|
|
1300
|
+
DataMapperError,
|
|
1098
1301
|
QueryInterpreter,
|
|
1099
1302
|
TransactionManager,
|
|
1100
1303
|
TransactionManagerError,
|
|
1101
1304
|
UserFacingError,
|
|
1305
|
+
doKeysMatch,
|
|
1306
|
+
isDeepStrictEqual,
|
|
1307
|
+
isPrismaValueBigInt,
|
|
1102
1308
|
isPrismaValueBytes,
|
|
1103
1309
|
isPrismaValueGenerator,
|
|
1104
1310
|
isPrismaValuePlaceholder,
|