@prisma/client-engine-runtime 6.8.2 → 6.9.0-dev.10

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.
@@ -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
@@ -32,6 +32,11 @@ export declare type Fragment = {
32
32
  type: 'parameterTupleList';
33
33
  };
34
34
 
35
+ /**
36
+ * Checks if two objects are deeply equal, recursively checking all properties for strict equality.
37
+ */
38
+ export declare function isDeepStrictEqual(a: unknown, b: unknown): boolean;
39
+
35
40
  export declare function isPrismaValueBytes(value: unknown): value is PrismaValueBytes;
36
41
 
37
42
  export declare function isPrismaValueGenerator(value: unknown): value is PrismaValueGenerator;
@@ -42,10 +47,18 @@ export declare type JoinExpression = {
42
47
  child: QueryPlanNode;
43
48
  on: [left: string, right: string][];
44
49
  parentField: string;
50
+ isRelationUnique: boolean;
45
51
  };
46
52
 
47
53
  export declare const noopTracingHelper: TracingHelper;
48
54
 
55
+ export declare type Pagination = {
56
+ cursor: Record<string, PrismaValue> | null;
57
+ take: number | null;
58
+ skip: number | null;
59
+ linkingFields: string[] | null;
60
+ };
61
+
49
62
  export declare interface PlaceholderFormat {
50
63
  prefix: string;
51
64
  hasNumbering: boolean;
@@ -233,11 +246,24 @@ export declare type QueryPlanNode = {
233
246
  from: QueryPlanNode;
234
247
  to: QueryPlanNode;
235
248
  };
249
+ } | {
250
+ type: 'distinctBy';
251
+ args: {
252
+ expr: QueryPlanNode;
253
+ fields: string[];
254
+ };
255
+ } | {
256
+ type: 'paginate';
257
+ args: {
258
+ expr: QueryPlanNode;
259
+ pagination: Pagination;
260
+ };
236
261
  };
237
262
 
238
263
  export declare type ResultNode = {
239
264
  type: 'Object';
240
265
  fields: Record<string, ResultNode>;
266
+ flattened: boolean;
241
267
  } | {
242
268
  type: 'Value';
243
269
  dbName: string;
package/dist/index.d.ts CHANGED
@@ -32,6 +32,11 @@ export declare type Fragment = {
32
32
  type: 'parameterTupleList';
33
33
  };
34
34
 
35
+ /**
36
+ * Checks if two objects are deeply equal, recursively checking all properties for strict equality.
37
+ */
38
+ export declare function isDeepStrictEqual(a: unknown, b: unknown): boolean;
39
+
35
40
  export declare function isPrismaValueBytes(value: unknown): value is PrismaValueBytes;
36
41
 
37
42
  export declare function isPrismaValueGenerator(value: unknown): value is PrismaValueGenerator;
@@ -42,10 +47,18 @@ export declare type JoinExpression = {
42
47
  child: QueryPlanNode;
43
48
  on: [left: string, right: string][];
44
49
  parentField: string;
50
+ isRelationUnique: boolean;
45
51
  };
46
52
 
47
53
  export declare const noopTracingHelper: TracingHelper;
48
54
 
55
+ export declare type Pagination = {
56
+ cursor: Record<string, PrismaValue> | null;
57
+ take: number | null;
58
+ skip: number | null;
59
+ linkingFields: string[] | null;
60
+ };
61
+
49
62
  export declare interface PlaceholderFormat {
50
63
  prefix: string;
51
64
  hasNumbering: boolean;
@@ -233,11 +246,24 @@ export declare type QueryPlanNode = {
233
246
  from: QueryPlanNode;
234
247
  to: QueryPlanNode;
235
248
  };
249
+ } | {
250
+ type: 'distinctBy';
251
+ args: {
252
+ expr: QueryPlanNode;
253
+ fields: string[];
254
+ };
255
+ } | {
256
+ type: 'paginate';
257
+ args: {
258
+ expr: QueryPlanNode;
259
+ pagination: Pagination;
260
+ };
236
261
  };
237
262
 
238
263
  export declare type ResultNode = {
239
264
  type: 'Object';
240
265
  fields: Record<string, ResultNode>;
266
+ flattened: boolean;
241
267
  } | {
242
268
  type: 'Value';
243
269
  dbName: string;
package/dist/index.js CHANGED
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  TransactionManager: () => TransactionManager,
35
35
  TransactionManagerError: () => TransactionManagerError,
36
36
  UserFacingError: () => UserFacingError,
37
+ isDeepStrictEqual: () => isDeepStrictEqual,
37
38
  isPrismaValueBytes: () => isPrismaValueBytes,
38
39
  isPrismaValueGenerator: () => isPrismaValueGenerator,
39
40
  isPrismaValuePlaceholder: () => isPrismaValuePlaceholder,
@@ -48,6 +49,9 @@ var import_api = require("@opentelemetry/api");
48
49
  function assertNever(_, message) {
49
50
  throw new Error(message);
50
51
  }
52
+ function isDeepStrictEqual(a, b) {
53
+ 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]));
54
+ }
51
55
 
52
56
  // src/tracing.ts
53
57
  var noopTracingHelper = {
@@ -242,15 +246,16 @@ function mapObject(data, fields) {
242
246
  const result = {};
243
247
  for (const [name, node] of Object.entries(fields)) {
244
248
  switch (node.type) {
245
- case "Object":
246
- if (Object.hasOwn(data, name)) {
247
- result[name] = mapArrayOrObject(data[name], node.fields);
248
- } else {
249
+ case "Object": {
250
+ if (!node.flattened && !Object.hasOwn(data, name)) {
249
251
  throw new Error(
250
252
  `DataMapper: Missing data field (Object): '${name}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
251
253
  );
252
254
  }
255
+ const target = node.flattened ? data : data[name];
256
+ result[name] = mapArrayOrObject(target, node.fields);
253
257
  break;
258
+ }
254
259
  case "Value":
255
260
  {
256
261
  const dbName = node.dbName;
@@ -665,8 +670,11 @@ var QueryInterpreter = class _QueryInterpreter {
665
670
  async interpretNode(node, queryable, scope, generators) {
666
671
  switch (node.type) {
667
672
  case "seq": {
668
- const results = await Promise.all(node.args.map((arg) => this.interpretNode(arg, queryable, scope, generators)));
669
- return results[results.length - 1];
673
+ let result;
674
+ for (const arg of node.args) {
675
+ result = await this.interpretNode(arg, queryable, scope, generators);
676
+ }
677
+ return result;
670
678
  }
671
679
  case "get": {
672
680
  return scope[node.args.name];
@@ -790,6 +798,38 @@ var QueryInterpreter = class _QueryInterpreter {
790
798
  const toSet = new Set(asList(to));
791
799
  return asList(from).filter((item) => !toSet.has(item));
792
800
  }
801
+ case "distinctBy": {
802
+ const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
803
+ const seen = /* @__PURE__ */ new Set();
804
+ const result = [];
805
+ for (const item of asList(value)) {
806
+ const key = getRecordKey(item, node.args.fields);
807
+ if (!seen.has(key)) {
808
+ seen.add(key);
809
+ result.push(item);
810
+ }
811
+ }
812
+ return result;
813
+ }
814
+ case "paginate": {
815
+ const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
816
+ const list = asList(value);
817
+ const linkingFields = node.args.pagination.linkingFields;
818
+ if (linkingFields !== null) {
819
+ const groupedByParent = /* @__PURE__ */ new Map();
820
+ for (const item of list) {
821
+ const parentKey = getRecordKey(item, linkingFields);
822
+ if (!groupedByParent.has(parentKey)) {
823
+ groupedByParent.set(parentKey, []);
824
+ }
825
+ groupedByParent.get(parentKey).push(item);
826
+ }
827
+ const groupList = Array.from(groupedByParent.entries());
828
+ groupList.sort(([aId], [bId]) => aId < bId ? -1 : aId > bId ? 1 : 0);
829
+ return groupList.flatMap(([, elems]) => paginate(elems, node.args.pagination));
830
+ }
831
+ return paginate(list, node.args.pagination);
832
+ }
793
833
  default:
794
834
  assertNever(node, `Unexpected node type: ${node.type}`);
795
835
  }
@@ -861,7 +901,12 @@ function attachChildrenToParent(parentRecord, children) {
861
901
  }
862
902
  function filterChildRecords(records, parentRecord, joinExpr) {
863
903
  if (Array.isArray(records)) {
864
- return records.filter((record) => childRecordMatchesParent(asRecord(record), parentRecord, joinExpr));
904
+ const filtered = records.filter((record) => childRecordMatchesParent(asRecord(record), parentRecord, joinExpr));
905
+ if (joinExpr.isRelationUnique) {
906
+ return filtered.length > 0 ? filtered[0] : null;
907
+ } else {
908
+ return filtered;
909
+ }
865
910
  } else if (records === null) {
866
911
  return null;
867
912
  } else {
@@ -877,6 +922,26 @@ function childRecordMatchesParent(childRecord, parentRecord, joinExpr) {
877
922
  }
878
923
  return true;
879
924
  }
925
+ function paginate(list, { cursor, skip, take }) {
926
+ const cursorIndex = cursor !== null ? list.findIndex((item) => doesMatchCursor(item, cursor)) : 0;
927
+ if (cursorIndex === -1) {
928
+ return [];
929
+ }
930
+ const start = cursorIndex + (skip ?? 0);
931
+ const end = take !== null ? start + take : list.length;
932
+ return list.slice(start, end);
933
+ }
934
+ function getRecordKey(record, fields) {
935
+ return JSON.stringify(fields.map((field) => record[field]));
936
+ }
937
+ function doesMatchCursor(item, cursor) {
938
+ return Object.keys(cursor).every((key) => {
939
+ if (typeof item[key] !== typeof cursor[key] && (typeof item[key] === "number" || typeof cursor[key] === "number")) {
940
+ return `${item[key]}` === `${cursor[key]}`;
941
+ }
942
+ return isDeepStrictEqual(cursor[key], item[key]);
943
+ });
944
+ }
880
945
 
881
946
  // src/transactionManager/TransactionManager.ts
882
947
  var import_debug = require("@prisma/debug");
@@ -1099,6 +1164,7 @@ var TransactionManager = class {
1099
1164
  TransactionManager,
1100
1165
  TransactionManagerError,
1101
1166
  UserFacingError,
1167
+ isDeepStrictEqual,
1102
1168
  isPrismaValueBytes,
1103
1169
  isPrismaValueGenerator,
1104
1170
  isPrismaValuePlaceholder,
package/dist/index.mjs CHANGED
@@ -5,6 +5,9 @@ import { SpanKind } from "@opentelemetry/api";
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
+ }
8
11
 
9
12
  // src/tracing.ts
10
13
  var noopTracingHelper = {
@@ -199,15 +202,16 @@ function mapObject(data, fields) {
199
202
  const result = {};
200
203
  for (const [name, node] of Object.entries(fields)) {
201
204
  switch (node.type) {
202
- case "Object":
203
- if (Object.hasOwn(data, name)) {
204
- result[name] = mapArrayOrObject(data[name], node.fields);
205
- } else {
205
+ case "Object": {
206
+ if (!node.flattened && !Object.hasOwn(data, name)) {
206
207
  throw new Error(
207
208
  `DataMapper: Missing data field (Object): '${name}'; node: ${JSON.stringify(node)}; data: ${JSON.stringify(data)}`
208
209
  );
209
210
  }
211
+ const target = node.flattened ? data : data[name];
212
+ result[name] = mapArrayOrObject(target, node.fields);
210
213
  break;
214
+ }
211
215
  case "Value":
212
216
  {
213
217
  const dbName = node.dbName;
@@ -622,8 +626,11 @@ var QueryInterpreter = class _QueryInterpreter {
622
626
  async interpretNode(node, queryable, scope, generators) {
623
627
  switch (node.type) {
624
628
  case "seq": {
625
- const results = await Promise.all(node.args.map((arg) => this.interpretNode(arg, queryable, scope, generators)));
626
- return results[results.length - 1];
629
+ let result;
630
+ for (const arg of node.args) {
631
+ result = await this.interpretNode(arg, queryable, scope, generators);
632
+ }
633
+ return result;
627
634
  }
628
635
  case "get": {
629
636
  return scope[node.args.name];
@@ -747,6 +754,38 @@ var QueryInterpreter = class _QueryInterpreter {
747
754
  const toSet = new Set(asList(to));
748
755
  return asList(from).filter((item) => !toSet.has(item));
749
756
  }
757
+ case "distinctBy": {
758
+ const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
759
+ const seen = /* @__PURE__ */ new Set();
760
+ const result = [];
761
+ for (const item of asList(value)) {
762
+ const key = getRecordKey(item, node.args.fields);
763
+ if (!seen.has(key)) {
764
+ seen.add(key);
765
+ result.push(item);
766
+ }
767
+ }
768
+ return result;
769
+ }
770
+ case "paginate": {
771
+ const value = await this.interpretNode(node.args.expr, queryable, scope, generators);
772
+ const list = asList(value);
773
+ const linkingFields = node.args.pagination.linkingFields;
774
+ if (linkingFields !== null) {
775
+ const groupedByParent = /* @__PURE__ */ new Map();
776
+ for (const item of list) {
777
+ const parentKey = getRecordKey(item, linkingFields);
778
+ if (!groupedByParent.has(parentKey)) {
779
+ groupedByParent.set(parentKey, []);
780
+ }
781
+ groupedByParent.get(parentKey).push(item);
782
+ }
783
+ const groupList = Array.from(groupedByParent.entries());
784
+ groupList.sort(([aId], [bId]) => aId < bId ? -1 : aId > bId ? 1 : 0);
785
+ return groupList.flatMap(([, elems]) => paginate(elems, node.args.pagination));
786
+ }
787
+ return paginate(list, node.args.pagination);
788
+ }
750
789
  default:
751
790
  assertNever(node, `Unexpected node type: ${node.type}`);
752
791
  }
@@ -818,7 +857,12 @@ function attachChildrenToParent(parentRecord, children) {
818
857
  }
819
858
  function filterChildRecords(records, parentRecord, joinExpr) {
820
859
  if (Array.isArray(records)) {
821
- return records.filter((record) => childRecordMatchesParent(asRecord(record), parentRecord, joinExpr));
860
+ const filtered = records.filter((record) => childRecordMatchesParent(asRecord(record), parentRecord, joinExpr));
861
+ if (joinExpr.isRelationUnique) {
862
+ return filtered.length > 0 ? filtered[0] : null;
863
+ } else {
864
+ return filtered;
865
+ }
822
866
  } else if (records === null) {
823
867
  return null;
824
868
  } else {
@@ -834,6 +878,26 @@ function childRecordMatchesParent(childRecord, parentRecord, joinExpr) {
834
878
  }
835
879
  return true;
836
880
  }
881
+ function paginate(list, { cursor, skip, take }) {
882
+ const cursorIndex = cursor !== null ? list.findIndex((item) => doesMatchCursor(item, cursor)) : 0;
883
+ if (cursorIndex === -1) {
884
+ return [];
885
+ }
886
+ const start = cursorIndex + (skip ?? 0);
887
+ const end = take !== null ? start + take : list.length;
888
+ return list.slice(start, end);
889
+ }
890
+ function getRecordKey(record, fields) {
891
+ return JSON.stringify(fields.map((field) => record[field]));
892
+ }
893
+ function doesMatchCursor(item, cursor) {
894
+ return Object.keys(cursor).every((key) => {
895
+ if (typeof item[key] !== typeof cursor[key] && (typeof item[key] === "number" || typeof cursor[key] === "number")) {
896
+ return `${item[key]}` === `${cursor[key]}`;
897
+ }
898
+ return isDeepStrictEqual(cursor[key], item[key]);
899
+ });
900
+ }
837
901
 
838
902
  // src/transactionManager/TransactionManager.ts
839
903
  import { Debug } from "@prisma/debug";
@@ -1055,6 +1119,7 @@ export {
1055
1119
  TransactionManager,
1056
1120
  TransactionManagerError,
1057
1121
  UserFacingError,
1122
+ isDeepStrictEqual,
1058
1123
  isPrismaValueBytes,
1059
1124
  isPrismaValueGenerator,
1060
1125
  isPrismaValuePlaceholder,
package/dist/utils.d.ts CHANGED
@@ -1 +1,5 @@
1
1
  export declare function assertNever(_: never, message: string): never;
2
+ /**
3
+ * Checks if two objects are deeply equal, recursively checking all properties for strict equality.
4
+ */
5
+ export declare function isDeepStrictEqual(a: unknown, b: unknown): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma/client-engine-runtime",
3
- "version": "6.8.2",
3
+ "version": "6.9.0-dev.10",
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.8.2",
35
- "@prisma/driver-adapter-utils": "6.8.2"
34
+ "@prisma/debug": "6.9.0-dev.10",
35
+ "@prisma/driver-adapter-utils": "6.9.0-dev.10"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/jest": "29.5.14",