@prisma/client-engine-runtime 6.9.0-dev.1 → 6.9.0-dev.11
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 +20 -0
- package/dist/index.d.mts +30 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +183 -99
- package/dist/index.mjs +181 -99
- package/dist/interpreter/DataMapper.d.ts +3 -0
- package/dist/utils.d.ts +4 -0
- package/package.json +3 -3
package/dist/QueryPlan.d.ts
CHANGED
|
@@ -47,6 +47,7 @@ export type PrismaValueType = {
|
|
|
47
47
|
export type ResultNode = {
|
|
48
48
|
type: 'Object';
|
|
49
49
|
fields: Record<string, ResultNode>;
|
|
50
|
+
flattened: boolean;
|
|
50
51
|
} | {
|
|
51
52
|
type: 'Value';
|
|
52
53
|
dbName: string;
|
|
@@ -84,6 +85,7 @@ export type JoinExpression = {
|
|
|
84
85
|
child: QueryPlanNode;
|
|
85
86
|
on: [left: string, right: string][];
|
|
86
87
|
parentField: string;
|
|
88
|
+
isRelationUnique: boolean;
|
|
87
89
|
};
|
|
88
90
|
export type QueryPlanNode = {
|
|
89
91
|
type: 'seq';
|
|
@@ -168,6 +170,24 @@ export type QueryPlanNode = {
|
|
|
168
170
|
from: QueryPlanNode;
|
|
169
171
|
to: QueryPlanNode;
|
|
170
172
|
};
|
|
173
|
+
} | {
|
|
174
|
+
type: 'distinctBy';
|
|
175
|
+
args: {
|
|
176
|
+
expr: QueryPlanNode;
|
|
177
|
+
fields: string[];
|
|
178
|
+
};
|
|
179
|
+
} | {
|
|
180
|
+
type: 'paginate';
|
|
181
|
+
args: {
|
|
182
|
+
expr: QueryPlanNode;
|
|
183
|
+
pagination: Pagination;
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
export type Pagination = {
|
|
187
|
+
cursor: Record<string, PrismaValue> | null;
|
|
188
|
+
take: number | null;
|
|
189
|
+
skip: number | null;
|
|
190
|
+
linkingFields: string[] | null;
|
|
171
191
|
};
|
|
172
192
|
export type DataRule = {
|
|
173
193
|
type: 'rowCountEq';
|
package/dist/index.d.mts
CHANGED
|
@@ -7,6 +7,10 @@ import { SqlQueryable } from '@prisma/driver-adapter-utils';
|
|
|
7
7
|
import { SqlResultSet } from '@prisma/driver-adapter-utils';
|
|
8
8
|
import { Transaction } from '@prisma/driver-adapter-utils';
|
|
9
9
|
|
|
10
|
+
export declare class DataMapperError extends Error {
|
|
11
|
+
name: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
export declare type DataRule = {
|
|
11
15
|
type: 'rowCountEq';
|
|
12
16
|
args: number;
|
|
@@ -32,6 +36,11 @@ export declare type Fragment = {
|
|
|
32
36
|
type: 'parameterTupleList';
|
|
33
37
|
};
|
|
34
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Checks if two objects are deeply equal, recursively checking all properties for strict equality.
|
|
41
|
+
*/
|
|
42
|
+
export declare function isDeepStrictEqual(a: unknown, b: unknown): boolean;
|
|
43
|
+
|
|
35
44
|
export declare function isPrismaValueBytes(value: unknown): value is PrismaValueBytes;
|
|
36
45
|
|
|
37
46
|
export declare function isPrismaValueGenerator(value: unknown): value is PrismaValueGenerator;
|
|
@@ -42,10 +51,18 @@ export declare type JoinExpression = {
|
|
|
42
51
|
child: QueryPlanNode;
|
|
43
52
|
on: [left: string, right: string][];
|
|
44
53
|
parentField: string;
|
|
54
|
+
isRelationUnique: boolean;
|
|
45
55
|
};
|
|
46
56
|
|
|
47
57
|
export declare const noopTracingHelper: TracingHelper;
|
|
48
58
|
|
|
59
|
+
export declare type Pagination = {
|
|
60
|
+
cursor: Record<string, PrismaValue> | null;
|
|
61
|
+
take: number | null;
|
|
62
|
+
skip: number | null;
|
|
63
|
+
linkingFields: string[] | null;
|
|
64
|
+
};
|
|
65
|
+
|
|
49
66
|
export declare interface PlaceholderFormat {
|
|
50
67
|
prefix: string;
|
|
51
68
|
hasNumbering: boolean;
|
|
@@ -233,11 +250,24 @@ export declare type QueryPlanNode = {
|
|
|
233
250
|
from: QueryPlanNode;
|
|
234
251
|
to: QueryPlanNode;
|
|
235
252
|
};
|
|
253
|
+
} | {
|
|
254
|
+
type: 'distinctBy';
|
|
255
|
+
args: {
|
|
256
|
+
expr: QueryPlanNode;
|
|
257
|
+
fields: string[];
|
|
258
|
+
};
|
|
259
|
+
} | {
|
|
260
|
+
type: 'paginate';
|
|
261
|
+
args: {
|
|
262
|
+
expr: QueryPlanNode;
|
|
263
|
+
pagination: Pagination;
|
|
264
|
+
};
|
|
236
265
|
};
|
|
237
266
|
|
|
238
267
|
export declare type ResultNode = {
|
|
239
268
|
type: 'Object';
|
|
240
269
|
fields: Record<string, ResultNode>;
|
|
270
|
+
flattened: boolean;
|
|
241
271
|
} | {
|
|
242
272
|
type: 'Value';
|
|
243
273
|
dbName: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,10 @@ import { SqlQueryable } from '@prisma/driver-adapter-utils';
|
|
|
7
7
|
import { SqlResultSet } from '@prisma/driver-adapter-utils';
|
|
8
8
|
import { Transaction } from '@prisma/driver-adapter-utils';
|
|
9
9
|
|
|
10
|
+
export declare class DataMapperError extends Error {
|
|
11
|
+
name: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
export declare type DataRule = {
|
|
11
15
|
type: 'rowCountEq';
|
|
12
16
|
args: number;
|
|
@@ -32,6 +36,11 @@ export declare type Fragment = {
|
|
|
32
36
|
type: 'parameterTupleList';
|
|
33
37
|
};
|
|
34
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Checks if two objects are deeply equal, recursively checking all properties for strict equality.
|
|
41
|
+
*/
|
|
42
|
+
export declare function isDeepStrictEqual(a: unknown, b: unknown): boolean;
|
|
43
|
+
|
|
35
44
|
export declare function isPrismaValueBytes(value: unknown): value is PrismaValueBytes;
|
|
36
45
|
|
|
37
46
|
export declare function isPrismaValueGenerator(value: unknown): value is PrismaValueGenerator;
|
|
@@ -42,10 +51,18 @@ export declare type JoinExpression = {
|
|
|
42
51
|
child: QueryPlanNode;
|
|
43
52
|
on: [left: string, right: string][];
|
|
44
53
|
parentField: string;
|
|
54
|
+
isRelationUnique: boolean;
|
|
45
55
|
};
|
|
46
56
|
|
|
47
57
|
export declare const noopTracingHelper: TracingHelper;
|
|
48
58
|
|
|
59
|
+
export declare type Pagination = {
|
|
60
|
+
cursor: Record<string, PrismaValue> | null;
|
|
61
|
+
take: number | null;
|
|
62
|
+
skip: number | null;
|
|
63
|
+
linkingFields: string[] | null;
|
|
64
|
+
};
|
|
65
|
+
|
|
49
66
|
export declare interface PlaceholderFormat {
|
|
50
67
|
prefix: string;
|
|
51
68
|
hasNumbering: boolean;
|
|
@@ -233,11 +250,24 @@ export declare type QueryPlanNode = {
|
|
|
233
250
|
from: QueryPlanNode;
|
|
234
251
|
to: QueryPlanNode;
|
|
235
252
|
};
|
|
253
|
+
} | {
|
|
254
|
+
type: 'distinctBy';
|
|
255
|
+
args: {
|
|
256
|
+
expr: QueryPlanNode;
|
|
257
|
+
fields: string[];
|
|
258
|
+
};
|
|
259
|
+
} | {
|
|
260
|
+
type: 'paginate';
|
|
261
|
+
args: {
|
|
262
|
+
expr: QueryPlanNode;
|
|
263
|
+
pagination: Pagination;
|
|
264
|
+
};
|
|
236
265
|
};
|
|
237
266
|
|
|
238
267
|
export declare type ResultNode = {
|
|
239
268
|
type: 'Object';
|
|
240
269
|
fields: Record<string, ResultNode>;
|
|
270
|
+
flattened: boolean;
|
|
241
271
|
} | {
|
|
242
272
|
type: 'Value';
|
|
243
273
|
dbName: string;
|
package/dist/index.js
CHANGED
|
@@ -30,10 +30,12 @@ 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
|
+
isDeepStrictEqual: () => isDeepStrictEqual,
|
|
37
39
|
isPrismaValueBytes: () => isPrismaValueBytes,
|
|
38
40
|
isPrismaValueGenerator: () => isPrismaValueGenerator,
|
|
39
41
|
isPrismaValuePlaceholder: () => isPrismaValuePlaceholder,
|
|
@@ -41,13 +43,127 @@ __export(index_exports, {
|
|
|
41
43
|
});
|
|
42
44
|
module.exports = __toCommonJS(index_exports);
|
|
43
45
|
|
|
44
|
-
// src/interpreter/
|
|
45
|
-
var
|
|
46
|
+
// src/interpreter/DataMapper.ts
|
|
47
|
+
var import_decimal = __toESM(require("decimal.js"));
|
|
46
48
|
|
|
47
49
|
// src/utils.ts
|
|
48
50
|
function assertNever(_, message) {
|
|
49
51
|
throw new Error(message);
|
|
50
52
|
}
|
|
53
|
+
function isDeepStrictEqual(a, b) {
|
|
54
|
+
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]));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/interpreter/DataMapper.ts
|
|
58
|
+
var DataMapperError = class extends Error {
|
|
59
|
+
name = "DataMapperError";
|
|
60
|
+
};
|
|
61
|
+
function applyDataMap(data, structure) {
|
|
62
|
+
switch (structure.type) {
|
|
63
|
+
case "Object":
|
|
64
|
+
return mapArrayOrObject(data, structure.fields);
|
|
65
|
+
case "Value":
|
|
66
|
+
return mapValue(data, structure.resultType);
|
|
67
|
+
default:
|
|
68
|
+
assertNever(structure, `Invalid data mapping type: '${structure.type}'`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function mapArrayOrObject(data, fields) {
|
|
72
|
+
if (data === null) return null;
|
|
73
|
+
if (Array.isArray(data)) {
|
|
74
|
+
const rows = data;
|
|
75
|
+
return rows.map((row) => mapObject(row, fields));
|
|
76
|
+
}
|
|
77
|
+
if (typeof data === "object") {
|
|
78
|
+
const row = data;
|
|
79
|
+
return mapObject(row, fields);
|
|
80
|
+
}
|
|
81
|
+
if (typeof data === "string") {
|
|
82
|
+
let decodedData;
|
|
83
|
+
try {
|
|
84
|
+
decodedData = JSON.parse(data);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
throw new DataMapperError(`Expected an array or object, got a string that is not valid JSON`, {
|
|
87
|
+
cause: error
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return mapArrayOrObject(decodedData, fields);
|
|
91
|
+
}
|
|
92
|
+
throw new DataMapperError(`Expected an array or an object, got: ${typeof data}`);
|
|
93
|
+
}
|
|
94
|
+
function mapObject(data, fields) {
|
|
95
|
+
if (typeof data !== "object") {
|
|
96
|
+
throw new DataMapperError(`Expected an object, but got '${typeof data}'`);
|
|
97
|
+
}
|
|
98
|
+
const result = {};
|
|
99
|
+
for (const [name, node] of Object.entries(fields)) {
|
|
100
|
+
switch (node.type) {
|
|
101
|
+
case "Object": {
|
|
102
|
+
if (!node.flattened && !Object.hasOwn(data, name)) {
|
|
103
|
+
throw new DataMapperError(
|
|
104
|
+
`Missing data field (Object): '${name}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
const target = node.flattened ? data : data[name];
|
|
108
|
+
result[name] = mapArrayOrObject(target, node.fields);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
case "Value":
|
|
112
|
+
{
|
|
113
|
+
const dbName = node.dbName;
|
|
114
|
+
if (Object.hasOwn(data, dbName)) {
|
|
115
|
+
result[name] = mapValue(data[dbName], node.resultType);
|
|
116
|
+
} else {
|
|
117
|
+
throw new DataMapperError(
|
|
118
|
+
`Missing data field (Value): '${dbName}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
break;
|
|
123
|
+
default:
|
|
124
|
+
assertNever(node, `DataMapper: Invalid data mapping node type: '${node.type}'`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
function mapValue(value, resultType) {
|
|
130
|
+
if (value === null) return null;
|
|
131
|
+
switch (resultType.type) {
|
|
132
|
+
case "Any":
|
|
133
|
+
return value;
|
|
134
|
+
case "String":
|
|
135
|
+
return typeof value === "string" ? value : `${value}`;
|
|
136
|
+
case "Int":
|
|
137
|
+
return typeof value === "number" ? value : parseInt(`${value}`, 10);
|
|
138
|
+
case "BigInt":
|
|
139
|
+
return typeof value === "bigint" ? value : BigInt(`${value}`);
|
|
140
|
+
case "Float":
|
|
141
|
+
return typeof value === "number" ? value : parseFloat(`${value}`);
|
|
142
|
+
case "Boolean":
|
|
143
|
+
return typeof value === "boolean" ? value : value !== "0";
|
|
144
|
+
case "Decimal":
|
|
145
|
+
return typeof value === "number" ? new import_decimal.default(value) : new import_decimal.default(`${value}`);
|
|
146
|
+
case "Date":
|
|
147
|
+
return value instanceof Date ? value : /* @__PURE__ */ new Date(`${value}`);
|
|
148
|
+
case "Array": {
|
|
149
|
+
const values = value;
|
|
150
|
+
return values.map((v) => mapValue(v, resultType.inner));
|
|
151
|
+
}
|
|
152
|
+
case "Object":
|
|
153
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
154
|
+
case "Bytes": {
|
|
155
|
+
if (!Array.isArray(value)) {
|
|
156
|
+
throw new DataMapperError(`Bytes data is invalid, got: ${typeof value}`);
|
|
157
|
+
}
|
|
158
|
+
return new Uint8Array(value);
|
|
159
|
+
}
|
|
160
|
+
default:
|
|
161
|
+
assertNever(resultType, `DataMapper: Unknown result type: ${resultType.type}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/interpreter/QueryInterpreter.ts
|
|
166
|
+
var import_api = require("@opentelemetry/api");
|
|
51
167
|
|
|
52
168
|
// src/tracing.ts
|
|
53
169
|
var noopTracingHelper = {
|
|
@@ -211,100 +327,6 @@ function renderConstraint(constraint) {
|
|
|
211
327
|
return "(not available)";
|
|
212
328
|
}
|
|
213
329
|
|
|
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
330
|
// src/interpreter/generators.ts
|
|
309
331
|
var import_cuid = __toESM(require("@bugsnag/cuid"));
|
|
310
332
|
var import_cuid2 = require("@paralleldrive/cuid2");
|
|
@@ -665,8 +687,11 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
665
687
|
async interpretNode(node, queryable, scope, generators) {
|
|
666
688
|
switch (node.type) {
|
|
667
689
|
case "seq": {
|
|
668
|
-
|
|
669
|
-
|
|
690
|
+
let result;
|
|
691
|
+
for (const arg of node.args) {
|
|
692
|
+
result = await this.interpretNode(arg, queryable, scope, generators);
|
|
693
|
+
}
|
|
694
|
+
return result;
|
|
670
695
|
}
|
|
671
696
|
case "get": {
|
|
672
697
|
return scope[node.args.name];
|
|
@@ -790,6 +815,38 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
790
815
|
const toSet = new Set(asList(to));
|
|
791
816
|
return asList(from).filter((item) => !toSet.has(item));
|
|
792
817
|
}
|
|
818
|
+
case "distinctBy": {
|
|
819
|
+
const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
820
|
+
const seen = /* @__PURE__ */ new Set();
|
|
821
|
+
const result = [];
|
|
822
|
+
for (const item of asList(value)) {
|
|
823
|
+
const key = getRecordKey(item, node.args.fields);
|
|
824
|
+
if (!seen.has(key)) {
|
|
825
|
+
seen.add(key);
|
|
826
|
+
result.push(item);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return result;
|
|
830
|
+
}
|
|
831
|
+
case "paginate": {
|
|
832
|
+
const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
833
|
+
const list = asList(value);
|
|
834
|
+
const linkingFields = node.args.pagination.linkingFields;
|
|
835
|
+
if (linkingFields !== null) {
|
|
836
|
+
const groupedByParent = /* @__PURE__ */ new Map();
|
|
837
|
+
for (const item of list) {
|
|
838
|
+
const parentKey = getRecordKey(item, linkingFields);
|
|
839
|
+
if (!groupedByParent.has(parentKey)) {
|
|
840
|
+
groupedByParent.set(parentKey, []);
|
|
841
|
+
}
|
|
842
|
+
groupedByParent.get(parentKey).push(item);
|
|
843
|
+
}
|
|
844
|
+
const groupList = Array.from(groupedByParent.entries());
|
|
845
|
+
groupList.sort(([aId], [bId]) => aId < bId ? -1 : aId > bId ? 1 : 0);
|
|
846
|
+
return groupList.flatMap(([, elems]) => paginate(elems, node.args.pagination));
|
|
847
|
+
}
|
|
848
|
+
return paginate(list, node.args.pagination);
|
|
849
|
+
}
|
|
793
850
|
default:
|
|
794
851
|
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
795
852
|
}
|
|
@@ -861,7 +918,12 @@ function attachChildrenToParent(parentRecord, children) {
|
|
|
861
918
|
}
|
|
862
919
|
function filterChildRecords(records, parentRecord, joinExpr) {
|
|
863
920
|
if (Array.isArray(records)) {
|
|
864
|
-
|
|
921
|
+
const filtered = records.filter((record) => childRecordMatchesParent(asRecord(record), parentRecord, joinExpr));
|
|
922
|
+
if (joinExpr.isRelationUnique) {
|
|
923
|
+
return filtered.length > 0 ? filtered[0] : null;
|
|
924
|
+
} else {
|
|
925
|
+
return filtered;
|
|
926
|
+
}
|
|
865
927
|
} else if (records === null) {
|
|
866
928
|
return null;
|
|
867
929
|
} else {
|
|
@@ -877,6 +939,26 @@ function childRecordMatchesParent(childRecord, parentRecord, joinExpr) {
|
|
|
877
939
|
}
|
|
878
940
|
return true;
|
|
879
941
|
}
|
|
942
|
+
function paginate(list, { cursor, skip, take }) {
|
|
943
|
+
const cursorIndex = cursor !== null ? list.findIndex((item) => doesMatchCursor(item, cursor)) : 0;
|
|
944
|
+
if (cursorIndex === -1) {
|
|
945
|
+
return [];
|
|
946
|
+
}
|
|
947
|
+
const start = cursorIndex + (skip ?? 0);
|
|
948
|
+
const end = take !== null ? start + take : list.length;
|
|
949
|
+
return list.slice(start, end);
|
|
950
|
+
}
|
|
951
|
+
function getRecordKey(record, fields) {
|
|
952
|
+
return JSON.stringify(fields.map((field) => record[field]));
|
|
953
|
+
}
|
|
954
|
+
function doesMatchCursor(item, cursor) {
|
|
955
|
+
return Object.keys(cursor).every((key) => {
|
|
956
|
+
if (typeof item[key] !== typeof cursor[key] && (typeof item[key] === "number" || typeof cursor[key] === "number")) {
|
|
957
|
+
return `${item[key]}` === `${cursor[key]}`;
|
|
958
|
+
}
|
|
959
|
+
return isDeepStrictEqual(cursor[key], item[key]);
|
|
960
|
+
});
|
|
961
|
+
}
|
|
880
962
|
|
|
881
963
|
// src/transactionManager/TransactionManager.ts
|
|
882
964
|
var import_debug = require("@prisma/debug");
|
|
@@ -1095,10 +1177,12 @@ var TransactionManager = class {
|
|
|
1095
1177
|
};
|
|
1096
1178
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1097
1179
|
0 && (module.exports = {
|
|
1180
|
+
DataMapperError,
|
|
1098
1181
|
QueryInterpreter,
|
|
1099
1182
|
TransactionManager,
|
|
1100
1183
|
TransactionManagerError,
|
|
1101
1184
|
UserFacingError,
|
|
1185
|
+
isDeepStrictEqual,
|
|
1102
1186
|
isPrismaValueBytes,
|
|
1103
1187
|
isPrismaValueGenerator,
|
|
1104
1188
|
isPrismaValuePlaceholder,
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,124 @@
|
|
|
1
|
-
// src/interpreter/
|
|
2
|
-
import
|
|
1
|
+
// src/interpreter/DataMapper.ts
|
|
2
|
+
import Decimal from "decimal.js";
|
|
3
3
|
|
|
4
4
|
// src/utils.ts
|
|
5
5
|
function assertNever(_, message) {
|
|
6
6
|
throw new Error(message);
|
|
7
7
|
}
|
|
8
|
+
function isDeepStrictEqual(a, b) {
|
|
9
|
+
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]));
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/interpreter/DataMapper.ts
|
|
13
|
+
var DataMapperError = class extends Error {
|
|
14
|
+
name = "DataMapperError";
|
|
15
|
+
};
|
|
16
|
+
function applyDataMap(data, structure) {
|
|
17
|
+
switch (structure.type) {
|
|
18
|
+
case "Object":
|
|
19
|
+
return mapArrayOrObject(data, structure.fields);
|
|
20
|
+
case "Value":
|
|
21
|
+
return mapValue(data, structure.resultType);
|
|
22
|
+
default:
|
|
23
|
+
assertNever(structure, `Invalid data mapping type: '${structure.type}'`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function mapArrayOrObject(data, fields) {
|
|
27
|
+
if (data === null) return null;
|
|
28
|
+
if (Array.isArray(data)) {
|
|
29
|
+
const rows = data;
|
|
30
|
+
return rows.map((row) => mapObject(row, fields));
|
|
31
|
+
}
|
|
32
|
+
if (typeof data === "object") {
|
|
33
|
+
const row = data;
|
|
34
|
+
return mapObject(row, fields);
|
|
35
|
+
}
|
|
36
|
+
if (typeof data === "string") {
|
|
37
|
+
let decodedData;
|
|
38
|
+
try {
|
|
39
|
+
decodedData = JSON.parse(data);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
throw new DataMapperError(`Expected an array or object, got a string that is not valid JSON`, {
|
|
42
|
+
cause: error
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return mapArrayOrObject(decodedData, fields);
|
|
46
|
+
}
|
|
47
|
+
throw new DataMapperError(`Expected an array or an object, got: ${typeof data}`);
|
|
48
|
+
}
|
|
49
|
+
function mapObject(data, fields) {
|
|
50
|
+
if (typeof data !== "object") {
|
|
51
|
+
throw new DataMapperError(`Expected an object, but got '${typeof data}'`);
|
|
52
|
+
}
|
|
53
|
+
const result = {};
|
|
54
|
+
for (const [name, node] of Object.entries(fields)) {
|
|
55
|
+
switch (node.type) {
|
|
56
|
+
case "Object": {
|
|
57
|
+
if (!node.flattened && !Object.hasOwn(data, name)) {
|
|
58
|
+
throw new DataMapperError(
|
|
59
|
+
`Missing data field (Object): '${name}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
const target = node.flattened ? data : data[name];
|
|
63
|
+
result[name] = mapArrayOrObject(target, node.fields);
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case "Value":
|
|
67
|
+
{
|
|
68
|
+
const dbName = node.dbName;
|
|
69
|
+
if (Object.hasOwn(data, dbName)) {
|
|
70
|
+
result[name] = mapValue(data[dbName], node.resultType);
|
|
71
|
+
} else {
|
|
72
|
+
throw new DataMapperError(
|
|
73
|
+
`Missing data field (Value): '${dbName}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
assertNever(node, `DataMapper: Invalid data mapping node type: '${node.type}'`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
function mapValue(value, resultType) {
|
|
85
|
+
if (value === null) return null;
|
|
86
|
+
switch (resultType.type) {
|
|
87
|
+
case "Any":
|
|
88
|
+
return value;
|
|
89
|
+
case "String":
|
|
90
|
+
return typeof value === "string" ? value : `${value}`;
|
|
91
|
+
case "Int":
|
|
92
|
+
return typeof value === "number" ? value : parseInt(`${value}`, 10);
|
|
93
|
+
case "BigInt":
|
|
94
|
+
return typeof value === "bigint" ? value : BigInt(`${value}`);
|
|
95
|
+
case "Float":
|
|
96
|
+
return typeof value === "number" ? value : parseFloat(`${value}`);
|
|
97
|
+
case "Boolean":
|
|
98
|
+
return typeof value === "boolean" ? value : value !== "0";
|
|
99
|
+
case "Decimal":
|
|
100
|
+
return typeof value === "number" ? new Decimal(value) : new Decimal(`${value}`);
|
|
101
|
+
case "Date":
|
|
102
|
+
return value instanceof Date ? value : /* @__PURE__ */ new Date(`${value}`);
|
|
103
|
+
case "Array": {
|
|
104
|
+
const values = value;
|
|
105
|
+
return values.map((v) => mapValue(v, resultType.inner));
|
|
106
|
+
}
|
|
107
|
+
case "Object":
|
|
108
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
109
|
+
case "Bytes": {
|
|
110
|
+
if (!Array.isArray(value)) {
|
|
111
|
+
throw new DataMapperError(`Bytes data is invalid, got: ${typeof value}`);
|
|
112
|
+
}
|
|
113
|
+
return new Uint8Array(value);
|
|
114
|
+
}
|
|
115
|
+
default:
|
|
116
|
+
assertNever(resultType, `DataMapper: Unknown result type: ${resultType.type}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/interpreter/QueryInterpreter.ts
|
|
121
|
+
import { SpanKind } from "@opentelemetry/api";
|
|
8
122
|
|
|
9
123
|
// src/tracing.ts
|
|
10
124
|
var noopTracingHelper = {
|
|
@@ -168,100 +282,6 @@ function renderConstraint(constraint) {
|
|
|
168
282
|
return "(not available)";
|
|
169
283
|
}
|
|
170
284
|
|
|
171
|
-
// src/interpreter/DataMapper.ts
|
|
172
|
-
import Decimal from "decimal.js";
|
|
173
|
-
function applyDataMap(data, structure) {
|
|
174
|
-
switch (structure.type) {
|
|
175
|
-
case "Object":
|
|
176
|
-
return mapArrayOrObject(data, structure.fields);
|
|
177
|
-
case "Value":
|
|
178
|
-
return mapValue(data, structure.resultType);
|
|
179
|
-
default:
|
|
180
|
-
assertNever(structure, `Invalid data mapping type: '${structure.type}'`);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
function mapArrayOrObject(data, fields) {
|
|
184
|
-
if (data === null) return null;
|
|
185
|
-
if (Array.isArray(data)) {
|
|
186
|
-
const rows = data;
|
|
187
|
-
return rows.map((row) => mapObject(row, fields));
|
|
188
|
-
}
|
|
189
|
-
if (typeof data === "object") {
|
|
190
|
-
const row = data;
|
|
191
|
-
return mapObject(row, fields);
|
|
192
|
-
}
|
|
193
|
-
throw new Error(`DataMapper: Expected an array or an object, got: ${typeof data}`);
|
|
194
|
-
}
|
|
195
|
-
function mapObject(data, fields) {
|
|
196
|
-
if (typeof data !== "object") {
|
|
197
|
-
throw new Error(`DataMapper: Expected an object, but got '${typeof data}'`);
|
|
198
|
-
}
|
|
199
|
-
const result = {};
|
|
200
|
-
for (const [name, node] of Object.entries(fields)) {
|
|
201
|
-
switch (node.type) {
|
|
202
|
-
case "Object":
|
|
203
|
-
if (Object.hasOwn(data, name)) {
|
|
204
|
-
result[name] = mapArrayOrObject(data[name], node.fields);
|
|
205
|
-
} else {
|
|
206
|
-
throw new Error(
|
|
207
|
-
`DataMapper: Missing data field (Object): '${name}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
208
|
-
);
|
|
209
|
-
}
|
|
210
|
-
break;
|
|
211
|
-
case "Value":
|
|
212
|
-
{
|
|
213
|
-
const dbName = node.dbName;
|
|
214
|
-
if (Object.hasOwn(data, dbName)) {
|
|
215
|
-
result[name] = mapValue(data[dbName], node.resultType);
|
|
216
|
-
} else {
|
|
217
|
-
throw new Error(
|
|
218
|
-
`DataMapper: Missing data field (Value): '${dbName}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
break;
|
|
223
|
-
default:
|
|
224
|
-
assertNever(node, `DataMapper: Invalid data mapping node type: '${node.type}'`);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return result;
|
|
228
|
-
}
|
|
229
|
-
function mapValue(value, resultType) {
|
|
230
|
-
if (value === null) return null;
|
|
231
|
-
switch (resultType.type) {
|
|
232
|
-
case "Any":
|
|
233
|
-
return value;
|
|
234
|
-
case "String":
|
|
235
|
-
return typeof value === "string" ? value : `${value}`;
|
|
236
|
-
case "Int":
|
|
237
|
-
return typeof value === "number" ? value : parseInt(`${value}`, 10);
|
|
238
|
-
case "BigInt":
|
|
239
|
-
return typeof value === "bigint" ? value : BigInt(`${value}`);
|
|
240
|
-
case "Float":
|
|
241
|
-
return typeof value === "number" ? value : parseFloat(`${value}`);
|
|
242
|
-
case "Boolean":
|
|
243
|
-
return typeof value === "boolean" ? value : value !== "0";
|
|
244
|
-
case "Decimal":
|
|
245
|
-
return typeof value === "number" ? new Decimal(value) : new Decimal(`${value}`);
|
|
246
|
-
case "Date":
|
|
247
|
-
return value instanceof Date ? value : /* @__PURE__ */ new Date(`${value}`);
|
|
248
|
-
case "Array": {
|
|
249
|
-
const values = value;
|
|
250
|
-
return values.map((v) => mapValue(v, resultType.inner));
|
|
251
|
-
}
|
|
252
|
-
case "Object":
|
|
253
|
-
return typeof value === "string" ? value : JSON.stringify(value);
|
|
254
|
-
case "Bytes": {
|
|
255
|
-
if (!Array.isArray(value)) {
|
|
256
|
-
throw new Error(`DataMapper: Bytes data is invalid, got: ${typeof value}`);
|
|
257
|
-
}
|
|
258
|
-
return new Uint8Array(value);
|
|
259
|
-
}
|
|
260
|
-
default:
|
|
261
|
-
assertNever(resultType, `DataMapper: Unknown result type: ${resultType.type}`);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
285
|
// src/interpreter/generators.ts
|
|
266
286
|
import cuid1 from "@bugsnag/cuid";
|
|
267
287
|
import { createId as cuid2 } from "@paralleldrive/cuid2";
|
|
@@ -622,8 +642,11 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
622
642
|
async interpretNode(node, queryable, scope, generators) {
|
|
623
643
|
switch (node.type) {
|
|
624
644
|
case "seq": {
|
|
625
|
-
|
|
626
|
-
|
|
645
|
+
let result;
|
|
646
|
+
for (const arg of node.args) {
|
|
647
|
+
result = await this.interpretNode(arg, queryable, scope, generators);
|
|
648
|
+
}
|
|
649
|
+
return result;
|
|
627
650
|
}
|
|
628
651
|
case "get": {
|
|
629
652
|
return scope[node.args.name];
|
|
@@ -747,6 +770,38 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
747
770
|
const toSet = new Set(asList(to));
|
|
748
771
|
return asList(from).filter((item) => !toSet.has(item));
|
|
749
772
|
}
|
|
773
|
+
case "distinctBy": {
|
|
774
|
+
const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
775
|
+
const seen = /* @__PURE__ */ new Set();
|
|
776
|
+
const result = [];
|
|
777
|
+
for (const item of asList(value)) {
|
|
778
|
+
const key = getRecordKey(item, node.args.fields);
|
|
779
|
+
if (!seen.has(key)) {
|
|
780
|
+
seen.add(key);
|
|
781
|
+
result.push(item);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
return result;
|
|
785
|
+
}
|
|
786
|
+
case "paginate": {
|
|
787
|
+
const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
788
|
+
const list = asList(value);
|
|
789
|
+
const linkingFields = node.args.pagination.linkingFields;
|
|
790
|
+
if (linkingFields !== null) {
|
|
791
|
+
const groupedByParent = /* @__PURE__ */ new Map();
|
|
792
|
+
for (const item of list) {
|
|
793
|
+
const parentKey = getRecordKey(item, linkingFields);
|
|
794
|
+
if (!groupedByParent.has(parentKey)) {
|
|
795
|
+
groupedByParent.set(parentKey, []);
|
|
796
|
+
}
|
|
797
|
+
groupedByParent.get(parentKey).push(item);
|
|
798
|
+
}
|
|
799
|
+
const groupList = Array.from(groupedByParent.entries());
|
|
800
|
+
groupList.sort(([aId], [bId]) => aId < bId ? -1 : aId > bId ? 1 : 0);
|
|
801
|
+
return groupList.flatMap(([, elems]) => paginate(elems, node.args.pagination));
|
|
802
|
+
}
|
|
803
|
+
return paginate(list, node.args.pagination);
|
|
804
|
+
}
|
|
750
805
|
default:
|
|
751
806
|
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
752
807
|
}
|
|
@@ -818,7 +873,12 @@ function attachChildrenToParent(parentRecord, children) {
|
|
|
818
873
|
}
|
|
819
874
|
function filterChildRecords(records, parentRecord, joinExpr) {
|
|
820
875
|
if (Array.isArray(records)) {
|
|
821
|
-
|
|
876
|
+
const filtered = records.filter((record) => childRecordMatchesParent(asRecord(record), parentRecord, joinExpr));
|
|
877
|
+
if (joinExpr.isRelationUnique) {
|
|
878
|
+
return filtered.length > 0 ? filtered[0] : null;
|
|
879
|
+
} else {
|
|
880
|
+
return filtered;
|
|
881
|
+
}
|
|
822
882
|
} else if (records === null) {
|
|
823
883
|
return null;
|
|
824
884
|
} else {
|
|
@@ -834,6 +894,26 @@ function childRecordMatchesParent(childRecord, parentRecord, joinExpr) {
|
|
|
834
894
|
}
|
|
835
895
|
return true;
|
|
836
896
|
}
|
|
897
|
+
function paginate(list, { cursor, skip, take }) {
|
|
898
|
+
const cursorIndex = cursor !== null ? list.findIndex((item) => doesMatchCursor(item, cursor)) : 0;
|
|
899
|
+
if (cursorIndex === -1) {
|
|
900
|
+
return [];
|
|
901
|
+
}
|
|
902
|
+
const start = cursorIndex + (skip ?? 0);
|
|
903
|
+
const end = take !== null ? start + take : list.length;
|
|
904
|
+
return list.slice(start, end);
|
|
905
|
+
}
|
|
906
|
+
function getRecordKey(record, fields) {
|
|
907
|
+
return JSON.stringify(fields.map((field) => record[field]));
|
|
908
|
+
}
|
|
909
|
+
function doesMatchCursor(item, cursor) {
|
|
910
|
+
return Object.keys(cursor).every((key) => {
|
|
911
|
+
if (typeof item[key] !== typeof cursor[key] && (typeof item[key] === "number" || typeof cursor[key] === "number")) {
|
|
912
|
+
return `${item[key]}` === `${cursor[key]}`;
|
|
913
|
+
}
|
|
914
|
+
return isDeepStrictEqual(cursor[key], item[key]);
|
|
915
|
+
});
|
|
916
|
+
}
|
|
837
917
|
|
|
838
918
|
// src/transactionManager/TransactionManager.ts
|
|
839
919
|
import { Debug } from "@prisma/debug";
|
|
@@ -1051,10 +1131,12 @@ var TransactionManager = class {
|
|
|
1051
1131
|
}
|
|
1052
1132
|
};
|
|
1053
1133
|
export {
|
|
1134
|
+
DataMapperError,
|
|
1054
1135
|
QueryInterpreter,
|
|
1055
1136
|
TransactionManager,
|
|
1056
1137
|
TransactionManagerError,
|
|
1057
1138
|
UserFacingError,
|
|
1139
|
+
isDeepStrictEqual,
|
|
1058
1140
|
isPrismaValueBytes,
|
|
1059
1141
|
isPrismaValueGenerator,
|
|
1060
1142
|
isPrismaValuePlaceholder,
|
package/dist/utils.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/client-engine-runtime",
|
|
3
|
-
"version": "6.9.0-dev.
|
|
3
|
+
"version": "6.9.0-dev.11",
|
|
4
4
|
"description": "This package is intended for Prisma's internal use",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"nanoid": "5.1.5",
|
|
32
32
|
"ulid": "3.0.0",
|
|
33
33
|
"uuid": "11.1.0",
|
|
34
|
-
"@prisma/debug": "6.9.0-dev.
|
|
35
|
-
"@prisma/driver-adapter-utils": "6.9.0-dev.
|
|
34
|
+
"@prisma/debug": "6.9.0-dev.11",
|
|
35
|
+
"@prisma/driver-adapter-utils": "6.9.0-dev.11"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/jest": "29.5.14",
|