@vantreeseba/drizzle-graphql 2.0.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4,29 +4,19 @@ import { MySqlDatabase } from "drizzle-orm/mysql-core";
4
4
  import { PgAsyncDatabase } from "drizzle-orm/pg-core";
5
5
  import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core";
6
6
  import {
7
- GraphQLObjectType as GraphQLObjectType4,
7
+ GraphQLObjectType as GraphQLObjectType5,
8
8
  GraphQLSchema
9
9
  } from "graphql";
10
10
 
11
- // src/util/builders/mysql.ts
12
- import { is as is4, One as One3 } from "drizzle-orm";
13
- import { getTableConfig, MySqlTable } from "drizzle-orm/mysql-core";
14
- import {
15
- GraphQLBoolean as GraphQLBoolean3,
16
- GraphQLError as GraphQLError3,
17
- GraphQLList as GraphQLList3,
18
- GraphQLNonNull as GraphQLNonNull3,
19
- GraphQLObjectType as GraphQLObjectType3
20
- } from "graphql";
21
- import { parseResolveInfo } from "graphql-parse-resolve-info";
22
-
23
11
  // src/util/builders/common.ts
24
12
  import {
13
+ aliasedTable,
25
14
  and,
26
15
  asc,
27
16
  desc,
28
17
  eq,
29
18
  getColumns,
19
+ getTableAsAliasSQL,
30
20
  gt,
31
21
  gte,
32
22
  ilike,
@@ -38,17 +28,19 @@ import {
38
28
  lt,
39
29
  lte,
40
30
  ne,
31
+ not,
41
32
  notIlike,
42
33
  notInArray,
43
34
  notLike,
44
35
  One as One2,
45
36
  or,
37
+ relationsFilterToSQL,
46
38
  sql
47
39
  } from "drizzle-orm";
48
40
  import {
49
41
  GraphQLBoolean as GraphQLBoolean2,
50
42
  GraphQLEnumType as GraphQLEnumType2,
51
- GraphQLError as GraphQLError2,
43
+ GraphQLError as GraphQLError3,
52
44
  GraphQLInputObjectType as GraphQLInputObjectType2,
53
45
  GraphQLInt as GraphQLInt2,
54
46
  GraphQLList as GraphQLList2,
@@ -111,6 +103,7 @@ var capitalize = (input) => input?.length ? `${input[0].toLocaleUpperCase()}${in
111
103
  // src/util/data-mappers/index.ts
112
104
  import { getTableColumns, is, One } from "drizzle-orm";
113
105
  import { GraphQLError } from "graphql";
106
+ var isJsonColumn = (column) => (column.dataType ?? "").includes("json") && column.columnType !== "PgGeometryObject";
114
107
  var remapToGraphQLCore = (key, value, tableName, column, relationMap) => {
115
108
  if (Array.isArray(value)) {
116
109
  const relations = relationMap?.[tableName];
@@ -140,6 +133,9 @@ var remapToGraphQLCore = (key, value, tableName, column, relationMap) => {
140
133
  if (!column) {
141
134
  return value;
142
135
  }
136
+ if (isJsonColumn(column)) {
137
+ return value;
138
+ }
143
139
  if (value instanceof Date) {
144
140
  return value.toISOString();
145
141
  }
@@ -217,17 +213,7 @@ var remapFromGraphQLCore = (value, column, columnName) => {
217
213
  }
218
214
  }
219
215
  if (dataType.includes("json") && column.columnType !== "PgGeometryObject") {
220
- if (typeof value !== "string") {
221
- return value;
222
- }
223
- try {
224
- return JSON.parse(value);
225
- } catch (e) {
226
- throw new GraphQLError(
227
- `Invalid JSON in field '${columnName}':
228
- ${e instanceof Error ? e.message : "Unknown error"}`
229
- );
230
- }
216
+ return value;
231
217
  }
232
218
  switch (dataType) {
233
219
  case "date": {
@@ -310,7 +296,7 @@ var remapFromGraphQLArrayInput = (queryInput, table) => {
310
296
  // src/util/type-converter/index.ts
311
297
  import { extractExtendedColumnType, is as is2 } from "drizzle-orm";
312
298
  import { MySqlInt, MySqlSerial } from "drizzle-orm/mysql-core";
313
- import { PgDate, PgDateString, PgInteger, PgSerial, PgTimestamp, PgTimestampString } from "drizzle-orm/pg-core";
299
+ import { PgDate, PgDateString, PgInteger, PgSerial, PgTimestamp, PgTimestampString, PgUUID } from "drizzle-orm/pg-core";
314
300
  import { SQLiteInteger } from "drizzle-orm/sqlite-core";
315
301
  import {
316
302
  GraphQLBoolean,
@@ -323,7 +309,47 @@ import {
323
309
  GraphQLObjectType,
324
310
  GraphQLString
325
311
  } from "graphql";
326
- import { GraphQLDate, GraphQLDateTime } from "graphql-scalars";
312
+
313
+ // src/util/scalars/index.ts
314
+ import { GraphQLError as GraphQLError2, GraphQLScalarType, Kind } from "graphql";
315
+ import { GraphQLDate, GraphQLDateTime, GraphQLJSON, GraphQLUUID } from "graphql-scalars";
316
+ var asDecimalString = (value) => {
317
+ if (typeof value === "bigint") {
318
+ return value.toString();
319
+ }
320
+ if (typeof value === "number") {
321
+ if (!Number.isInteger(value)) {
322
+ throw new GraphQLError2(`BigInt cannot represent non-integer value: ${value}`);
323
+ }
324
+ if (!Number.isSafeInteger(value)) {
325
+ throw new GraphQLError2(
326
+ `BigInt cannot represent the number ${value} without precision loss \u2014 pass it as a string instead`
327
+ );
328
+ }
329
+ return String(value);
330
+ }
331
+ if (typeof value === "string") {
332
+ if (!/^-?\d+$/.test(value)) {
333
+ throw new GraphQLError2(`BigInt cannot represent non-integer value: "${value}"`);
334
+ }
335
+ return value;
336
+ }
337
+ throw new GraphQLError2(`BigInt cannot represent value: ${JSON.stringify(value)}`);
338
+ };
339
+ var GraphQLBigIntString = new GraphQLScalarType({
340
+ name: "BigInt",
341
+ description: "A 64-bit integer, transported as a decimal string so that values beyond JavaScript's safe integer range survive the round-trip intact.",
342
+ serialize: asDecimalString,
343
+ parseValue: asDecimalString,
344
+ parseLiteral: (ast) => {
345
+ if (ast.kind !== Kind.STRING && ast.kind !== Kind.INT) {
346
+ throw new GraphQLError2(`BigInt cannot represent a ${ast.kind}`, { nodes: ast });
347
+ }
348
+ return asDecimalString(ast.value);
349
+ }
350
+ });
351
+
352
+ // src/util/type-converter/index.ts
327
353
  var allowedNameChars = /^[a-zA-Z0-9_]+$/;
328
354
  var enumMap = /* @__PURE__ */ new WeakMap();
329
355
  var generateEnumCached = (column, columnName, tableName) => {
@@ -374,7 +400,7 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
374
400
  } : column.columnType === "PgBytea" ? {
375
401
  type: new GraphQLList(new GraphQLNonNull(GraphQLInt)),
376
402
  description: "Buffer"
377
- } : { type: GraphQLString, description: "JSON" };
403
+ } : { type: GraphQLJSON, description: "JSON" };
378
404
  case "string":
379
405
  if (column.enumValues?.length) {
380
406
  return { type: generateEnumCached(column, columnName, tableName) };
@@ -382,12 +408,15 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
382
408
  if (column instanceof PgTimestamp || column instanceof PgTimestampString) {
383
409
  return { type: GraphQLDateTime, description: "DateTime" };
384
410
  }
411
+ if (column instanceof PgUUID) {
412
+ return { type: GraphQLUUID, description: "UUID" };
413
+ }
385
414
  if (column instanceof PgDateString) {
386
415
  return isInput ? { type: GraphQLString, description: "Date" } : { type: GraphQLDate, description: "Date" };
387
416
  }
388
417
  return { type: GraphQLString, description: "String" };
389
418
  case "bigint":
390
- return { type: GraphQLString, description: "BigInt" };
419
+ return { type: GraphQLBigIntString, description: "BigInt" };
391
420
  case "number": {
392
421
  const dims = column.dimensions;
393
422
  if (dims !== void 0 && dims > 0) {
@@ -518,6 +547,23 @@ var extractRelationJoinColumns = (relEntry, parentTable, targetTable) => {
518
547
  }
519
548
  return { localColPropName, foreignCol: targetCol, foreignColPropName };
520
549
  };
550
+ var drizzleExecutorKey = /* @__PURE__ */ Symbol.for("drizzle-graphql:executor");
551
+ var resolveExecutor = (db, context) => {
552
+ if (context && typeof context === "object") {
553
+ const executor = context[drizzleExecutorKey];
554
+ if (executor) {
555
+ return executor;
556
+ }
557
+ }
558
+ return db;
559
+ };
560
+ var resolveQueryExecutor = (db, context, tableName, buildTimeQueryBase) => {
561
+ const executor = resolveExecutor(db, context);
562
+ return {
563
+ executor,
564
+ queryBase: buildTimeQueryBase ? executor?.query?.[tableName] ?? buildTimeQueryBase : buildTimeQueryBase
565
+ };
566
+ };
521
567
  var batchedPaginatedRelationQuery = async (db, targetTable, foreignCol, whereCondition, orderByArg, limit, offset, pkNames) => {
522
568
  const cols = getColumns(targetTable);
523
569
  const orderExprs = [
@@ -539,7 +585,7 @@ var batchedPaginatedRelationQuery = async (db, targetTable, foreignCol, whereCon
539
585
  }
540
586
  return rows;
541
587
  };
542
- var createRelationResolverFactory = (db, tables) => ({ tableName, relationName, relEntry, isOne }) => {
588
+ var createRelationResolverFactory = (db, tables, filterCtx) => ({ tableName, relationName, relEntry, isOne }) => {
543
589
  const parentTable = tables[tableName];
544
590
  const targetTableName = relEntry.targetTableName;
545
591
  const targetTable = tables[targetTableName];
@@ -569,15 +615,16 @@ var createRelationResolverFactory = (db, tables) => ({ tableName, relationName,
569
615
  });
570
616
  const loaderKey = `${tableName}::${relationName}::${argsKey}`;
571
617
  const loader = getOrCreateLoader(context, loaderKey, async (parentIds) => {
618
+ const executor = resolveExecutor(db, context);
572
619
  const uniqueIds = [...new Set(parentIds)];
573
620
  const whereCondition = and(
574
621
  inArray(foreignCol, uniqueIds),
575
- whereArg ? extractFilters(targetTable, targetTableName, whereArg) : void 0
622
+ whereArg ? extractFilters(targetTable, targetTableName, whereArg, relationFilterCtx(filterCtx, targetTableName)) : void 0
576
623
  );
577
624
  let rows;
578
625
  if (limit != null || offset != null) {
579
626
  rows = await batchedPaginatedRelationQuery(
580
- db,
627
+ executor,
581
628
  targetTable,
582
629
  foreignCol,
583
630
  whereCondition,
@@ -587,7 +634,7 @@ var createRelationResolverFactory = (db, tables) => ({ tableName, relationName,
587
634
  targetPkNames
588
635
  );
589
636
  } else {
590
- let q = db.select().from(targetTable).where(whereCondition);
637
+ let q = executor.select().from(targetTable).where(whereCondition);
591
638
  if (orderByArg) {
592
639
  q = q.orderBy(...extractOrderBy(targetTable, orderByArg));
593
640
  }
@@ -608,7 +655,31 @@ var createRelationResolverFactory = (db, tables) => ({ tableName, relationName,
608
655
  return loader.load(localValue);
609
656
  };
610
657
  };
611
- var extractSelectedColumnsFromTree = (tree, table) => {
658
+ var AGGREGATE_FIELD_SUFFIX = "Aggregate";
659
+ var relationAggregateJoinColumns = (tree, table, selectionCtx) => {
660
+ const relations = selectionCtx?.relationMap[selectionCtx.tableName];
661
+ if (!relations || !selectionCtx) {
662
+ return [];
663
+ }
664
+ const tableColumns = getColumns(table);
665
+ const needed = [];
666
+ for (const fieldData of Object.values(tree)) {
667
+ if (tableColumns[fieldData.name] || !fieldData.name.endsWith(AGGREGATE_FIELD_SUFFIX)) {
668
+ continue;
669
+ }
670
+ const relEntry = relations[fieldData.name.slice(0, -AGGREGATE_FIELD_SUFFIX.length)];
671
+ const targetTable = relEntry ? selectionCtx.tables[relEntry.targetTableName] : void 0;
672
+ if (!relEntry || !targetTable) {
673
+ continue;
674
+ }
675
+ const joinCols = extractRelationJoinColumns(relEntry, table, targetTable);
676
+ if (joinCols) {
677
+ needed.push(joinCols.localColPropName);
678
+ }
679
+ }
680
+ return needed;
681
+ };
682
+ var extractSelectedColumnsFromTree = (tree, table, selectionCtx) => {
612
683
  const tableColumns = getColumns(table);
613
684
  const treeEntries = Object.entries(tree);
614
685
  const selectedColumns = [];
@@ -618,6 +689,9 @@ var extractSelectedColumnsFromTree = (tree, table) => {
618
689
  }
619
690
  selectedColumns.push([fieldData.name, true]);
620
691
  }
692
+ for (const columnName of relationAggregateJoinColumns(tree, table, selectionCtx)) {
693
+ selectedColumns.push([columnName, true]);
694
+ }
621
695
  if (!selectedColumns.length) {
622
696
  const columnKeys = Object.entries(tableColumns);
623
697
  const columnName = columnKeys.find((e) => rqbCrashTypes.find((haram) => e[1].columnType !== haram))?.[0] ?? columnKeys[0][0];
@@ -625,7 +699,7 @@ var extractSelectedColumnsFromTree = (tree, table) => {
625
699
  }
626
700
  return Object.fromEntries(selectedColumns);
627
701
  };
628
- var extractSelectedColumnsFromTreeSQLFormat = (tree, table) => {
702
+ var extractSelectedColumnsFromTreeSQLFormat = (tree, table, selectionCtx) => {
629
703
  const tableColumns = getColumns(table);
630
704
  const treeEntries = Object.entries(tree);
631
705
  const selectedColumns = [];
@@ -635,6 +709,9 @@ var extractSelectedColumnsFromTreeSQLFormat = (tree, table) => {
635
709
  }
636
710
  selectedColumns.push([fieldData.name, tableColumns[fieldData.name]]);
637
711
  }
712
+ for (const columnName of relationAggregateJoinColumns(tree, table, selectionCtx)) {
713
+ selectedColumns.push([columnName, tableColumns[columnName]]);
714
+ }
638
715
  if (!selectedColumns.length) {
639
716
  const columnKeys = Object.entries(tableColumns);
640
717
  const columnName = columnKeys.find((e) => rqbCrashTypes.find((haram) => e[1].columnType !== haram))?.[0] ?? columnKeys[0][0];
@@ -797,34 +874,102 @@ var generateTableOrderTypeCached = (table, tableName, typeNameMapper, cacheCtx)
797
874
  cacheCtx.orderTypeCache.set(table, order);
798
875
  return order;
799
876
  };
800
- var generateTableFilterTypeCached = (table, tableName, cacheCtx, typeNameMapper) => {
877
+ var isFilterableRelation = (relation) => !relation.through;
878
+ var generateListRelationFilterCached = (targetTable, targetTableName, cacheCtx, typeNameMapper, relationMap, tables) => {
879
+ const cached = cacheCtx.listRelationFilterCache.get(targetTableName);
880
+ if (cached) {
881
+ return cached;
882
+ }
883
+ const listFilter = new GraphQLInputObjectType2({
884
+ name: `${resolveTypeName(targetTableName, typeNameMapper)}ListRelationFilter`,
885
+ fields: () => {
886
+ const targetFilters = generateTableFilterTypeCached(
887
+ targetTable,
888
+ targetTableName,
889
+ cacheCtx,
890
+ typeNameMapper,
891
+ relationMap,
892
+ tables
893
+ );
894
+ return {
895
+ some: { type: targetFilters, description: "At least one related row matches" },
896
+ none: { type: targetFilters, description: "No related row matches" },
897
+ every: { type: targetFilters, description: "Every related row matches" }
898
+ };
899
+ }
900
+ });
901
+ cacheCtx.listRelationFilterCache.set(targetTableName, listFilter);
902
+ return listFilter;
903
+ };
904
+ var generateRelationFilterFields = (tableName, cacheCtx, typeNameMapper, columnFields, relationMap, tables) => {
905
+ const relations = relationMap?.[tableName];
906
+ if (!relations || !tables) {
907
+ return {};
908
+ }
909
+ const fields = {};
910
+ for (const [relationName, relEntry] of Object.entries(relations)) {
911
+ if (relationName in columnFields) {
912
+ continue;
913
+ }
914
+ const targetTable = tables[relEntry.targetTableName];
915
+ const relation = relEntry.relation ?? relEntry;
916
+ if (!targetTable || !isFilterableRelation(relation)) {
917
+ continue;
918
+ }
919
+ fields[relationName] = is3(relation, One2) ? {
920
+ type: generateTableFilterTypeCached(
921
+ targetTable,
922
+ relEntry.targetTableName,
923
+ cacheCtx,
924
+ typeNameMapper,
925
+ relationMap,
926
+ tables
927
+ ),
928
+ description: `Matches rows whose ${relationName} matches these filters`
929
+ } : {
930
+ type: generateListRelationFilterCached(
931
+ targetTable,
932
+ relEntry.targetTableName,
933
+ cacheCtx,
934
+ typeNameMapper,
935
+ relationMap,
936
+ tables
937
+ )
938
+ };
939
+ }
940
+ return fields;
941
+ };
942
+ var generateTableFilterTypeCached = (table, tableName, cacheCtx, typeNameMapper, relationMap, tables) => {
801
943
  if (cacheCtx.filterTypeCache.has(table)) {
802
944
  return cacheCtx.filterTypeCache.get(table);
803
945
  }
804
- const filterColumns = generateTableFilterValuesCached(table, tableName, cacheCtx);
946
+ const buildFields = () => {
947
+ const filterColumns = generateTableFilterValuesCached(table, tableName, cacheCtx);
948
+ return {
949
+ ...filterColumns,
950
+ ...generateRelationFilterFields(tableName, cacheCtx, typeNameMapper, filterColumns, relationMap, tables)
951
+ };
952
+ };
953
+ const orFilters = new GraphQLInputObjectType2({
954
+ name: `${resolveTypeName(tableName, typeNameMapper)}FiltersOr`,
955
+ fields: buildFields
956
+ });
805
957
  const filters = new GraphQLInputObjectType2({
806
958
  name: `${resolveTypeName(tableName, typeNameMapper)}Filters`,
807
- fields: {
808
- ...filterColumns,
959
+ fields: () => ({
960
+ ...buildFields(),
809
961
  OR: {
810
- type: new GraphQLList2(
811
- new GraphQLNonNull2(
812
- new GraphQLInputObjectType2({
813
- name: `${resolveTypeName(tableName, typeNameMapper)}FiltersOr`,
814
- fields: filterColumns
815
- })
816
- )
817
- )
962
+ type: new GraphQLList2(new GraphQLNonNull2(orFilters))
818
963
  }
819
- }
964
+ })
820
965
  });
821
966
  cacheCtx.filterTypeCache.set(table, filters);
822
967
  return filters;
823
968
  };
824
- var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromRelationName, withOrder, relationsDepthLimit, cacheCtx, typeNameMapper, usedTables = /* @__PURE__ */ new Set(), resolverFactory, currentDepth = 0) => {
969
+ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromRelationName, withOrder, relationsDepthLimit, cacheCtx, typeNameMapper, usedTables = /* @__PURE__ */ new Set(), resolverFactory, currentDepth = 0, relationAggregateFactory) => {
825
970
  const table = tables[tableName];
826
971
  const order = withOrder ? generateTableOrderTypeCached(table, tableName, typeNameMapper, cacheCtx) : void 0;
827
- const filters = generateTableFilterTypeCached(table, tableName, cacheCtx, typeNameMapper);
972
+ const filters = generateTableFilterTypeCached(table, tableName, cacheCtx, typeNameMapper, relationMap, tables);
828
973
  const tableFields = generateTableSelectTypeFieldsCached(table, tableName);
829
974
  const relationsForTable = relationMap[tableName];
830
975
  const relationEntries = relationsForTable ? Object.entries(relationsForTable) : [];
@@ -888,7 +1033,8 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
888
1033
  typeNameMapper,
889
1034
  nextUsedTables,
890
1035
  resolverFactory,
891
- currentDepth + 1
1036
+ currentDepth + 1,
1037
+ relationAggregateFactory
892
1038
  );
893
1039
  let relType = cacheCtx.objectTypeCache.get(targetTableName);
894
1040
  if (!relType) {
@@ -933,6 +1079,26 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
933
1079
  resolve
934
1080
  }
935
1081
  ]);
1082
+ const aggregateFieldName = `${relationName}Aggregate`;
1083
+ if (!tableFields[aggregateFieldName] && !relationsForTable?.[aggregateFieldName]) {
1084
+ const relationAggregate = relationAggregateFactory?.({
1085
+ tableName,
1086
+ relationName,
1087
+ relEntry
1088
+ });
1089
+ if (relationAggregate) {
1090
+ rawRelationFields.push([
1091
+ aggregateFieldName,
1092
+ {
1093
+ type: new GraphQLNonNull2(relationAggregate.type),
1094
+ args: {
1095
+ where: { type: relSelectData.filters }
1096
+ },
1097
+ resolve: relationAggregate.resolve
1098
+ }
1099
+ ]);
1100
+ }
1101
+ }
936
1102
  }
937
1103
  const builtRelationFields = Object.fromEntries(rawRelationFields);
938
1104
  if (isRootCall) {
@@ -956,7 +1122,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
956
1122
  relationFields: {}
957
1123
  };
958
1124
  };
959
- var generateTableTypes = (tableName, tables, relationMap, withReturning, relationsDepthLimit, cacheCtx, typeNameMapper = void 0, insertPrefix = "create", updatePrefix = "update", resolverFactory) => {
1125
+ var generateTableTypes = (tableName, tables, relationMap, withReturning, relationsDepthLimit, cacheCtx, typeNameMapper = void 0, insertPrefix = "create", updatePrefix = "update", resolverFactory, relationAggregateFactory) => {
960
1126
  const { tableFields, relationFields, filters, order } = generateSelectFields(
961
1127
  tables,
962
1128
  tableName,
@@ -971,7 +1137,8 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
971
1137
  typeNameMapper,
972
1138
  /* @__PURE__ */ new Set(),
973
1139
  resolverFactory,
974
- 0
1140
+ 0,
1141
+ relationAggregateFactory
975
1142
  );
976
1143
  const table = tables[tableName];
977
1144
  const columns = getColumns(table);
@@ -1026,19 +1193,10 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
1026
1193
  outputs
1027
1194
  };
1028
1195
  };
1029
- var extractOrderBy = (table, orderArgs) => {
1030
- const res = [];
1031
- for (const [column, config] of Object.entries(orderArgs).sort(
1032
- (a, b) => (b[1]?.priority ?? 0) - (a[1]?.priority ?? 0)
1033
- )) {
1034
- if (!config) {
1035
- continue;
1036
- }
1037
- const { direction } = config;
1038
- res.push(direction === "asc" ? asc(getColumns(table)[column]) : desc(getColumns(table)[column]));
1039
- }
1040
- return res;
1041
- };
1196
+ var orderByEntries = (orderArgs) => Object.entries(orderArgs).sort((a, b) => (b[1]?.priority ?? 0) - (a[1]?.priority ?? 0)).filter(([, config]) => config).map(([column, config]) => [column, config.direction]);
1197
+ var extractOrderBy = (table, orderArgs) => orderByEntries(orderArgs).map(
1198
+ ([column, direction]) => direction === "asc" ? asc(getColumns(table)[column]) : desc(getColumns(table)[column])
1199
+ );
1042
1200
  var extractFiltersColumn = (column, columnName, operators) => {
1043
1201
  if (!operators.OR?.length) {
1044
1202
  delete operators.OR;
@@ -1046,7 +1204,7 @@ var extractFiltersColumn = (column, columnName, operators) => {
1046
1204
  const entries = Object.entries(operators);
1047
1205
  if (operators.OR) {
1048
1206
  if (entries.length > 1) {
1049
- throw new GraphQLError2(`WHERE ${columnName}: Cannot specify both fields and 'OR' in column operators!`);
1207
+ throw new GraphQLError3(`WHERE ${columnName}: Cannot specify both fields and 'OR' in column operators!`);
1050
1208
  }
1051
1209
  const variants2 = [];
1052
1210
  for (const variant of operators.OR) {
@@ -1073,7 +1231,7 @@ var extractFiltersColumn = (column, columnName, operators) => {
1073
1231
  variants.push(stringValueOps[operatorName](column, operatorValue));
1074
1232
  } else if (operatorName in arrayValueOps) {
1075
1233
  if (!operatorValue.length) {
1076
- throw new GraphQLError2(`WHERE ${columnName}: Unable to use operator ${operatorName} with an empty array!`);
1234
+ throw new GraphQLError3(`WHERE ${columnName}: Unable to use operator ${operatorName} with an empty array!`);
1077
1235
  }
1078
1236
  const arrayValue = operatorValue.map((val) => remapFromGraphQLCore(val, column, columnName));
1079
1237
  variants.push(arrayValueOps[operatorName](column, arrayValue));
@@ -1083,7 +1241,67 @@ var extractFiltersColumn = (column, columnName, operators) => {
1083
1241
  }
1084
1242
  return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
1085
1243
  };
1086
- var extractFilters = (table, tableName, filters) => {
1244
+ var relationFilterCtx = (base, tableKey) => base ? { ...base, tableKey } : void 0;
1245
+ var buildRelationJoinCondition = (parentTable, relation, aliasedTarget, relationName) => {
1246
+ const sourceColumns = relation.sourceColumns;
1247
+ const targetColumns = relation.targetColumns;
1248
+ if (!sourceColumns?.length || sourceColumns.length !== targetColumns?.length) {
1249
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1250
+ }
1251
+ const parentColumns = Object.values(getColumns(parentTable));
1252
+ const targetColumnsByName = Object.values(getColumns(aliasedTarget));
1253
+ const conditions = [];
1254
+ for (let i = 0; i < sourceColumns.length; i++) {
1255
+ const localColumn = parentColumns.find((c) => c.name === sourceColumns[i].name);
1256
+ const foreignColumn = targetColumnsByName.find((c) => c.name === targetColumns[i].name);
1257
+ if (!localColumn || !foreignColumn) {
1258
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1259
+ }
1260
+ conditions.push(eq(localColumn, foreignColumn));
1261
+ }
1262
+ return conditions.length > 1 ? and(...conditions) : conditions[0];
1263
+ };
1264
+ var buildRelationExists = (parentTable, relationName, relEntry, innerFilters, mode, ctx) => {
1265
+ const { targetTableName } = relEntry;
1266
+ const targetTable = ctx.tables[targetTableName];
1267
+ const relation = relEntry.relation ?? relEntry;
1268
+ if (!targetTable || !isFilterableRelation(relation)) {
1269
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1270
+ }
1271
+ ctx.aliases ??= { n: 0 };
1272
+ const aliases = ctx.aliases;
1273
+ const aliasedTarget = aliasedTable(targetTable, `dgql_rel_${aliases.n++}`);
1274
+ const joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
1275
+ const relationWhere = relation.where ? relationsFilterToSQL(relation.isReversed ? parentTable : aliasedTarget, relation.where) : void 0;
1276
+ const inner = innerFilters ? extractFilters(aliasedTarget, targetTableName, innerFilters, { ...ctx, tableKey: targetTableName, aliases }) : void 0;
1277
+ if (mode === "every") {
1278
+ if (!inner) {
1279
+ return void 0;
1280
+ }
1281
+ return sql`not exists (select 1 from ${getTableAsAliasSQL(aliasedTarget)} where ${and(joinCondition, relationWhere, not(inner))})`;
1282
+ }
1283
+ const condition = and(joinCondition, relationWhere, inner);
1284
+ return mode === "none" ? sql`not exists (select 1 from ${getTableAsAliasSQL(aliasedTarget)} where ${condition})` : sql`exists (select 1 from ${getTableAsAliasSQL(aliasedTarget)} where ${condition})`;
1285
+ };
1286
+ var extractRelationFilter = (parentTable, relationName, relEntry, value, ctx) => {
1287
+ const relation = relEntry.relation ?? relEntry;
1288
+ if (is3(relation, One2)) {
1289
+ return buildRelationExists(parentTable, relationName, relEntry, value, "some", ctx);
1290
+ }
1291
+ const variants = [];
1292
+ for (const mode of ["some", "none", "every"]) {
1293
+ const inner = value[mode];
1294
+ if (inner === void 0 || inner === null) {
1295
+ continue;
1296
+ }
1297
+ const extracted = buildRelationExists(parentTable, relationName, relEntry, inner, mode, ctx);
1298
+ if (extracted) {
1299
+ variants.push(extracted);
1300
+ }
1301
+ }
1302
+ return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
1303
+ };
1304
+ var extractFilters = (table, tableName, filters, relationCtx) => {
1087
1305
  if (!filters.OR?.length) {
1088
1306
  delete filters.OR;
1089
1307
  }
@@ -1093,28 +1311,33 @@ var extractFilters = (table, tableName, filters) => {
1093
1311
  }
1094
1312
  if (filters.OR) {
1095
1313
  if (entries.length > 1) {
1096
- throw new GraphQLError2(`WHERE ${tableName}: Cannot specify both fields and 'OR' in table filters!`);
1314
+ throw new GraphQLError3(`WHERE ${tableName}: Cannot specify both fields and 'OR' in table filters!`);
1097
1315
  }
1098
1316
  const variants2 = [];
1099
1317
  for (const variant of filters.OR) {
1100
- const extracted = extractFilters(table, tableName, variant);
1318
+ const extracted = extractFilters(table, tableName, variant, relationCtx);
1101
1319
  if (extracted) {
1102
1320
  variants2.push(extracted);
1103
1321
  }
1104
1322
  }
1105
1323
  return variants2.length ? variants2.length > 1 ? or(...variants2) : variants2[0] : void 0;
1106
1324
  }
1325
+ const columns = getColumns(table);
1326
+ const relations = relationCtx?.relationMap[relationCtx.tableKey];
1107
1327
  const variants = [];
1108
- for (const [columnName, operators] of entries) {
1109
- if (operators === null) {
1328
+ for (const [fieldName, operators] of entries) {
1329
+ if (operators === null || operators === void 0) {
1110
1330
  continue;
1111
1331
  }
1112
- const column = getColumns(table)[columnName];
1113
- variants.push(extractFiltersColumn(column, columnName, operators));
1332
+ const column = columns[fieldName];
1333
+ const extracted = column ? extractFiltersColumn(column, fieldName, operators) : relations?.[fieldName] && relationCtx ? extractRelationFilter(table, fieldName, relations[fieldName], operators, relationCtx) : void 0;
1334
+ if (extracted) {
1335
+ variants.push(extracted);
1336
+ }
1114
1337
  }
1115
1338
  return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
1116
1339
  };
1117
- var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, originField, typeNameMapper, _isInitial = false) => {
1340
+ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, originField, typeNameMapper, _isInitial = false, filterCtx) => {
1118
1341
  const relationsForTable = relationMap[tableName];
1119
1342
  if (!relationsForTable) {
1120
1343
  return void 0;
@@ -1136,7 +1359,11 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
1136
1359
  if (!relFieldSelection) {
1137
1360
  continue;
1138
1361
  }
1139
- const columns = extractSelectedColumnsFromTree(relFieldSelection, tables[targetTableName]);
1362
+ const columns = extractSelectedColumnsFromTree(relFieldSelection, tables[targetTableName], {
1363
+ tableName: targetTableName,
1364
+ relationMap,
1365
+ tables
1366
+ });
1140
1367
  const thisRecord = {};
1141
1368
  thisRecord.columns = columns;
1142
1369
  const relationField = Object.values(baseField).find((e) => e.name === relName);
@@ -1144,23 +1371,34 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
1144
1371
  const offset = relationArgs?.offset ?? void 0;
1145
1372
  const limit = relationArgs?.limit ?? void 0;
1146
1373
  const relWhere = relationArgs?.where;
1147
- thisRecord.where = relWhere ? { RAW: (aliasedTable) => extractFilters(aliasedTable, relName, relWhere) } : void 0;
1374
+ thisRecord.where = relWhere ? {
1375
+ RAW: (aliasedTable2) => extractFilters(aliasedTable2, relName, relWhere, relationFilterCtx(filterCtx, targetTableName))
1376
+ } : void 0;
1148
1377
  const hasPagination = offset != null || limit != null;
1149
1378
  const pkNames = targetPkNames ?? [];
1150
- thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable) => extractOrderBy(aliasedTable, relationArgs.orderBy) : hasPagination && pkNames.length ? (aliasedTable) => primaryKeyOrderExprs(aliasedTable, pkNames) : void 0;
1379
+ thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, relationArgs.orderBy) : hasPagination && pkNames.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0;
1151
1380
  thisRecord.offset = offset;
1152
1381
  thisRecord.limit = limit;
1153
- const relWith = relationField ? extractRelationsParamsInner(relationMap, tables, targetTableName, relTypeName, relationField, typeNameMapper) : void 0;
1382
+ const relWith = relationField ? extractRelationsParamsInner(
1383
+ relationMap,
1384
+ tables,
1385
+ targetTableName,
1386
+ relTypeName,
1387
+ relationField,
1388
+ typeNameMapper,
1389
+ false,
1390
+ filterCtx
1391
+ ) : void 0;
1154
1392
  thisRecord.with = relWith;
1155
1393
  args[relName] = thisRecord;
1156
1394
  }
1157
1395
  return args;
1158
1396
  };
1159
- var extractRelationsParams = (relationMap, tables, tableName, info, typeName, typeNameMapper) => {
1397
+ var extractRelationsParams = (relationMap, tables, tableName, info, typeName, typeNameMapper, filterCtx) => {
1160
1398
  if (!info) {
1161
1399
  return void 0;
1162
1400
  }
1163
- return extractRelationsParamsInner(relationMap, tables, tableName, typeName, info, typeNameMapper, true);
1401
+ return extractRelationsParamsInner(relationMap, tables, tableName, typeName, info, typeNameMapper, true, filterCtx);
1164
1402
  };
1165
1403
  var pruneNonEagerRelations = (relationMap, shouldEagerLoad) => {
1166
1404
  const out = {};
@@ -1204,39 +1442,307 @@ var primaryKeyOrderExprs = (table, pkNames) => {
1204
1442
  const cols = getColumns(table);
1205
1443
  return pkNames.map((n) => cols[n]).filter(Boolean).map((col) => asc(col));
1206
1444
  };
1445
+ var getUniqueColumnSets = (table, getTableConfig4) => {
1446
+ const cols = getColumns(table);
1447
+ const propNameByColumnName = new Map(Object.entries(cols).map(([propName, col]) => [col.name, propName]));
1448
+ const toPropNames = (columnNames) => {
1449
+ const propNames = [];
1450
+ for (const columnName of columnNames) {
1451
+ const propName = columnName === void 0 ? void 0 : propNameByColumnName.get(columnName);
1452
+ if (!propName) {
1453
+ return void 0;
1454
+ }
1455
+ propNames.push(propName);
1456
+ }
1457
+ return propNames.length ? propNames : void 0;
1458
+ };
1459
+ const config = getTableConfig4(table);
1460
+ const candidates = [
1461
+ // Inline `.primaryKey()` columns, then table-level `primaryKey({ columns })`.
1462
+ Object.entries(cols).filter(([, col]) => col.primary).map(([propName]) => propName),
1463
+ ...config.primaryKeys.map((pk) => toPropNames(pk.columns.map((c) => c.name))),
1464
+ ...(config.uniqueConstraints ?? []).map((uc) => toPropNames(uc.columns.map((c) => c.name))),
1465
+ ...(config.indexes ?? []).filter((index) => index.config.unique).map((index) => toPropNames(index.config.columns.map((c) => c?.name))),
1466
+ ...Object.entries(cols).filter(([, col]) => col.isUnique).map(([propName]) => [propName])
1467
+ ];
1468
+ const seen = /* @__PURE__ */ new Set();
1469
+ const sets = [];
1470
+ for (const set of candidates) {
1471
+ if (!set?.length) {
1472
+ continue;
1473
+ }
1474
+ const key = [...set].sort().join(",");
1475
+ if (seen.has(key)) {
1476
+ continue;
1477
+ }
1478
+ seen.add(key);
1479
+ sets.push(set);
1480
+ }
1481
+ return sets;
1482
+ };
1483
+ var DISTINCT_RN = "__drizzle_graphql_distinct_rn";
1484
+ var columnEnumCache = /* @__PURE__ */ new WeakMap();
1485
+ var generateColumnEnum = (table, enumName, description, predicate = () => true) => {
1486
+ let tableCache = columnEnumCache.get(table);
1487
+ const cached = tableCache?.get(enumName);
1488
+ if (cached) {
1489
+ return cached;
1490
+ }
1491
+ const columnNames = Object.entries(getColumns(table)).filter(([columnName, column]) => predicate(column, columnName)).map(([columnName]) => columnName);
1492
+ if (!columnNames.length) {
1493
+ return void 0;
1494
+ }
1495
+ const enumType = new GraphQLEnumType2({
1496
+ name: enumName,
1497
+ description,
1498
+ values: Object.fromEntries(columnNames.map((columnName) => [columnName, { value: columnName }]))
1499
+ });
1500
+ if (!tableCache) {
1501
+ tableCache = /* @__PURE__ */ new Map();
1502
+ columnEnumCache.set(table, tableCache);
1503
+ }
1504
+ tableCache.set(enumName, enumType);
1505
+ return enumType;
1506
+ };
1507
+ var generateDistinctEnum = (table, typeName) => generateColumnEnum(table, `${typeName}DistinctColumn`, `Columns of ${typeName} that a query can be made distinct on`);
1508
+ var conflictActionEnum = new GraphQLEnumType2({
1509
+ name: "ConflictAction",
1510
+ description: "What an upsert does when a row with the same unique key already exists",
1511
+ values: {
1512
+ UPDATE: { value: "UPDATE", description: "Overwrite the conflicting row with the supplied values" },
1513
+ NOTHING: { value: "NOTHING", description: "Keep the existing row and insert nothing" }
1514
+ }
1515
+ });
1516
+ var generateOnConflictInput = (params) => {
1517
+ const { table, typeName, uniqueSets, tableFilters, withTarget } = params;
1518
+ const updateEnum = generateColumnEnum(
1519
+ table,
1520
+ `${typeName}UpdateColumn`,
1521
+ `Columns of ${typeName} that an upsert can overwrite`
1522
+ );
1523
+ if (!updateEnum) {
1524
+ return void 0;
1525
+ }
1526
+ const fields = {
1527
+ action: {
1528
+ type: conflictActionEnum,
1529
+ defaultValue: "UPDATE",
1530
+ description: "Whether a conflicting row is overwritten or left alone. Defaults to UPDATE."
1531
+ },
1532
+ update: {
1533
+ type: new GraphQLList2(new GraphQLNonNull2(updateEnum)),
1534
+ description: "Columns to overwrite on conflict. Defaults to every column the request supplied, minus the conflict target. Columns the request did not supply cannot be listed here \u2014 there would be no value to write."
1535
+ }
1536
+ };
1537
+ if (withTarget) {
1538
+ const uniqueColumns = new Set(uniqueSets.flat());
1539
+ const targetEnum = generateColumnEnum(
1540
+ table,
1541
+ `${typeName}ConflictTarget`,
1542
+ `Columns of ${typeName} that carry a unique constraint, and so can be conflicted on`,
1543
+ (_column, columnName) => uniqueColumns.has(columnName)
1544
+ );
1545
+ if (!targetEnum) {
1546
+ return void 0;
1547
+ }
1548
+ fields["target"] = {
1549
+ type: new GraphQLList2(new GraphQLNonNull2(targetEnum)),
1550
+ description: "The unique column set a conflict is detected on. Must match one of the table\u2019s unique constraints exactly. Defaults to the primary key."
1551
+ };
1552
+ fields["where"] = {
1553
+ type: tableFilters,
1554
+ description: "Only overwrite conflicting rows that match this filter. Others are left alone."
1555
+ };
1556
+ }
1557
+ return new GraphQLInputObjectType2({
1558
+ name: `${typeName}OnConflict`,
1559
+ description: `Conflict handling for an upsert of ${typeName}`,
1560
+ fields
1561
+ });
1562
+ };
1563
+ var resolveConflictPlan = (params) => {
1564
+ const { table, values, onConflict, pkNames, uniqueSets, excludedRef, withTarget, buildWhere } = params;
1565
+ const columns = getColumns(table);
1566
+ let target;
1567
+ if (withTarget) {
1568
+ const targetNames2 = onConflict?.target?.length ? onConflict.target : [...pkNames];
1569
+ if (!targetNames2.length) {
1570
+ throw new GraphQLError3(
1571
+ "Unable to upsert: no conflict target was given and this table has no primary key. Pass onConflict.target."
1572
+ );
1573
+ }
1574
+ const requested = [...targetNames2].sort().join(",");
1575
+ if (!uniqueSets.some((set2) => [...set2].sort().join(",") === requested)) {
1576
+ throw new GraphQLError3(
1577
+ `Unable to upsert: [${targetNames2.join(", ")}] is not a unique constraint on this table. Valid conflict targets: ${uniqueSets.map((set2) => `[${set2.join(", ")}]`).join(", ")}.`
1578
+ );
1579
+ }
1580
+ target = targetNames2.map((name) => columns[name]);
1581
+ }
1582
+ if ((onConflict?.action ?? "UPDATE") === "NOTHING") {
1583
+ return { action: "NOTHING", target, set: {}, setWhere: void 0 };
1584
+ }
1585
+ const supplied = new Set(values.flatMap((row) => Object.keys(row)));
1586
+ const targetNames = new Set(withTarget ? onConflict?.target?.length ? onConflict.target : pkNames : []);
1587
+ let updateNames;
1588
+ if (onConflict?.update?.length) {
1589
+ const unsupplied = onConflict.update.filter((name) => !supplied.has(name));
1590
+ if (unsupplied.length) {
1591
+ throw new GraphQLError3(
1592
+ `Unable to upsert: onConflict.update lists ${unsupplied.join(", ")}, which the values do not supply.`
1593
+ );
1594
+ }
1595
+ updateNames = onConflict.update;
1596
+ } else {
1597
+ updateNames = [...supplied].filter((name) => !targetNames.has(name));
1598
+ }
1599
+ if (!updateNames.length) {
1600
+ return { action: "NOTHING", target, set: {}, setWhere: void 0 };
1601
+ }
1602
+ const set = Object.fromEntries(updateNames.map((name) => [name, excludedRef(columns[name].name)]));
1603
+ const setWhere = onConflict?.where && buildWhere ? buildWhere(onConflict.where) : void 0;
1604
+ return { action: "UPDATE", target, set, setWhere };
1605
+ };
1606
+ var excludedColumnRef = (columnName) => sql`excluded.${sql.identifier(columnName)}`;
1607
+ var mysqlValuesColumnRef = (columnName) => sql`values(${sql.identifier(columnName)})`;
1608
+ var selectDistinctKeys = async (params) => {
1609
+ const { db, table, tableName, distinct, pkNames, where, orderBy, limit, offset } = params;
1610
+ const cols = getColumns(table);
1611
+ if (!pkNames.length) {
1612
+ throw new GraphQLError3(`Table ${tableName} has no primary key, so 'distinct' cannot be applied to it.`);
1613
+ }
1614
+ const partitionCols = distinct.map((name) => cols[name]).filter(Boolean);
1615
+ if (!partitionCols.length) {
1616
+ throw new GraphQLError3(`No known columns were given to 'distinct' on ${tableName}.`);
1617
+ }
1618
+ const orderEntries = orderBy ? orderByEntries(orderBy) : [];
1619
+ const windowOrder = [
1620
+ ...orderEntries.map(([column, direction]) => direction === "asc" ? asc(cols[column]) : desc(cols[column])),
1621
+ ...primaryKeyOrderExprs(table, pkNames)
1622
+ ];
1623
+ const rowNumber = sql`row_number() over (partition by ${sql.join(partitionCols, sql`, `)} order by ${sql.join(
1624
+ windowOrder,
1625
+ sql`, `
1626
+ )})`.as(DISTINCT_RN);
1627
+ const sub = db.select({ ...cols, [DISTINCT_RN]: rowNumber }).from(table).where(where).as("__dgql_distinct");
1628
+ const outerOrder = [
1629
+ ...orderEntries.map(([column, direction]) => direction === "asc" ? asc(sub[column]) : desc(sub[column])),
1630
+ ...pkNames.filter((name) => sub[name]).map((name) => asc(sub[name]))
1631
+ ];
1632
+ let query = db.select(Object.fromEntries(pkNames.map((name) => [name, sub[name]]))).from(sub).where(eq(sub[DISTINCT_RN], 1)).orderBy(...outerOrder);
1633
+ if (offset) {
1634
+ query = query.offset(offset);
1635
+ }
1636
+ if (limit != null) {
1637
+ query = query.limit(limit);
1638
+ }
1639
+ return await query;
1640
+ };
1641
+ var primaryKeyRestriction = (table, pkNames, keys) => {
1642
+ const cols = getColumns(table);
1643
+ if (pkNames.length === 1) {
1644
+ const name = pkNames[0];
1645
+ return inArray(
1646
+ cols[name],
1647
+ keys.map((key) => key[name])
1648
+ );
1649
+ }
1650
+ return or(...keys.map((key) => and(...pkNames.map((name) => eq(cols[name], key[name])))));
1651
+ };
1207
1652
  var prepareMutationRelationColumns = (params) => {
1208
1653
  const { relationMap, tables, tableName, typeName, typeNameMapper, table, pkNames, parsedInfo } = params;
1209
1654
  const withParams = relationMap[tableName] ? extractRelationsParams(relationMap, tables, tableName, parsedInfo, typeName, typeNameMapper) : void 0;
1210
1655
  const hasRelations = !!(withParams && Object.keys(withParams).length);
1211
- const baseColumns = extractSelectedColumnsFromTreeSQLFormat(parsedInfo.fieldsByTypeName[typeName], table);
1656
+ const baseColumns = extractSelectedColumnsFromTreeSQLFormat(parsedInfo.fieldsByTypeName[typeName], table, {
1657
+ tableName,
1658
+ relationMap,
1659
+ tables
1660
+ });
1212
1661
  const columns = hasRelations ? withPrimaryKeyColumns(baseColumns, table, pkNames) : baseColumns;
1213
1662
  return { columns, hasRelations, withParams };
1214
1663
  };
1215
- var toGraphQLError = (e) => e instanceof Error ? new GraphQLError2(e.message) : e;
1664
+ var toGraphQLError = (e) => {
1665
+ if (e instanceof GraphQLError3) {
1666
+ return e;
1667
+ }
1668
+ return e instanceof Error ? new GraphQLError3(e.message, { originalError: e }) : e;
1669
+ };
1670
+ var defaultErrorMapper = (error) => {
1671
+ if (error instanceof GraphQLError3 && !error.originalError) {
1672
+ return error;
1673
+ }
1674
+ return new GraphQLError3("Internal server error", {
1675
+ originalError: error instanceof GraphQLError3 ? error.originalError ?? error : error instanceof Error ? error : null,
1676
+ extensions: { code: "INTERNAL_SERVER_ERROR" }
1677
+ });
1678
+ };
1679
+ var applyErrorMapper = (entities, mapError) => {
1680
+ const wrap = (resolve) => (...args) => {
1681
+ try {
1682
+ const result = resolve(...args);
1683
+ if (result && typeof result.then === "function") {
1684
+ return result.then(void 0, (e) => {
1685
+ throw mapError(e);
1686
+ });
1687
+ }
1688
+ return result;
1689
+ } catch (e) {
1690
+ throw mapError(e);
1691
+ }
1692
+ };
1693
+ for (const field of [...Object.values(entities.queries), ...Object.values(entities.mutations)]) {
1694
+ if (field?.resolve) {
1695
+ field.resolve = wrap(field.resolve);
1696
+ }
1697
+ }
1698
+ for (const type of Object.values(entities.types)) {
1699
+ if (typeof type?.getFields !== "function") {
1700
+ continue;
1701
+ }
1702
+ for (const field of Object.values(type.getFields())) {
1703
+ if (field?.resolve) {
1704
+ field.resolve = wrap(field.resolve);
1705
+ }
1706
+ }
1707
+ }
1708
+ for (const tableResolvers of Object.values(entities.fieldResolvers ?? {})) {
1709
+ for (const [relationName, resolve] of Object.entries(tableResolvers)) {
1710
+ tableResolvers[relationName] = wrap(resolve);
1711
+ }
1712
+ }
1713
+ };
1216
1714
  var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes) => {
1217
1715
  const mapped = typeNameMapper?.(tableName);
1218
1716
  const typeName = mapped ? capitalize(mapped.singular) : capitalize(tableName);
1219
1717
  const listFieldName = (mapped?.plural ?? uncapitalize(tableName)) + suffixes.list;
1220
1718
  const singleFieldName = mapped?.singular ?? uncapitalize(tableName) + suffixes.single;
1719
+ const aggregateFieldName = `${mapped?.plural ?? uncapitalize(tableName)}Aggregate`;
1221
1720
  const createArrayFieldName = `${prefixes.insert}${mapped ? capitalize(mapped.plural) : capitalize(tableName)}`;
1222
1721
  const createSingleFieldName = mapped ? `${prefixes.insert}${capitalize(mapped.singular)}` : `${prefixes.insert}${capitalize(tableName)}${suffixes.single}`;
1722
+ const upsertPrefix = prefixes.upsert ?? "upsert";
1723
+ const upsertArrayFieldName = `${upsertPrefix}${mapped ? capitalize(mapped.plural) : capitalize(tableName)}`;
1724
+ const upsertSingleFieldName = mapped ? `${upsertPrefix}${capitalize(mapped.singular)}` : `${upsertPrefix}${capitalize(tableName)}${suffixes.single}`;
1223
1725
  const updateFieldName = `${prefixes.update}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
1224
1726
  const deleteFieldName = `${prefixes.delete}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
1225
1727
  return {
1226
1728
  typeName,
1227
1729
  listFieldName,
1228
1730
  singleFieldName,
1731
+ aggregateFieldName,
1229
1732
  createArrayFieldName,
1230
1733
  createSingleFieldName,
1734
+ upsertArrayFieldName,
1735
+ upsertSingleFieldName,
1231
1736
  updateFieldName,
1232
1737
  deleteFieldName
1233
1738
  };
1234
1739
  };
1235
- var selectArrayArgs = (orderArgs, filterArgs) => ({
1740
+ var selectArrayArgs = (orderArgs, filterArgs, distinctEnum) => ({
1236
1741
  offset: { type: GraphQLInt2 },
1237
1742
  limit: { type: GraphQLInt2 },
1238
1743
  orderBy: { type: orderArgs },
1239
- where: { type: filterArgs }
1744
+ where: { type: filterArgs },
1745
+ ...distinctEnum ? { distinct: { type: new GraphQLList2(new GraphQLNonNull2(distinctEnum)) } } : {}
1240
1746
  });
1241
1747
  var selectSingleArgs = (orderArgs, filterArgs) => ({
1242
1748
  offset: { type: GraphQLInt2 },
@@ -1256,22 +1762,52 @@ var runRelationalSelect = async (opts) => {
1256
1762
  offset,
1257
1763
  orderBy,
1258
1764
  where,
1259
- single
1765
+ single,
1766
+ filterCtx,
1767
+ pkNames
1260
1768
  } = opts;
1769
+ const distinct = opts.distinct?.length ? opts.distinct : void 0;
1770
+ const needsDefaultOrder = single || offset != null || opts.limit != null;
1771
+ let distinctKeys;
1772
+ if (distinct) {
1773
+ distinctKeys = await selectDistinctKeys({
1774
+ db: opts.db,
1775
+ table,
1776
+ tableName,
1777
+ distinct,
1778
+ pkNames: pkNames ?? [],
1779
+ where: where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0,
1780
+ orderBy,
1781
+ limit: single ? 1 : opts.limit,
1782
+ offset
1783
+ });
1784
+ if (!distinctKeys.length) {
1785
+ return single ? void 0 : [];
1786
+ }
1787
+ }
1261
1788
  const params = {
1262
- columns: extractSelectedColumnsFromTree(parsedInfo.fieldsByTypeName[typeName], table),
1263
- offset,
1789
+ columns: extractSelectedColumnsFromTree(parsedInfo.fieldsByTypeName[typeName], table, {
1790
+ tableName,
1791
+ relationMap,
1792
+ tables
1793
+ }),
1794
+ offset: distinctKeys ? void 0 : offset,
1264
1795
  // drizzle-orm v1 RQB calls orderBy/where with the aliased table proxy — use it
1265
1796
  // directly so column refs match the CTE alias.
1266
- orderBy: orderBy ? (aliasedTable) => extractOrderBy(aliasedTable, orderBy) : void 0,
1267
- where: where ? { RAW: (aliasedTable) => extractFilters(aliasedTable, tableName, where) } : void 0,
1268
- with: relationMap[tableName] ? extractRelationsParams(relationMap, tables, tableName, parsedInfo, typeName, typeNameMapper) : void 0
1797
+ orderBy: distinctKeys ? (aliasedTable2) => [
1798
+ ...orderBy ? extractOrderBy(aliasedTable2, orderBy) : [],
1799
+ ...primaryKeyOrderExprs(aliasedTable2, pkNames)
1800
+ ] : orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, orderBy) : needsDefaultOrder && pkNames?.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0,
1801
+ where: distinctKeys ? { RAW: (aliasedTable2) => primaryKeyRestriction(aliasedTable2, pkNames, distinctKeys) } : where ? {
1802
+ RAW: (aliasedTable2) => extractFilters(aliasedTable2, tableName, where, relationFilterCtx(filterCtx, tableName))
1803
+ } : void 0,
1804
+ with: relationMap[tableName] ? extractRelationsParams(relationMap, tables, tableName, parsedInfo, typeName, typeNameMapper, filterCtx) : void 0
1269
1805
  };
1270
1806
  if (single) {
1271
1807
  const result2 = await queryBase.findFirst(params);
1272
1808
  return result2 ? remapToGraphQLSingleOutput(result2, tableName, table, relationMap) : void 0;
1273
1809
  }
1274
- params.limit = opts.limit;
1810
+ params.limit = distinctKeys ? void 0 : opts.limit;
1275
1811
  const result = await queryBase.findMany(params);
1276
1812
  return remapToGraphQLArrayOutput(result, tableName, table, relationMap);
1277
1813
  };
@@ -1344,32 +1880,233 @@ var eagerLoadMutationRelations = async (db, tableName, rows, pkNames, withParams
1344
1880
  };
1345
1881
 
1346
1882
  // src/util/builders/mysql.ts
1347
- var generateSelectArray = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper) => {
1348
- const queryBase = db.query[tableName];
1349
- if (!queryBase) {
1350
- throw new Error(
1351
- `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`
1352
- );
1883
+ import { is as is4, One as One3 } from "drizzle-orm";
1884
+ import { getTableConfig, MySqlTable } from "drizzle-orm/mysql-core";
1885
+ import {
1886
+ GraphQLBoolean as GraphQLBoolean3,
1887
+ GraphQLError as GraphQLError4,
1888
+ GraphQLList as GraphQLList4,
1889
+ GraphQLNonNull as GraphQLNonNull4,
1890
+ GraphQLObjectType as GraphQLObjectType4
1891
+ } from "graphql";
1892
+ import { parseResolveInfo as parseResolveInfo2 } from "graphql-parse-resolve-info";
1893
+
1894
+ // src/util/builders/aggregates.ts
1895
+ import {
1896
+ and as and2,
1897
+ avg,
1898
+ count,
1899
+ countDistinct,
1900
+ extractExtendedColumnType as extractExtendedColumnType2,
1901
+ getColumns as getColumns2,
1902
+ inArray as inArray2,
1903
+ max,
1904
+ min,
1905
+ sum
1906
+ } from "drizzle-orm";
1907
+ import {
1908
+ GraphQLFloat as GraphQLFloat2,
1909
+ GraphQLInt as GraphQLInt3,
1910
+ GraphQLList as GraphQLList3,
1911
+ GraphQLNonNull as GraphQLNonNull3,
1912
+ GraphQLObjectType as GraphQLObjectType3
1913
+ } from "graphql";
1914
+ import { parseResolveInfo } from "graphql-parse-resolve-info";
1915
+ var AGGREGATE_OPS = ["avg", "sum", "min", "max", "countNonNull", "countDistinct"];
1916
+ var COUNT_OPS = /* @__PURE__ */ new Set(["countNonNull", "countDistinct"]);
1917
+ var OP_FNS = {
1918
+ avg,
1919
+ sum,
1920
+ min,
1921
+ max,
1922
+ countNonNull: count,
1923
+ countDistinct
1924
+ };
1925
+ var SEP = "__";
1926
+ var classifyAggregateColumns = (table, tableName) => {
1927
+ const numeric = {};
1928
+ const orderable = {};
1929
+ const all = {};
1930
+ for (const [columnName, column] of Object.entries(getColumns2(table))) {
1931
+ all[columnName] = column;
1932
+ const converted = drizzleColumnToGraphQLType(column, columnName, tableName, true, false, false);
1933
+ const gqlType = converted.type;
1934
+ if (gqlType instanceof GraphQLList3 || gqlType instanceof GraphQLObjectType3) {
1935
+ continue;
1936
+ }
1937
+ const { type: dataType, constraint } = extractExtendedColumnType2(column);
1938
+ if (dataType === "boolean" || dataType === "array" || dataType === "custom") {
1939
+ continue;
1940
+ }
1941
+ if (dataType === "object" && constraint !== "date") {
1942
+ continue;
1943
+ }
1944
+ orderable[columnName] = { column, converted };
1945
+ if (dataType === "number") {
1946
+ numeric[columnName] = column;
1947
+ }
1353
1948
  }
1354
- const queryArgs = selectArrayArgs(orderArgs, filterArgs);
1355
- const table = tables[tableName];
1356
- return {
1357
- name: fieldName,
1358
- resolver: async (_source, args, _context, info) => {
1359
- try {
1360
- const parsedInfo = parseResolveInfo(info, { deep: true });
1361
- return await runRelationalSelect({
1362
- queryBase,
1363
- tables,
1364
- tableName,
1365
- table,
1366
- relationMap,
1367
- typeName,
1368
- typeNameMapper,
1369
- parsedInfo,
1370
- ...args,
1371
- single: false
1372
- });
1949
+ return { numeric, orderable, all };
1950
+ };
1951
+ var generateAggregateTypes = (table, tableName, typeName, cacheCtx) => {
1952
+ const cached = cacheCtx?.aggregateTypeCache.get(tableName);
1953
+ if (cached) {
1954
+ return cached;
1955
+ }
1956
+ const { numeric, orderable, all } = classifyAggregateColumns(table, tableName);
1957
+ const fields = {
1958
+ count: { type: new GraphQLNonNull3(GraphQLInt3) }
1959
+ };
1960
+ if (Object.keys(numeric).length) {
1961
+ for (const op of ["avg", "sum"]) {
1962
+ fields[op] = {
1963
+ type: new GraphQLObjectType3({
1964
+ name: `${typeName}${capitalize(op)}Aggregate`,
1965
+ fields: Object.fromEntries(Object.keys(numeric).map((columnName) => [columnName, { type: GraphQLFloat2 }]))
1966
+ })
1967
+ };
1968
+ }
1969
+ }
1970
+ if (Object.keys(orderable).length) {
1971
+ for (const op of ["min", "max"]) {
1972
+ fields[op] = {
1973
+ type: new GraphQLObjectType3({
1974
+ name: `${typeName}${capitalize(op)}Aggregate`,
1975
+ fields: Object.fromEntries(
1976
+ Object.entries(orderable).map(([columnName, { converted }]) => [
1977
+ columnName,
1978
+ { type: converted.type, description: converted.description }
1979
+ ])
1980
+ )
1981
+ })
1982
+ };
1983
+ }
1984
+ }
1985
+ const countSets = { countNonNull: all, countDistinct: orderable };
1986
+ for (const [op, columns] of Object.entries(countSets)) {
1987
+ const columnNames = Object.keys(columns);
1988
+ if (!columnNames.length) {
1989
+ continue;
1990
+ }
1991
+ fields[op] = {
1992
+ type: new GraphQLObjectType3({
1993
+ name: `${typeName}${capitalize(op)}Aggregate`,
1994
+ fields: Object.fromEntries(
1995
+ columnNames.map((columnName) => [columnName, { type: new GraphQLNonNull3(GraphQLInt3) }])
1996
+ )
1997
+ })
1998
+ };
1999
+ }
2000
+ const aggregateType = new GraphQLObjectType3({
2001
+ name: `${typeName}Aggregate`,
2002
+ fields
2003
+ });
2004
+ cacheCtx?.aggregateTypeCache.set(tableName, aggregateType);
2005
+ return aggregateType;
2006
+ };
2007
+ var parseDriverDateTime = (raw) => {
2008
+ let v = raw.includes(" ") ? raw.replace(" ", "T") : raw;
2009
+ if (!v.includes("T")) {
2010
+ v = `${v}T00:00:00`;
2011
+ }
2012
+ if (!/(?:[Zz]|[+-]\d{2}(?::?\d{2})?)$/.test(v)) {
2013
+ v = `${v}Z`;
2014
+ }
2015
+ const parsed = new Date(v);
2016
+ return Number.isNaN(parsed.getTime()) ? new Date(raw) : parsed;
2017
+ };
2018
+ var aggregateTarget = (table, tableName, typeName) => {
2019
+ const { orderable } = classifyAggregateColumns(table, tableName);
2020
+ return {
2021
+ tableName,
2022
+ typeName,
2023
+ columns: getColumns2(table),
2024
+ dateTimeColumns: new Set(
2025
+ Object.entries(orderable).filter(([, { converted }]) => converted.description === "DateTime").map(([columnName]) => columnName)
2026
+ )
2027
+ };
2028
+ };
2029
+ var parseAggregateRequest = (info, target) => {
2030
+ const parsedInfo = parseResolveInfo(info, { deep: true });
2031
+ const selectionTree = parsedInfo.fieldsByTypeName[`${target.typeName}Aggregate`] ?? {};
2032
+ const request = {
2033
+ count: false,
2034
+ ops: { avg: [], sum: [], min: [], max: [], countNonNull: [], countDistinct: [] },
2035
+ selection: {}
2036
+ };
2037
+ for (const field of Object.values(selectionTree)) {
2038
+ if (field.name === "count") {
2039
+ request.count = true;
2040
+ request.selection.count = count();
2041
+ continue;
2042
+ }
2043
+ if (!AGGREGATE_OPS.includes(field.name)) {
2044
+ continue;
2045
+ }
2046
+ const op = field.name;
2047
+ const subTree = field.fieldsByTypeName[`${target.typeName}${capitalize(op)}Aggregate`];
2048
+ if (!subTree) {
2049
+ continue;
2050
+ }
2051
+ for (const subField of Object.values(subTree)) {
2052
+ const columnName = subField.name;
2053
+ const column = target.columns[columnName];
2054
+ if (!column || request.ops[op].includes(columnName)) {
2055
+ continue;
2056
+ }
2057
+ request.ops[op].push(columnName);
2058
+ request.selection[`${op}${SEP}${columnName}`] = OP_FNS[op](column);
2059
+ }
2060
+ }
2061
+ return request;
2062
+ };
2063
+ var assembleAggregateRow = (row, request, target) => {
2064
+ const result = {};
2065
+ if (request.count) {
2066
+ result.count = row.count == null ? 0 : Number(row.count);
2067
+ }
2068
+ for (const op of AGGREGATE_OPS) {
2069
+ if (!request.ops[op].length) {
2070
+ continue;
2071
+ }
2072
+ const opResult = {};
2073
+ for (const columnName of request.ops[op]) {
2074
+ const value = row[`${op}${SEP}${columnName}`];
2075
+ if (COUNT_OPS.has(op)) {
2076
+ opResult[columnName] = value == null ? 0 : Number(value);
2077
+ } else if (value == null) {
2078
+ opResult[columnName] = null;
2079
+ } else if (op === "avg" || op === "sum") {
2080
+ opResult[columnName] = Number(value);
2081
+ } else {
2082
+ const column = target.columns[columnName];
2083
+ const decoded = typeof value === "string" && target.dateTimeColumns.has(columnName) ? parseDriverDateTime(value) : value;
2084
+ opResult[columnName] = remapToGraphQLCore(columnName, decoded, target.tableName, column);
2085
+ }
2086
+ }
2087
+ result[op] = opResult;
2088
+ }
2089
+ return result;
2090
+ };
2091
+ var generateAggregate = (db, tableName, table, typeName, fieldName, filterArgs, filterCtx) => {
2092
+ const target = aggregateTarget(table, tableName, typeName);
2093
+ const queryArgs = {
2094
+ where: { type: filterArgs }
2095
+ };
2096
+ return {
2097
+ name: fieldName,
2098
+ resolver: async (_source, args, context, info) => {
2099
+ try {
2100
+ const request = parseAggregateRequest(info, target);
2101
+ if (!Object.keys(request.selection).length) {
2102
+ return {};
2103
+ }
2104
+ let query = resolveExecutor(db, context).select(request.selection).from(table);
2105
+ if (args.where) {
2106
+ query = query.where(extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)));
2107
+ }
2108
+ const rows = await query;
2109
+ return assembleAggregateRow(rows[0] ?? {}, request, target);
1373
2110
  } catch (e) {
1374
2111
  throw toGraphQLError(e);
1375
2112
  }
@@ -1377,7 +2114,103 @@ var generateSelectArray = (db, tableName, tables, relationMap, orderArgs, filter
1377
2114
  args: queryArgs
1378
2115
  };
1379
2116
  };
1380
- var generateSelectSingle = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper) => {
2117
+ var GROUP_KEY = "__dgql_group_key";
2118
+ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filterCtx) => {
2119
+ return ({ tableName, relationName, relEntry }) => {
2120
+ const parentTable = tables[tableName];
2121
+ const targetTableName = relEntry.targetTableName;
2122
+ const targetTable = tables[targetTableName];
2123
+ if (!parentTable || !targetTable) {
2124
+ return void 0;
2125
+ }
2126
+ const joinCols = extractRelationJoinColumns(relEntry, parentTable, targetTable);
2127
+ if (!joinCols) {
2128
+ return void 0;
2129
+ }
2130
+ const { localColPropName, foreignCol } = joinCols;
2131
+ const targetTypeName = resolveTypeName(targetTableName, typeNameMapper);
2132
+ const type = generateAggregateTypes(targetTable, targetTableName, targetTypeName, cacheCtx);
2133
+ const target = aggregateTarget(targetTable, targetTableName, targetTypeName);
2134
+ const resolve = async (parent, args, context, info) => {
2135
+ try {
2136
+ const request = parseAggregateRequest(info, target);
2137
+ if (!Object.keys(request.selection).length) {
2138
+ return {};
2139
+ }
2140
+ const localValue = parent[localColPropName];
2141
+ if (localValue == null) {
2142
+ return assembleAggregateRow({}, request, target);
2143
+ }
2144
+ const whereArg = args?.where;
2145
+ const argsKey = JSON.stringify({
2146
+ where: whereArg ?? null,
2147
+ selection: Object.keys(request.selection).sort()
2148
+ });
2149
+ const loaderKey = `${tableName}::${relationName}::aggregate::${argsKey}`;
2150
+ const loader = getOrCreateLoader(context, loaderKey, async (parentIds) => {
2151
+ const executor = resolveExecutor(db, context);
2152
+ const uniqueIds = [...new Set(parentIds)];
2153
+ const whereCondition = and2(
2154
+ inArray2(foreignCol, uniqueIds),
2155
+ whereArg ? extractFilters(targetTable, targetTableName, whereArg, relationFilterCtx(filterCtx, targetTableName)) : void 0
2156
+ );
2157
+ const rows = await executor.select({ [GROUP_KEY]: foreignCol, ...request.selection }).from(targetTable).where(whereCondition).groupBy(foreignCol);
2158
+ const byKey = new Map(rows.map((row) => [row[GROUP_KEY], row]));
2159
+ return parentIds.map((id) => byKey.get(id) ?? {});
2160
+ });
2161
+ return assembleAggregateRow(await loader.load(localValue), request, target);
2162
+ } catch (e) {
2163
+ throw toGraphQLError(e);
2164
+ }
2165
+ };
2166
+ return { type, resolve };
2167
+ };
2168
+ };
2169
+
2170
+ // src/util/builders/mysql.ts
2171
+ var generateSelectArray = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
2172
+ const queryBase = db.query[tableName];
2173
+ if (!queryBase) {
2174
+ throw new Error(
2175
+ `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`
2176
+ );
2177
+ }
2178
+ const table = tables[tableName];
2179
+ const pkNames = mysqlPrimaryKeyPropNames(table);
2180
+ const queryArgs = selectArrayArgs(
2181
+ orderArgs,
2182
+ filterArgs,
2183
+ distinctEnabled ? generateDistinctEnum(table, typeName) : void 0
2184
+ );
2185
+ return {
2186
+ name: fieldName,
2187
+ resolver: async (_source, args, context, info) => {
2188
+ try {
2189
+ const parsedInfo = parseResolveInfo2(info, { deep: true });
2190
+ const { executor, queryBase: requestQueryBase } = resolveQueryExecutor(db, context, tableName, queryBase);
2191
+ return await runRelationalSelect({
2192
+ queryBase: requestQueryBase,
2193
+ tables,
2194
+ tableName,
2195
+ table,
2196
+ relationMap,
2197
+ typeName,
2198
+ typeNameMapper,
2199
+ parsedInfo,
2200
+ ...args,
2201
+ single: false,
2202
+ filterCtx,
2203
+ pkNames,
2204
+ db: executor
2205
+ });
2206
+ } catch (e) {
2207
+ throw toGraphQLError(e);
2208
+ }
2209
+ },
2210
+ args: queryArgs
2211
+ };
2212
+ };
2213
+ var generateSelectSingle = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
1381
2214
  const queryBase = db.query[tableName];
1382
2215
  if (!queryBase) {
1383
2216
  throw new Error(
@@ -1386,13 +2219,15 @@ var generateSelectSingle = (db, tableName, tables, relationMap, orderArgs, filte
1386
2219
  }
1387
2220
  const queryArgs = selectSingleArgs(orderArgs, filterArgs);
1388
2221
  const table = tables[tableName];
2222
+ const pkNames = mysqlPrimaryKeyPropNames(table);
1389
2223
  return {
1390
2224
  name: fieldName,
1391
- resolver: async (_source, args, _context, info) => {
2225
+ resolver: async (_source, args, context, info) => {
1392
2226
  try {
1393
- const parsedInfo = parseResolveInfo(info, { deep: true });
2227
+ const parsedInfo = parseResolveInfo2(info, { deep: true });
2228
+ const { executor, queryBase: requestQueryBase } = resolveQueryExecutor(db, context, tableName, queryBase);
1394
2229
  return await runRelationalSelect({
1395
- queryBase,
2230
+ queryBase: requestQueryBase,
1396
2231
  tables,
1397
2232
  tableName,
1398
2233
  table,
@@ -1401,7 +2236,10 @@ var generateSelectSingle = (db, tableName, tables, relationMap, orderArgs, filte
1401
2236
  typeNameMapper,
1402
2237
  parsedInfo,
1403
2238
  ...args,
1404
- single: true
2239
+ single: true,
2240
+ filterCtx,
2241
+ pkNames,
2242
+ db: executor
1405
2243
  });
1406
2244
  } catch (e) {
1407
2245
  throw toGraphQLError(e);
@@ -1413,18 +2251,18 @@ var generateSelectSingle = (db, tableName, tables, relationMap, orderArgs, filte
1413
2251
  var generateInsertArray = (db, _tableName, table, baseType, fieldName) => {
1414
2252
  const queryArgs = {
1415
2253
  values: {
1416
- type: new GraphQLNonNull3(new GraphQLList3(new GraphQLNonNull3(baseType)))
2254
+ type: new GraphQLNonNull4(new GraphQLList4(new GraphQLNonNull4(baseType)))
1417
2255
  }
1418
2256
  };
1419
2257
  return {
1420
2258
  name: fieldName,
1421
- resolver: async (_source, args, _context, _info) => {
2259
+ resolver: async (_source, args, context, _info) => {
1422
2260
  try {
1423
2261
  const input = remapFromGraphQLArrayInput(args.values, table);
1424
2262
  if (!input.length) {
1425
- throw new GraphQLError3("No values were provided!");
2263
+ throw new GraphQLError4("No values were provided!");
1426
2264
  }
1427
- await db.insert(table).values(input);
2265
+ await resolveExecutor(db, context).insert(table).values(input);
1428
2266
  return { isSuccess: true };
1429
2267
  } catch (e) {
1430
2268
  throw toGraphQLError(e);
@@ -1436,15 +2274,15 @@ var generateInsertArray = (db, _tableName, table, baseType, fieldName) => {
1436
2274
  var generateInsertSingle = (db, _tableName, table, baseType, fieldName) => {
1437
2275
  const queryArgs = {
1438
2276
  values: {
1439
- type: new GraphQLNonNull3(baseType)
2277
+ type: new GraphQLNonNull4(baseType)
1440
2278
  }
1441
2279
  };
1442
2280
  return {
1443
2281
  name: fieldName,
1444
- resolver: async (_source, args, _context, _info) => {
2282
+ resolver: async (_source, args, context, _info) => {
1445
2283
  try {
1446
2284
  const input = remapFromGraphQLSingleInput(args.values, table);
1447
- await db.insert(table).values(input);
2285
+ await resolveExecutor(db, context).insert(table).values(input);
1448
2286
  return { isSuccess: true };
1449
2287
  } catch (e) {
1450
2288
  throw toGraphQLError(e);
@@ -1453,10 +2291,52 @@ var generateInsertSingle = (db, _tableName, table, baseType, fieldName) => {
1453
2291
  args: queryArgs
1454
2292
  };
1455
2293
  };
1456
- var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName) => {
2294
+ var generateUpsert = (db, table, baseType, onConflictType, fieldName, single) => {
2295
+ const queryArgs = {
2296
+ values: {
2297
+ type: single ? new GraphQLNonNull4(baseType) : new GraphQLNonNull4(new GraphQLList4(new GraphQLNonNull4(baseType)))
2298
+ },
2299
+ onConflict: {
2300
+ type: onConflictType,
2301
+ description: "How a conflicting row is resolved. Defaults to overwriting it."
2302
+ }
2303
+ };
2304
+ const pkNames = mysqlPrimaryKeyPropNames(table);
2305
+ return {
2306
+ name: fieldName,
2307
+ resolver: async (_source, args, context, _info) => {
2308
+ try {
2309
+ const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
2310
+ if (!input.length) {
2311
+ throw new GraphQLError4("No values were provided!");
2312
+ }
2313
+ const plan = resolveConflictPlan({
2314
+ table,
2315
+ values: input,
2316
+ onConflict: args.onConflict,
2317
+ pkNames,
2318
+ uniqueSets: [],
2319
+ excludedRef: mysqlValuesColumnRef,
2320
+ withTarget: false
2321
+ });
2322
+ const executor = resolveExecutor(db, context);
2323
+ if (plan.action === "NOTHING") {
2324
+ await executor.insert(table).ignore().values(input);
2325
+ } else {
2326
+ await executor.insert(table).values(input).onDuplicateKeyUpdate({ set: plan.set });
2327
+ }
2328
+ return { isSuccess: true };
2329
+ } catch (e) {
2330
+ throw toGraphQLError(e);
2331
+ }
2332
+ },
2333
+ args: queryArgs
2334
+ };
2335
+ };
2336
+ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filterCtx) => {
1457
2337
  const queryArgs = {
1458
2338
  set: {
1459
- type: new GraphQLNonNull3(setArgs)
2339
+ type: new GraphQLNonNull4(setArgs)
1460
2340
  },
1461
2341
  where: {
1462
2342
  type: filterArgs
@@ -1464,16 +2344,17 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName) => {
1464
2344
  };
1465
2345
  return {
1466
2346
  name: fieldName,
1467
- resolver: async (_source, args, _context, _info) => {
2347
+ resolver: async (_source, args, context, _info) => {
1468
2348
  try {
1469
2349
  const { where, set } = args;
1470
2350
  const input = remapFromGraphQLSingleInput(set, table);
1471
2351
  if (!Object.keys(input).length) {
1472
- throw new GraphQLError3("Unable to update with no values specified!");
2352
+ throw new GraphQLError4("Unable to update with no values specified!");
1473
2353
  }
1474
- let query = db.update(table).set(input);
2354
+ const executor = resolveExecutor(db, context);
2355
+ let query = executor.update(table).set(input);
1475
2356
  if (where) {
1476
- const filters = extractFilters(table, tableName, where);
2357
+ const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
1477
2358
  query = query.where(filters);
1478
2359
  }
1479
2360
  await query;
@@ -1485,7 +2366,7 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName) => {
1485
2366
  args: queryArgs
1486
2367
  };
1487
2368
  };
1488
- var generateDelete = (db, tableName, table, filterArgs, fieldName) => {
2369
+ var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) => {
1489
2370
  const queryArgs = {
1490
2371
  where: {
1491
2372
  type: filterArgs
@@ -1493,12 +2374,13 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName) => {
1493
2374
  };
1494
2375
  return {
1495
2376
  name: fieldName,
1496
- resolver: async (_source, args, _context, _info) => {
2377
+ resolver: async (_source, args, context, _info) => {
1497
2378
  try {
1498
2379
  const { where } = args;
1499
- let query = db.delete(table);
2380
+ const executor = resolveExecutor(db, context);
2381
+ let query = executor.delete(table);
1500
2382
  if (where) {
1501
- const filters = extractFilters(table, tableName, where);
2383
+ const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
1502
2384
  query = query.where(filters);
1503
2385
  }
1504
2386
  await query;
@@ -1511,7 +2393,8 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName) => {
1511
2393
  };
1512
2394
  };
1513
2395
  var mysqlPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig);
1514
- var generateSchemaData = (db, schema, relations, relationsDepthLimit, prefixes, suffixes, typeNameMapper, shouldEagerLoad = () => true) => {
2396
+ var generateSchemaData = (db, schema, relations, options) => {
2397
+ const { relationsDepthLimit, prefixes, suffixes, typeNameMapper, shouldEagerLoad, features } = options;
1515
2398
  const rawSchema = schema;
1516
2399
  const schemaEntries = Object.entries(rawSchema);
1517
2400
  const tableEntries = schemaEntries.filter(([_key, value]) => is4(value, MySqlTable));
@@ -1524,7 +2407,8 @@ var generateSchemaData = (db, schema, relations, relationsDepthLimit, prefixes,
1524
2407
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
1525
2408
  attachTargetPrimaryKeys(namedRelations, tables, mysqlPrimaryKeyPropNames);
1526
2409
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
1527
- const resolverFactory = createRelationResolverFactory(db, tables);
2410
+ const filterCtx = { tables, relationMap: namedRelations };
2411
+ const resolverFactory = createRelationResolverFactory(db, tables, filterCtx);
1528
2412
  const cacheCtx = {
1529
2413
  genericFilterCache: /* @__PURE__ */ new Map(),
1530
2414
  objectTypeCache: /* @__PURE__ */ new Map(),
@@ -1532,8 +2416,11 @@ var generateSchemaData = (db, schema, relations, relationsDepthLimit, prefixes,
1532
2416
  fullyBuiltTables: /* @__PURE__ */ new Set(),
1533
2417
  relationTypeCache: /* @__PURE__ */ new Map(),
1534
2418
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
1535
- filterTypeCache: /* @__PURE__ */ new WeakMap()
2419
+ filterTypeCache: /* @__PURE__ */ new WeakMap(),
2420
+ listRelationFilterCache: /* @__PURE__ */ new Map(),
2421
+ aggregateTypeCache: /* @__PURE__ */ new Map()
1536
2422
  };
2423
+ const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
1537
2424
  const queries = {};
1538
2425
  const mutations = {};
1539
2426
  const gqlSchemaTypes = Object.fromEntries(
@@ -1549,22 +2436,24 @@ var generateSchemaData = (db, schema, relations, relationsDepthLimit, prefixes,
1549
2436
  typeNameMapper,
1550
2437
  prefixes.insert,
1551
2438
  prefixes.update,
1552
- resolverFactory
2439
+ resolverFactory,
2440
+ relationAggregateFactory
1553
2441
  )
1554
2442
  ])
1555
2443
  );
1556
- const mutationReturnType = new GraphQLObjectType3({
2444
+ const mutationReturnType = new GraphQLObjectType4({
1557
2445
  name: "MutationReturn",
1558
2446
  fields: {
1559
2447
  isSuccess: {
1560
- type: new GraphQLNonNull3(GraphQLBoolean3)
2448
+ type: new GraphQLNonNull4(GraphQLBoolean3)
1561
2449
  }
1562
2450
  }
1563
2451
  });
1564
2452
  const inputs = {};
1565
- const outputs = {
1566
- MutationReturn: mutationReturnType
1567
- };
2453
+ const outputs = {};
2454
+ if (features.insert || features.upsert || features.update || features.delete) {
2455
+ outputs.MutationReturn = mutationReturnType;
2456
+ }
1568
2457
  for (const [tableName, tableTypes] of Object.entries(gqlSchemaTypes)) {
1569
2458
  const { insertInput, updateInput, tableFilters, tableOrder } = tableTypes.inputs;
1570
2459
  const { selectSingleOutput, selectArrOutput } = tableTypes.outputs;
@@ -1572,8 +2461,11 @@ var generateSchemaData = (db, schema, relations, relationsDepthLimit, prefixes,
1572
2461
  typeName,
1573
2462
  listFieldName,
1574
2463
  singleFieldName,
2464
+ aggregateFieldName,
1575
2465
  createArrayFieldName,
1576
2466
  createSingleFieldName,
2467
+ upsertArrayFieldName,
2468
+ upsertSingleFieldName,
1577
2469
  updateFieldName,
1578
2470
  deleteFieldName
1579
2471
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
@@ -1586,7 +2478,9 @@ var generateSchemaData = (db, schema, relations, relationsDepthLimit, prefixes,
1586
2478
  tableFilters,
1587
2479
  listFieldName,
1588
2480
  typeName,
1589
- typeNameMapper
2481
+ typeNameMapper,
2482
+ filterCtx,
2483
+ features.distinct
1590
2484
  );
1591
2485
  const selectSingleGenerated = generateSelectSingle(
1592
2486
  db,
@@ -1597,37 +2491,40 @@ var generateSchemaData = (db, schema, relations, relationsDepthLimit, prefixes,
1597
2491
  tableFilters,
1598
2492
  singleFieldName,
1599
2493
  typeName,
1600
- typeNameMapper
1601
- );
1602
- const insertArrGenerated = generateInsertArray(
1603
- db,
1604
- tableName,
1605
- schema[tableName],
1606
- insertInput,
1607
- createArrayFieldName
1608
- );
1609
- const insertSingleGenerated = generateInsertSingle(
1610
- db,
1611
- tableName,
1612
- schema[tableName],
1613
- insertInput,
1614
- createSingleFieldName
2494
+ typeNameMapper,
2495
+ filterCtx
1615
2496
  );
1616
- const updateGenerated = generateUpdate(
2497
+ const insertArrGenerated = features.insert ? generateInsertArray(db, tableName, schema[tableName], insertInput, createArrayFieldName) : void 0;
2498
+ const insertSingleGenerated = features.insert ? generateInsertSingle(db, tableName, schema[tableName], insertInput, createSingleFieldName) : void 0;
2499
+ const onConflictInput = features.upsert ? generateOnConflictInput({
2500
+ table: schema[tableName],
2501
+ typeName,
2502
+ uniqueSets: [],
2503
+ tableFilters,
2504
+ withTarget: false
2505
+ }) : void 0;
2506
+ const upsertArrGenerated = onConflictInput ? generateUpsert(db, schema[tableName], insertInput, onConflictInput, upsertArrayFieldName, false) : void 0;
2507
+ const upsertSingleGenerated = onConflictInput ? generateUpsert(db, schema[tableName], insertInput, onConflictInput, upsertSingleFieldName, true) : void 0;
2508
+ const updateGenerated = features.update ? generateUpdate(
1617
2509
  db,
1618
2510
  tableName,
1619
2511
  schema[tableName],
1620
2512
  updateInput,
1621
2513
  tableFilters,
1622
- updateFieldName
1623
- );
1624
- const deleteGenerated = generateDelete(
2514
+ updateFieldName,
2515
+ filterCtx
2516
+ ) : void 0;
2517
+ const deleteGenerated = features.delete ? generateDelete(db, tableName, schema[tableName], tableFilters, deleteFieldName, filterCtx) : void 0;
2518
+ const aggregateType = features.aggregates ? generateAggregateTypes(schema[tableName], tableName, typeName, cacheCtx) : void 0;
2519
+ const aggregateGenerated = features.aggregates ? generateAggregate(
1625
2520
  db,
1626
2521
  tableName,
1627
2522
  schema[tableName],
2523
+ typeName,
2524
+ aggregateFieldName,
1628
2525
  tableFilters,
1629
- deleteFieldName
1630
- );
2526
+ filterCtx
2527
+ ) : void 0;
1631
2528
  queries[selectArrGenerated.name] = {
1632
2529
  type: selectArrOutput,
1633
2530
  args: selectArrGenerated.args,
@@ -1638,30 +2535,44 @@ var generateSchemaData = (db, schema, relations, relationsDepthLimit, prefixes,
1638
2535
  args: selectSingleGenerated.args,
1639
2536
  resolve: selectSingleGenerated.resolver
1640
2537
  };
1641
- mutations[insertArrGenerated.name] = {
1642
- type: mutationReturnType,
1643
- args: insertArrGenerated.args,
1644
- resolve: insertArrGenerated.resolver
1645
- };
1646
- mutations[insertSingleGenerated.name] = {
1647
- type: mutationReturnType,
1648
- args: insertSingleGenerated.args,
1649
- resolve: insertSingleGenerated.resolver
1650
- };
1651
- mutations[updateGenerated.name] = {
1652
- type: mutationReturnType,
1653
- args: updateGenerated.args,
1654
- resolve: updateGenerated.resolver
1655
- };
1656
- mutations[deleteGenerated.name] = {
1657
- type: mutationReturnType,
1658
- args: deleteGenerated.args,
1659
- resolve: deleteGenerated.resolver
1660
- };
1661
- [insertInput, updateInput, tableFilters, tableOrder].forEach((e) => {
2538
+ if (aggregateGenerated && aggregateType) {
2539
+ queries[aggregateGenerated.name] = {
2540
+ type: new GraphQLNonNull4(aggregateType),
2541
+ args: aggregateGenerated.args,
2542
+ resolve: aggregateGenerated.resolver
2543
+ };
2544
+ }
2545
+ for (const generated of [
2546
+ insertArrGenerated,
2547
+ insertSingleGenerated,
2548
+ upsertArrGenerated,
2549
+ upsertSingleGenerated,
2550
+ updateGenerated,
2551
+ deleteGenerated
2552
+ ]) {
2553
+ if (generated) {
2554
+ mutations[generated.name] = {
2555
+ type: mutationReturnType,
2556
+ args: generated.args,
2557
+ resolve: generated.resolver
2558
+ };
2559
+ }
2560
+ }
2561
+ const activeInputs = [
2562
+ // The insert input types the upsert mutations too, so either feature keeps it.
2563
+ ...features.insert || onConflictInput ? [insertInput] : [],
2564
+ ...onConflictInput ? [onConflictInput] : [],
2565
+ ...features.update ? [updateInput] : [],
2566
+ tableFilters,
2567
+ tableOrder
2568
+ ];
2569
+ activeInputs.forEach((e) => {
1662
2570
  inputs[e.name] = e;
1663
2571
  });
1664
2572
  outputs[selectSingleOutput.name] = selectSingleOutput;
2573
+ if (aggregateType) {
2574
+ outputs[aggregateType.name] = aggregateType;
2575
+ }
1665
2576
  }
1666
2577
  const fieldResolvers = {};
1667
2578
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -1684,23 +2595,29 @@ var generateSchemaData = (db, schema, relations, relationsDepthLimit, prefixes,
1684
2595
  import { is as is5, One as One4 } from "drizzle-orm";
1685
2596
  import { getTableConfig as getTableConfig2, PgTable } from "drizzle-orm/pg-core";
1686
2597
  import {
1687
- GraphQLError as GraphQLError4,
1688
- GraphQLList as GraphQLList4,
1689
- GraphQLNonNull as GraphQLNonNull4
2598
+ GraphQLError as GraphQLError5,
2599
+ GraphQLList as GraphQLList5,
2600
+ GraphQLNonNull as GraphQLNonNull5
1690
2601
  } from "graphql";
1691
- import { parseResolveInfo as parseResolveInfo2 } from "graphql-parse-resolve-info";
1692
- var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper) => {
2602
+ import { parseResolveInfo as parseResolveInfo3 } from "graphql-parse-resolve-info";
2603
+ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
1693
2604
  const queryBase = db.query[tableName];
1694
- const queryArgs = selectArrayArgs(orderArgs, filterArgs);
1695
2605
  const table = tables[tableName];
2606
+ const pkNames = pgPrimaryKeyPropNames(table);
2607
+ const queryArgs = selectArrayArgs(
2608
+ orderArgs,
2609
+ filterArgs,
2610
+ distinctEnabled ? generateDistinctEnum(table, typeName) : void 0
2611
+ );
1696
2612
  return {
1697
2613
  name: fieldName,
1698
- resolver: async (_source, args, _context, info) => {
2614
+ resolver: async (_source, args, context, info) => {
1699
2615
  try {
1700
- const parsedInfo = parseResolveInfo2(info, { deep: true });
1701
- if (queryBase) {
2616
+ const parsedInfo = parseResolveInfo3(info, { deep: true });
2617
+ const { executor, queryBase: requestQueryBase } = resolveQueryExecutor(db, context, tableName, queryBase);
2618
+ if (requestQueryBase) {
1702
2619
  return await runRelationalSelect({
1703
- queryBase,
2620
+ queryBase: requestQueryBase,
1704
2621
  tables,
1705
2622
  tableName,
1706
2623
  table,
@@ -1709,26 +2626,57 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
1709
2626
  typeNameMapper,
1710
2627
  parsedInfo,
1711
2628
  ...args,
1712
- single: false
2629
+ single: false,
2630
+ filterCtx,
2631
+ pkNames,
2632
+ db: executor
1713
2633
  });
1714
2634
  }
1715
- const { offset, limit, orderBy, where } = args;
2635
+ const { offset, limit, orderBy, where, distinct } = args;
1716
2636
  const selectedColumnsSql = extractSelectedColumnsFromTreeSQLFormat(
1717
2637
  parsedInfo.fieldsByTypeName[typeName],
1718
- table
2638
+ table,
2639
+ { tableName, relationMap, tables }
1719
2640
  );
1720
- let q = db.select(selectedColumnsSql).from(table);
1721
- if (where) {
1722
- q = q.where(extractFilters(table, tableName, where));
2641
+ const whereSql = where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0;
2642
+ let distinctKeys;
2643
+ if (distinct?.length) {
2644
+ distinctKeys = await selectDistinctKeys({
2645
+ db: executor,
2646
+ table,
2647
+ tableName,
2648
+ distinct,
2649
+ pkNames,
2650
+ where: whereSql,
2651
+ orderBy,
2652
+ limit,
2653
+ offset
2654
+ });
2655
+ if (!distinctKeys.length) {
2656
+ return [];
2657
+ }
1723
2658
  }
1724
- if (orderBy) {
1725
- q = q.orderBy(...extractOrderBy(table, orderBy));
2659
+ let q = executor.select(selectedColumnsSql).from(table);
2660
+ if (distinctKeys) {
2661
+ q = q.where(primaryKeyRestriction(table, pkNames, distinctKeys));
2662
+ } else if (whereSql) {
2663
+ q = q.where(whereSql);
1726
2664
  }
1727
- if (offset) {
1728
- q = q.offset(offset);
2665
+ if (orderBy) {
2666
+ q = q.orderBy(
2667
+ ...extractOrderBy(table, orderBy),
2668
+ ...distinctKeys ? primaryKeyOrderExprs(table, pkNames) : []
2669
+ );
2670
+ } else if ((distinctKeys || offset != null || limit != null) && pkNames.length) {
2671
+ q = q.orderBy(...primaryKeyOrderExprs(table, pkNames));
1729
2672
  }
1730
- if (limit) {
1731
- q = q.limit(limit);
2673
+ if (!distinctKeys) {
2674
+ if (offset) {
2675
+ q = q.offset(offset);
2676
+ }
2677
+ if (limit) {
2678
+ q = q.limit(limit);
2679
+ }
1732
2680
  }
1733
2681
  return remapToGraphQLArrayOutput(await q, tableName, table, relationMap);
1734
2682
  } catch (e) {
@@ -1738,18 +2686,20 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
1738
2686
  args: queryArgs
1739
2687
  };
1740
2688
  };
1741
- var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper) => {
2689
+ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
1742
2690
  const queryBase = db.query[tableName];
1743
2691
  const queryArgs = selectSingleArgs(orderArgs, filterArgs);
1744
2692
  const table = tables[tableName];
2693
+ const pkNames = pgPrimaryKeyPropNames(table);
1745
2694
  return {
1746
2695
  name: fieldName,
1747
- resolver: async (_source, args, _context, info) => {
2696
+ resolver: async (_source, args, context, info) => {
1748
2697
  try {
1749
- const parsedInfo = parseResolveInfo2(info, { deep: true });
1750
- if (queryBase) {
2698
+ const parsedInfo = parseResolveInfo3(info, { deep: true });
2699
+ const { executor, queryBase: requestQueryBase } = resolveQueryExecutor(db, context, tableName, queryBase);
2700
+ if (requestQueryBase) {
1751
2701
  return await runRelationalSelect({
1752
- queryBase,
2702
+ queryBase: requestQueryBase,
1753
2703
  tables,
1754
2704
  tableName,
1755
2705
  table,
@@ -1758,20 +2708,26 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
1758
2708
  typeNameMapper,
1759
2709
  parsedInfo,
1760
2710
  ...args,
1761
- single: true
2711
+ single: true,
2712
+ filterCtx,
2713
+ pkNames,
2714
+ db: executor
1762
2715
  });
1763
2716
  }
1764
2717
  const { offset, orderBy, where } = args;
1765
2718
  const selectedColumnsSql = extractSelectedColumnsFromTreeSQLFormat(
1766
2719
  parsedInfo.fieldsByTypeName[typeName],
1767
- table
2720
+ table,
2721
+ { tableName, relationMap, tables }
1768
2722
  );
1769
- let q = db.select(selectedColumnsSql).from(table);
2723
+ let q = executor.select(selectedColumnsSql).from(table);
1770
2724
  if (where) {
1771
- q = q.where(extractFilters(table, tableName, where));
2725
+ q = q.where(extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)));
1772
2726
  }
1773
2727
  if (orderBy) {
1774
2728
  q = q.orderBy(...extractOrderBy(table, orderBy));
2729
+ } else if (pkNames.length) {
2730
+ q = q.orderBy(...primaryKeyOrderExprs(table, pkNames));
1775
2731
  }
1776
2732
  if (offset) {
1777
2733
  q = q.offset(offset);
@@ -1790,19 +2746,19 @@ var pgPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, g
1790
2746
  var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false) => {
1791
2747
  const queryArgs = {
1792
2748
  values: {
1793
- type: new GraphQLNonNull4(new GraphQLList4(new GraphQLNonNull4(baseType)))
2749
+ type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(baseType)))
1794
2750
  }
1795
2751
  };
1796
2752
  const pkNames = pgPrimaryKeyPropNames(table);
1797
2753
  return {
1798
2754
  name: fieldName,
1799
- resolver: async (_source, args, _context, info) => {
2755
+ resolver: async (_source, args, context, info) => {
1800
2756
  try {
1801
2757
  const input = remapFromGraphQLArrayInput(args.values, table);
1802
2758
  if (!input.length) {
1803
- throw new GraphQLError4("No values were provided!");
2759
+ throw new GraphQLError5("No values were provided!");
1804
2760
  }
1805
- const parsedInfo = parseResolveInfo2(info, {
2761
+ const parsedInfo = parseResolveInfo3(info, {
1806
2762
  deep: true
1807
2763
  });
1808
2764
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -1815,12 +2771,13 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
1815
2771
  pkNames,
1816
2772
  parsedInfo
1817
2773
  });
1818
- let query = db.insert(table).values(input).returning(columns);
2774
+ const executor = resolveExecutor(db, context);
2775
+ let query = executor.insert(table).values(input).returning(columns);
1819
2776
  if (conflictDoNothing) {
1820
2777
  query = query.onConflictDoNothing();
1821
2778
  }
1822
2779
  const result = await query;
1823
- const enriched = hasRelations ? await eagerLoadMutationRelations(db, tableName, result, pkNames, withParams) : result;
2780
+ const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
1824
2781
  return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
1825
2782
  } catch (e) {
1826
2783
  throw toGraphQLError(e);
@@ -1832,16 +2789,16 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
1832
2789
  var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false) => {
1833
2790
  const queryArgs = {
1834
2791
  values: {
1835
- type: new GraphQLNonNull4(baseType)
2792
+ type: new GraphQLNonNull5(baseType)
1836
2793
  }
1837
2794
  };
1838
2795
  const pkNames = pgPrimaryKeyPropNames(table);
1839
2796
  return {
1840
2797
  name: fieldName,
1841
- resolver: async (_source, args, _context, info) => {
2798
+ resolver: async (_source, args, context, info) => {
1842
2799
  try {
1843
2800
  const input = remapFromGraphQLSingleInput(args.values, table);
1844
- const parsedInfo = parseResolveInfo2(info, {
2801
+ const parsedInfo = parseResolveInfo3(info, {
1845
2802
  deep: true
1846
2803
  });
1847
2804
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -1854,7 +2811,8 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
1854
2811
  pkNames,
1855
2812
  parsedInfo
1856
2813
  });
1857
- let query = db.insert(table).values(input).returning(columns);
2814
+ const executor = resolveExecutor(db, context);
2815
+ let query = executor.insert(table).values(input).returning(columns);
1858
2816
  if (conflictDoNothing) {
1859
2817
  query = query.onConflictDoNothing();
1860
2818
  }
@@ -1862,7 +2820,7 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
1862
2820
  if (!result[0]) {
1863
2821
  return void 0;
1864
2822
  }
1865
- const enriched = hasRelations ? await eagerLoadMutationRelations(db, tableName, result, pkNames, withParams) : result;
2823
+ const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
1866
2824
  return remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap);
1867
2825
  } catch (e) {
1868
2826
  throw toGraphQLError(e);
@@ -1871,10 +2829,66 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
1871
2829
  args: queryArgs
1872
2830
  };
1873
2831
  };
1874
- var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper) => {
2832
+ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx) => {
2833
+ const queryArgs = {
2834
+ values: {
2835
+ type: single ? new GraphQLNonNull5(baseType) : new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(baseType)))
2836
+ },
2837
+ onConflict: {
2838
+ type: onConflictType,
2839
+ description: "How a conflicting row is resolved. Defaults to overwriting it on the primary key."
2840
+ }
2841
+ };
2842
+ const pkNames = pgPrimaryKeyPropNames(table);
2843
+ return {
2844
+ name: fieldName,
2845
+ resolver: async (_source, args, context, info) => {
2846
+ try {
2847
+ const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
2848
+ if (!input.length) {
2849
+ throw new GraphQLError5("No values were provided!");
2850
+ }
2851
+ const parsedInfo = parseResolveInfo3(info, { deep: true });
2852
+ const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
2853
+ relationMap,
2854
+ tables,
2855
+ tableName,
2856
+ typeName,
2857
+ typeNameMapper,
2858
+ table,
2859
+ pkNames,
2860
+ parsedInfo
2861
+ });
2862
+ const plan = resolveConflictPlan({
2863
+ table,
2864
+ values: input,
2865
+ onConflict: args.onConflict,
2866
+ pkNames,
2867
+ uniqueSets,
2868
+ excludedRef: excludedColumnRef,
2869
+ withTarget: true,
2870
+ buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
2871
+ });
2872
+ const executor = resolveExecutor(db, context);
2873
+ let query = executor.insert(table).values(input).returning(columns);
2874
+ query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
2875
+ const result = await query;
2876
+ if (single && !result[0]) {
2877
+ return void 0;
2878
+ }
2879
+ const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
2880
+ return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
2881
+ } catch (e) {
2882
+ throw toGraphQLError(e);
2883
+ }
2884
+ },
2885
+ args: queryArgs
2886
+ };
2887
+ };
2888
+ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
1875
2889
  const queryArgs = {
1876
2890
  set: {
1877
- type: new GraphQLNonNull4(setArgs)
2891
+ type: new GraphQLNonNull5(setArgs)
1878
2892
  },
1879
2893
  where: {
1880
2894
  type: filterArgs
@@ -1883,10 +2897,10 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
1883
2897
  const pkNames = pgPrimaryKeyPropNames(table);
1884
2898
  return {
1885
2899
  name: fieldName,
1886
- resolver: async (_source, args, _context, info) => {
2900
+ resolver: async (_source, args, context, info) => {
1887
2901
  try {
1888
2902
  const { where, set } = args;
1889
- const parsedInfo = parseResolveInfo2(info, {
2903
+ const parsedInfo = parseResolveInfo3(info, {
1890
2904
  deep: true
1891
2905
  });
1892
2906
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -1901,16 +2915,17 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
1901
2915
  });
1902
2916
  const input = remapFromGraphQLSingleInput(set, table);
1903
2917
  if (!Object.keys(input).length) {
1904
- throw new GraphQLError4("Unable to update with no values specified!");
2918
+ throw new GraphQLError5("Unable to update with no values specified!");
1905
2919
  }
1906
- let query = db.update(table).set(input);
2920
+ const executor = resolveExecutor(db, context);
2921
+ let query = executor.update(table).set(input);
1907
2922
  if (where) {
1908
- const filters = extractFilters(table, tableName, where);
2923
+ const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
1909
2924
  query = query.where(filters);
1910
2925
  }
1911
2926
  query = query.returning(columns);
1912
2927
  const result = await query;
1913
- const enriched = hasRelations ? await eagerLoadMutationRelations(db, tableName, result, pkNames, withParams) : result;
2928
+ const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
1914
2929
  return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
1915
2930
  } catch (e) {
1916
2931
  throw toGraphQLError(e);
@@ -1919,7 +2934,7 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
1919
2934
  args: queryArgs
1920
2935
  };
1921
2936
  };
1922
- var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName) => {
2937
+ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
1923
2938
  const queryArgs = {
1924
2939
  where: {
1925
2940
  type: filterArgs
@@ -1927,19 +2942,21 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName) =>
1927
2942
  };
1928
2943
  return {
1929
2944
  name: fieldName,
1930
- resolver: async (_source, args, _context, info) => {
2945
+ resolver: async (_source, args, context, info) => {
1931
2946
  try {
1932
2947
  const { where } = args;
1933
- const parsedInfo = parseResolveInfo2(info, {
2948
+ const parsedInfo = parseResolveInfo3(info, {
1934
2949
  deep: true
1935
2950
  });
1936
2951
  const columns = extractSelectedColumnsFromTreeSQLFormat(
1937
2952
  parsedInfo.fieldsByTypeName[typeName],
1938
- table
2953
+ table,
2954
+ selectionCtx
1939
2955
  );
1940
- let query = db.delete(table);
2956
+ const executor = resolveExecutor(db, context);
2957
+ let query = executor.delete(table);
1941
2958
  if (where) {
1942
- const filters = extractFilters(table, tableName, where);
2959
+ const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
1943
2960
  query = query.where(filters);
1944
2961
  }
1945
2962
  query = query.returning(columns);
@@ -1952,7 +2969,8 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName) =>
1952
2969
  args: queryArgs
1953
2970
  };
1954
2971
  };
1955
- function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixes, suffixes, conflictDoNothing = false, typeNameMapper, shouldEagerLoad = () => true) {
2972
+ function generateSchemaData2(db, schema, relations, options) {
2973
+ const { relationsDepthLimit, prefixes, suffixes, conflictDoNothing, typeNameMapper, shouldEagerLoad, features } = options;
1956
2974
  const schemaEntries = Object.entries(schema);
1957
2975
  const tableEntries = schemaEntries.filter(([_key, value]) => is5(value, PgTable));
1958
2976
  const tables = Object.fromEntries(tableEntries);
@@ -1964,7 +2982,8 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
1964
2982
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
1965
2983
  attachTargetPrimaryKeys(namedRelations, tables, pgPrimaryKeyPropNames);
1966
2984
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
1967
- const resolverFactory = createRelationResolverFactory(db, tables);
2985
+ const filterCtx = { tables, relationMap: namedRelations };
2986
+ const resolverFactory = createRelationResolverFactory(db, tables, filterCtx);
1968
2987
  const cacheCtx = {
1969
2988
  genericFilterCache: /* @__PURE__ */ new Map(),
1970
2989
  objectTypeCache: /* @__PURE__ */ new Map(),
@@ -1972,8 +2991,11 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
1972
2991
  fullyBuiltTables: /* @__PURE__ */ new Set(),
1973
2992
  relationTypeCache: /* @__PURE__ */ new Map(),
1974
2993
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
1975
- filterTypeCache: /* @__PURE__ */ new WeakMap()
2994
+ filterTypeCache: /* @__PURE__ */ new WeakMap(),
2995
+ listRelationFilterCache: /* @__PURE__ */ new Map(),
2996
+ aggregateTypeCache: /* @__PURE__ */ new Map()
1976
2997
  };
2998
+ const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
1977
2999
  const queries = {};
1978
3000
  const mutations = {};
1979
3001
  const gqlSchemaTypes = Object.fromEntries(
@@ -1989,7 +3011,8 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
1989
3011
  typeNameMapper,
1990
3012
  prefixes.insert,
1991
3013
  prefixes.update,
1992
- resolverFactory
3014
+ resolverFactory,
3015
+ relationAggregateFactory
1993
3016
  )
1994
3017
  ])
1995
3018
  );
@@ -2002,8 +3025,11 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
2002
3025
  typeName,
2003
3026
  listFieldName,
2004
3027
  singleFieldName,
3028
+ aggregateFieldName,
2005
3029
  createArrayFieldName,
2006
3030
  createSingleFieldName,
3031
+ upsertArrayFieldName,
3032
+ upsertSingleFieldName,
2007
3033
  updateFieldName,
2008
3034
  deleteFieldName
2009
3035
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
@@ -2016,7 +3042,9 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
2016
3042
  tableFilters,
2017
3043
  listFieldName,
2018
3044
  typeName,
2019
- typeNameMapper
3045
+ typeNameMapper,
3046
+ filterCtx,
3047
+ features.distinct
2020
3048
  );
2021
3049
  const selectSingleGenerated = generateSelectSingle2(
2022
3050
  db,
@@ -2027,9 +3055,10 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
2027
3055
  tableFilters,
2028
3056
  singleFieldName,
2029
3057
  typeName,
2030
- typeNameMapper
3058
+ typeNameMapper,
3059
+ filterCtx
2031
3060
  );
2032
- const insertArrGenerated = generateInsertArray2(
3061
+ const insertArrGenerated = features.insert ? generateInsertArray2(
2033
3062
  db,
2034
3063
  tableName,
2035
3064
  schema[tableName],
@@ -2040,8 +3069,8 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
2040
3069
  typeName,
2041
3070
  typeNameMapper,
2042
3071
  conflictDoNothing
2043
- );
2044
- const insertSingleGenerated = generateInsertSingle2(
3072
+ ) : void 0;
3073
+ const insertSingleGenerated = features.insert ? generateInsertSingle2(
2045
3074
  db,
2046
3075
  tableName,
2047
3076
  schema[tableName],
@@ -2052,8 +3081,46 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
2052
3081
  typeName,
2053
3082
  typeNameMapper,
2054
3083
  conflictDoNothing
2055
- );
2056
- const updateGenerated = generateUpdate2(
3084
+ ) : void 0;
3085
+ const uniqueSets = features.upsert ? getUniqueColumnSets(schema[tableName], getTableConfig2) : [];
3086
+ const onConflictInput = features.upsert ? generateOnConflictInput({
3087
+ table: schema[tableName],
3088
+ typeName,
3089
+ uniqueSets,
3090
+ tableFilters,
3091
+ withTarget: true
3092
+ }) : void 0;
3093
+ const upsertArrGenerated = onConflictInput ? generateUpsert2(
3094
+ db,
3095
+ tableName,
3096
+ schema[tableName],
3097
+ tables,
3098
+ eagerRelations,
3099
+ insertInput,
3100
+ onConflictInput,
3101
+ uniqueSets,
3102
+ upsertArrayFieldName,
3103
+ typeName,
3104
+ false,
3105
+ typeNameMapper,
3106
+ filterCtx
3107
+ ) : void 0;
3108
+ const upsertSingleGenerated = onConflictInput ? generateUpsert2(
3109
+ db,
3110
+ tableName,
3111
+ schema[tableName],
3112
+ tables,
3113
+ eagerRelations,
3114
+ insertInput,
3115
+ onConflictInput,
3116
+ uniqueSets,
3117
+ upsertSingleFieldName,
3118
+ typeName,
3119
+ true,
3120
+ typeNameMapper,
3121
+ filterCtx
3122
+ ) : void 0;
3123
+ const updateGenerated = features.update ? generateUpdate2(
2057
3124
  db,
2058
3125
  tableName,
2059
3126
  schema[tableName],
@@ -2063,16 +3130,29 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
2063
3130
  tableFilters,
2064
3131
  updateFieldName,
2065
3132
  typeName,
2066
- typeNameMapper
2067
- );
2068
- const deleteGenerated = generateDelete2(
3133
+ typeNameMapper,
3134
+ filterCtx
3135
+ ) : void 0;
3136
+ const deleteGenerated = features.delete ? generateDelete2(
2069
3137
  db,
2070
3138
  tableName,
2071
3139
  schema[tableName],
2072
3140
  tableFilters,
2073
3141
  deleteFieldName,
2074
- typeName
2075
- );
3142
+ typeName,
3143
+ filterCtx,
3144
+ { tableName, relationMap: namedRelations, tables }
3145
+ ) : void 0;
3146
+ const aggregateType = features.aggregates ? generateAggregateTypes(schema[tableName], tableName, typeName, cacheCtx) : void 0;
3147
+ const aggregateGenerated = features.aggregates ? generateAggregate(
3148
+ db,
3149
+ tableName,
3150
+ schema[tableName],
3151
+ typeName,
3152
+ aggregateFieldName,
3153
+ tableFilters,
3154
+ filterCtx
3155
+ ) : void 0;
2076
3156
  queries[selectArrGenerated.name] = {
2077
3157
  type: selectArrOutput,
2078
3158
  args: selectArrGenerated.args,
@@ -2083,31 +3163,71 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
2083
3163
  args: selectSingleGenerated.args,
2084
3164
  resolve: selectSingleGenerated.resolver
2085
3165
  };
2086
- mutations[insertArrGenerated.name] = {
2087
- type: arrTableItemOutput,
2088
- args: insertArrGenerated.args,
2089
- resolve: insertArrGenerated.resolver
2090
- };
2091
- mutations[insertSingleGenerated.name] = {
2092
- type: singleTableItemOutput,
2093
- args: insertSingleGenerated.args,
2094
- resolve: insertSingleGenerated.resolver
2095
- };
2096
- mutations[updateGenerated.name] = {
2097
- type: arrTableItemOutput,
2098
- args: updateGenerated.args,
2099
- resolve: updateGenerated.resolver
2100
- };
2101
- mutations[deleteGenerated.name] = {
2102
- type: arrTableItemOutput,
2103
- args: deleteGenerated.args,
2104
- resolve: deleteGenerated.resolver
2105
- };
2106
- [insertInput, updateInput, tableFilters, tableOrder].forEach((e) => {
3166
+ if (aggregateGenerated && aggregateType) {
3167
+ queries[aggregateGenerated.name] = {
3168
+ type: new GraphQLNonNull5(aggregateType),
3169
+ args: aggregateGenerated.args,
3170
+ resolve: aggregateGenerated.resolver
3171
+ };
3172
+ }
3173
+ if (insertArrGenerated) {
3174
+ mutations[insertArrGenerated.name] = {
3175
+ type: arrTableItemOutput,
3176
+ args: insertArrGenerated.args,
3177
+ resolve: insertArrGenerated.resolver
3178
+ };
3179
+ }
3180
+ if (insertSingleGenerated) {
3181
+ mutations[insertSingleGenerated.name] = {
3182
+ type: singleTableItemOutput,
3183
+ args: insertSingleGenerated.args,
3184
+ resolve: insertSingleGenerated.resolver
3185
+ };
3186
+ }
3187
+ if (upsertArrGenerated) {
3188
+ mutations[upsertArrGenerated.name] = {
3189
+ type: arrTableItemOutput,
3190
+ args: upsertArrGenerated.args,
3191
+ resolve: upsertArrGenerated.resolver
3192
+ };
3193
+ }
3194
+ if (upsertSingleGenerated) {
3195
+ mutations[upsertSingleGenerated.name] = {
3196
+ type: singleTableItemOutput,
3197
+ args: upsertSingleGenerated.args,
3198
+ resolve: upsertSingleGenerated.resolver
3199
+ };
3200
+ }
3201
+ if (updateGenerated) {
3202
+ mutations[updateGenerated.name] = {
3203
+ type: arrTableItemOutput,
3204
+ args: updateGenerated.args,
3205
+ resolve: updateGenerated.resolver
3206
+ };
3207
+ }
3208
+ if (deleteGenerated) {
3209
+ mutations[deleteGenerated.name] = {
3210
+ type: arrTableItemOutput,
3211
+ args: deleteGenerated.args,
3212
+ resolve: deleteGenerated.resolver
3213
+ };
3214
+ }
3215
+ const activeInputs = [
3216
+ // The insert input types the upsert mutations too, so either feature keeps it.
3217
+ ...features.insert || onConflictInput ? [insertInput] : [],
3218
+ ...onConflictInput ? [onConflictInput] : [],
3219
+ ...features.update ? [updateInput] : [],
3220
+ tableFilters,
3221
+ tableOrder
3222
+ ];
3223
+ activeInputs.forEach((e) => {
2107
3224
  inputs[e.name] = e;
2108
3225
  });
2109
3226
  outputs[selectSingleOutput.name] = selectSingleOutput;
2110
3227
  outputs[singleTableItemOutput.name] = singleTableItemOutput;
3228
+ if (aggregateType) {
3229
+ outputs[aggregateType.name] = aggregateType;
3230
+ }
2111
3231
  }
2112
3232
  const fieldResolvers = {};
2113
3233
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -2130,27 +3250,33 @@ function generateSchemaData2(db, schema, relations, relationsDepthLimit, prefixe
2130
3250
  import { is as is6, One as One5 } from "drizzle-orm";
2131
3251
  import { getTableConfig as getTableConfig3, SQLiteTable } from "drizzle-orm/sqlite-core";
2132
3252
  import {
2133
- GraphQLError as GraphQLError5,
2134
- GraphQLList as GraphQLList5,
2135
- GraphQLNonNull as GraphQLNonNull5
3253
+ GraphQLError as GraphQLError6,
3254
+ GraphQLList as GraphQLList6,
3255
+ GraphQLNonNull as GraphQLNonNull6
2136
3256
  } from "graphql";
2137
- import { parseResolveInfo as parseResolveInfo3 } from "graphql-parse-resolve-info";
2138
- var generateSelectArray3 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper) => {
3257
+ import { parseResolveInfo as parseResolveInfo4 } from "graphql-parse-resolve-info";
3258
+ var generateSelectArray3 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
2139
3259
  const queryBase = db.query[tableName];
2140
3260
  if (!queryBase) {
2141
3261
  throw new Error(
2142
3262
  `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`
2143
3263
  );
2144
3264
  }
2145
- const queryArgs = selectArrayArgs(orderArgs, filterArgs);
2146
3265
  const table = tables[tableName];
3266
+ const pkNames = sqlitePrimaryKeyPropNames(table);
3267
+ const queryArgs = selectArrayArgs(
3268
+ orderArgs,
3269
+ filterArgs,
3270
+ distinctEnabled ? generateDistinctEnum(table, typeName) : void 0
3271
+ );
2147
3272
  return {
2148
3273
  name: fieldName,
2149
- resolver: async (_source, args, _context, info) => {
3274
+ resolver: async (_source, args, context, info) => {
2150
3275
  try {
2151
- const parsedInfo = parseResolveInfo3(info, { deep: true });
3276
+ const parsedInfo = parseResolveInfo4(info, { deep: true });
3277
+ const { executor, queryBase: requestQueryBase } = resolveQueryExecutor(db, context, tableName, queryBase);
2152
3278
  return await runRelationalSelect({
2153
- queryBase,
3279
+ queryBase: requestQueryBase,
2154
3280
  tables,
2155
3281
  tableName,
2156
3282
  table,
@@ -2159,7 +3285,10 @@ var generateSelectArray3 = (db, tableName, tables, relationMap, orderArgs, filte
2159
3285
  typeNameMapper,
2160
3286
  parsedInfo,
2161
3287
  ...args,
2162
- single: false
3288
+ single: false,
3289
+ filterCtx,
3290
+ pkNames,
3291
+ db: executor
2163
3292
  });
2164
3293
  } catch (e) {
2165
3294
  throw toGraphQLError(e);
@@ -2168,7 +3297,7 @@ var generateSelectArray3 = (db, tableName, tables, relationMap, orderArgs, filte
2168
3297
  args: queryArgs
2169
3298
  };
2170
3299
  };
2171
- var generateSelectSingle3 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper) => {
3300
+ var generateSelectSingle3 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
2172
3301
  const queryBase = db.query[tableName];
2173
3302
  if (!queryBase) {
2174
3303
  throw new Error(
@@ -2177,13 +3306,15 @@ var generateSelectSingle3 = (db, tableName, tables, relationMap, orderArgs, filt
2177
3306
  }
2178
3307
  const queryArgs = selectSingleArgs(orderArgs, filterArgs);
2179
3308
  const table = tables[tableName];
3309
+ const pkNames = sqlitePrimaryKeyPropNames(table);
2180
3310
  return {
2181
3311
  name: fieldName,
2182
- resolver: async (_source, args, _context, info) => {
3312
+ resolver: async (_source, args, context, info) => {
2183
3313
  try {
2184
- const parsedInfo = parseResolveInfo3(info, { deep: true });
3314
+ const parsedInfo = parseResolveInfo4(info, { deep: true });
3315
+ const { executor, queryBase: requestQueryBase } = resolveQueryExecutor(db, context, tableName, queryBase);
2185
3316
  return await runRelationalSelect({
2186
- queryBase,
3317
+ queryBase: requestQueryBase,
2187
3318
  tables,
2188
3319
  tableName,
2189
3320
  table,
@@ -2192,7 +3323,10 @@ var generateSelectSingle3 = (db, tableName, tables, relationMap, orderArgs, filt
2192
3323
  typeNameMapper,
2193
3324
  parsedInfo,
2194
3325
  ...args,
2195
- single: true
3326
+ single: true,
3327
+ filterCtx,
3328
+ pkNames,
3329
+ db: executor
2196
3330
  });
2197
3331
  } catch (e) {
2198
3332
  throw toGraphQLError(e);
@@ -2202,22 +3336,22 @@ var generateSelectSingle3 = (db, tableName, tables, relationMap, orderArgs, filt
2202
3336
  };
2203
3337
  };
2204
3338
  var sqlitePrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig3);
2205
- var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper) => {
3339
+ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false) => {
2206
3340
  const queryArgs = {
2207
3341
  values: {
2208
- type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(baseType)))
3342
+ type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(baseType)))
2209
3343
  }
2210
3344
  };
2211
3345
  const pkNames = sqlitePrimaryKeyPropNames(table);
2212
3346
  return {
2213
3347
  name: fieldName,
2214
- resolver: async (_source, args, _context, info) => {
3348
+ resolver: async (_source, args, context, info) => {
2215
3349
  try {
2216
3350
  const input = remapFromGraphQLArrayInput(args.values, table);
2217
3351
  if (!input.length) {
2218
- throw new GraphQLError5("No values were provided!");
3352
+ throw new GraphQLError6("No values were provided!");
2219
3353
  }
2220
- const parsedInfo = parseResolveInfo3(info, {
3354
+ const parsedInfo = parseResolveInfo4(info, {
2221
3355
  deep: true
2222
3356
  });
2223
3357
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -2230,8 +3364,13 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
2230
3364
  pkNames,
2231
3365
  parsedInfo
2232
3366
  });
2233
- const result = await db.insert(table).values(input).returning(columns).onConflictDoNothing();
2234
- const enriched = hasRelations ? await eagerLoadMutationRelations(db, tableName, result, pkNames, withParams) : result;
3367
+ const executor = resolveExecutor(db, context);
3368
+ let query = executor.insert(table).values(input).returning(columns);
3369
+ if (conflictDoNothing) {
3370
+ query = query.onConflictDoNothing();
3371
+ }
3372
+ const result = await query;
3373
+ const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
2235
3374
  return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
2236
3375
  } catch (e) {
2237
3376
  throw toGraphQLError(e);
@@ -2240,19 +3379,19 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
2240
3379
  args: queryArgs
2241
3380
  };
2242
3381
  };
2243
- var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper) => {
3382
+ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false) => {
2244
3383
  const queryArgs = {
2245
3384
  values: {
2246
- type: new GraphQLNonNull5(baseType)
3385
+ type: new GraphQLNonNull6(baseType)
2247
3386
  }
2248
3387
  };
2249
3388
  const pkNames = sqlitePrimaryKeyPropNames(table);
2250
3389
  return {
2251
3390
  name: fieldName,
2252
- resolver: async (_source, args, _context, info) => {
3391
+ resolver: async (_source, args, context, info) => {
2253
3392
  try {
2254
3393
  const input = remapFromGraphQLSingleInput(args.values, table);
2255
- const parsedInfo = parseResolveInfo3(info, {
3394
+ const parsedInfo = parseResolveInfo4(info, {
2256
3395
  deep: true
2257
3396
  });
2258
3397
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -2265,11 +3404,16 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
2265
3404
  pkNames,
2266
3405
  parsedInfo
2267
3406
  });
2268
- const result = await db.insert(table).values(input).returning(columns).onConflictDoNothing();
3407
+ const executor = resolveExecutor(db, context);
3408
+ let query = executor.insert(table).values(input).returning(columns);
3409
+ if (conflictDoNothing) {
3410
+ query = query.onConflictDoNothing();
3411
+ }
3412
+ const result = await query;
2269
3413
  if (!result[0]) {
2270
3414
  return void 0;
2271
3415
  }
2272
- const enriched = hasRelations ? await eagerLoadMutationRelations(db, tableName, result, pkNames, withParams) : result;
3416
+ const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
2273
3417
  return remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap);
2274
3418
  } catch (e) {
2275
3419
  throw toGraphQLError(e);
@@ -2278,10 +3422,66 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
2278
3422
  args: queryArgs
2279
3423
  };
2280
3424
  };
2281
- var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper) => {
3425
+ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx) => {
3426
+ const queryArgs = {
3427
+ values: {
3428
+ type: single ? new GraphQLNonNull6(baseType) : new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(baseType)))
3429
+ },
3430
+ onConflict: {
3431
+ type: onConflictType,
3432
+ description: "How a conflicting row is resolved. Defaults to overwriting it on the primary key."
3433
+ }
3434
+ };
3435
+ const pkNames = sqlitePrimaryKeyPropNames(table);
3436
+ return {
3437
+ name: fieldName,
3438
+ resolver: async (_source, args, context, info) => {
3439
+ try {
3440
+ const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
3441
+ if (!input.length) {
3442
+ throw new GraphQLError6("No values were provided!");
3443
+ }
3444
+ const parsedInfo = parseResolveInfo4(info, { deep: true });
3445
+ const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
3446
+ relationMap,
3447
+ tables,
3448
+ tableName,
3449
+ typeName,
3450
+ typeNameMapper,
3451
+ table,
3452
+ pkNames,
3453
+ parsedInfo
3454
+ });
3455
+ const plan = resolveConflictPlan({
3456
+ table,
3457
+ values: input,
3458
+ onConflict: args.onConflict,
3459
+ pkNames,
3460
+ uniqueSets,
3461
+ excludedRef: excludedColumnRef,
3462
+ withTarget: true,
3463
+ buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
3464
+ });
3465
+ const executor = resolveExecutor(db, context);
3466
+ let query = executor.insert(table).values(input).returning(columns);
3467
+ query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
3468
+ const result = await query;
3469
+ if (single && !result[0]) {
3470
+ return void 0;
3471
+ }
3472
+ const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
3473
+ return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
3474
+ } catch (e) {
3475
+ throw toGraphQLError(e);
3476
+ }
3477
+ },
3478
+ args: queryArgs
3479
+ };
3480
+ };
3481
+ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
2282
3482
  const queryArgs = {
2283
3483
  set: {
2284
- type: new GraphQLNonNull5(setArgs)
3484
+ type: new GraphQLNonNull6(setArgs)
2285
3485
  },
2286
3486
  where: {
2287
3487
  type: filterArgs
@@ -2290,10 +3490,10 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
2290
3490
  const pkNames = sqlitePrimaryKeyPropNames(table);
2291
3491
  return {
2292
3492
  name: fieldName,
2293
- resolver: async (_source, args, _context, info) => {
3493
+ resolver: async (_source, args, context, info) => {
2294
3494
  try {
2295
3495
  const { where, set } = args;
2296
- const parsedInfo = parseResolveInfo3(info, {
3496
+ const parsedInfo = parseResolveInfo4(info, {
2297
3497
  deep: true
2298
3498
  });
2299
3499
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -2308,16 +3508,17 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
2308
3508
  });
2309
3509
  const input = remapFromGraphQLSingleInput(set, table);
2310
3510
  if (!Object.keys(input).length) {
2311
- throw new GraphQLError5("Unable to update with no values specified!");
3511
+ throw new GraphQLError6("Unable to update with no values specified!");
2312
3512
  }
2313
- let query = db.update(table).set(input);
3513
+ const executor = resolveExecutor(db, context);
3514
+ let query = executor.update(table).set(input);
2314
3515
  if (where) {
2315
- const filters = extractFilters(table, tableName, where);
3516
+ const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
2316
3517
  query = query.where(filters);
2317
3518
  }
2318
3519
  query = query.returning(columns);
2319
3520
  const result = await query;
2320
- const enriched = hasRelations ? await eagerLoadMutationRelations(db, tableName, result, pkNames, withParams) : result;
3521
+ const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
2321
3522
  return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
2322
3523
  } catch (e) {
2323
3524
  throw toGraphQLError(e);
@@ -2326,7 +3527,7 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
2326
3527
  args: queryArgs
2327
3528
  };
2328
3529
  };
2329
- var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName) => {
3530
+ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
2330
3531
  const queryArgs = {
2331
3532
  where: {
2332
3533
  type: filterArgs
@@ -2334,19 +3535,21 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName) =>
2334
3535
  };
2335
3536
  return {
2336
3537
  name: fieldName,
2337
- resolver: async (_source, args, _context, info) => {
3538
+ resolver: async (_source, args, context, info) => {
2338
3539
  try {
2339
3540
  const { where } = args;
2340
- const parsedInfo = parseResolveInfo3(info, {
3541
+ const parsedInfo = parseResolveInfo4(info, {
2341
3542
  deep: true
2342
3543
  });
2343
3544
  const columns = extractSelectedColumnsFromTreeSQLFormat(
2344
3545
  parsedInfo.fieldsByTypeName[typeName],
2345
- table
3546
+ table,
3547
+ selectionCtx
2346
3548
  );
2347
- let query = db.delete(table);
3549
+ const executor = resolveExecutor(db, context);
3550
+ let query = executor.delete(table);
2348
3551
  if (where) {
2349
- const filters = extractFilters(table, tableName, where);
3552
+ const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
2350
3553
  query = query.where(filters);
2351
3554
  }
2352
3555
  query = query.returning(columns);
@@ -2359,7 +3562,8 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName) =>
2359
3562
  args: queryArgs
2360
3563
  };
2361
3564
  };
2362
- var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes, suffixes, typeNameMapper, shouldEagerLoad = () => true) => {
3565
+ var generateSchemaData3 = (db, schema, relations, options) => {
3566
+ const { relationsDepthLimit, prefixes, suffixes, conflictDoNothing, typeNameMapper, shouldEagerLoad, features } = options;
2363
3567
  const rawSchema = schema;
2364
3568
  const schemaEntries = Object.entries(rawSchema);
2365
3569
  const tableEntries = schemaEntries.filter(([_key, value]) => is6(value, SQLiteTable));
@@ -2372,7 +3576,8 @@ var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes,
2372
3576
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
2373
3577
  attachTargetPrimaryKeys(namedRelations, tables, sqlitePrimaryKeyPropNames);
2374
3578
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
2375
- const resolverFactory = createRelationResolverFactory(db, tables);
3579
+ const filterCtx = { tables, relationMap: namedRelations };
3580
+ const resolverFactory = createRelationResolverFactory(db, tables, filterCtx);
2376
3581
  const cacheCtx = {
2377
3582
  genericFilterCache: /* @__PURE__ */ new Map(),
2378
3583
  objectTypeCache: /* @__PURE__ */ new Map(),
@@ -2380,8 +3585,11 @@ var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes,
2380
3585
  fullyBuiltTables: /* @__PURE__ */ new Set(),
2381
3586
  relationTypeCache: /* @__PURE__ */ new Map(),
2382
3587
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
2383
- filterTypeCache: /* @__PURE__ */ new WeakMap()
3588
+ filterTypeCache: /* @__PURE__ */ new WeakMap(),
3589
+ listRelationFilterCache: /* @__PURE__ */ new Map(),
3590
+ aggregateTypeCache: /* @__PURE__ */ new Map()
2384
3591
  };
3592
+ const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
2385
3593
  const queries = {};
2386
3594
  const mutations = {};
2387
3595
  const gqlSchemaTypes = Object.fromEntries(
@@ -2397,7 +3605,8 @@ var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes,
2397
3605
  typeNameMapper,
2398
3606
  prefixes.insert,
2399
3607
  prefixes.update,
2400
- resolverFactory
3608
+ resolverFactory,
3609
+ relationAggregateFactory
2401
3610
  )
2402
3611
  ])
2403
3612
  );
@@ -2410,8 +3619,11 @@ var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes,
2410
3619
  typeName,
2411
3620
  listFieldName,
2412
3621
  singleFieldName,
3622
+ aggregateFieldName,
2413
3623
  createArrayFieldName,
2414
3624
  createSingleFieldName,
3625
+ upsertArrayFieldName,
3626
+ upsertSingleFieldName,
2415
3627
  updateFieldName,
2416
3628
  deleteFieldName
2417
3629
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
@@ -2424,7 +3636,9 @@ var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes,
2424
3636
  tableFilters,
2425
3637
  listFieldName,
2426
3638
  typeName,
2427
- typeNameMapper
3639
+ typeNameMapper,
3640
+ filterCtx,
3641
+ features.distinct
2428
3642
  );
2429
3643
  const selectSingleGenerated = generateSelectSingle3(
2430
3644
  db,
@@ -2435,9 +3649,10 @@ var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes,
2435
3649
  tableFilters,
2436
3650
  singleFieldName,
2437
3651
  typeName,
2438
- typeNameMapper
3652
+ typeNameMapper,
3653
+ filterCtx
2439
3654
  );
2440
- const insertArrGenerated = generateInsertArray3(
3655
+ const insertArrGenerated = features.insert ? generateInsertArray3(
2441
3656
  db,
2442
3657
  tableName,
2443
3658
  schema[tableName],
@@ -2446,9 +3661,10 @@ var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes,
2446
3661
  insertInput,
2447
3662
  createArrayFieldName,
2448
3663
  typeName,
2449
- typeNameMapper
2450
- );
2451
- const insertSingleGenerated = generateInsertSingle3(
3664
+ typeNameMapper,
3665
+ conflictDoNothing
3666
+ ) : void 0;
3667
+ const insertSingleGenerated = features.insert ? generateInsertSingle3(
2452
3668
  db,
2453
3669
  tableName,
2454
3670
  schema[tableName],
@@ -2457,9 +3673,48 @@ var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes,
2457
3673
  insertInput,
2458
3674
  createSingleFieldName,
2459
3675
  typeName,
2460
- typeNameMapper
2461
- );
2462
- const updateGenerated = generateUpdate3(
3676
+ typeNameMapper,
3677
+ conflictDoNothing
3678
+ ) : void 0;
3679
+ const uniqueSets = features.upsert ? getUniqueColumnSets(schema[tableName], getTableConfig3) : [];
3680
+ const onConflictInput = features.upsert ? generateOnConflictInput({
3681
+ table: schema[tableName],
3682
+ typeName,
3683
+ uniqueSets,
3684
+ tableFilters,
3685
+ withTarget: true
3686
+ }) : void 0;
3687
+ const upsertArrGenerated = onConflictInput ? generateUpsert3(
3688
+ db,
3689
+ tableName,
3690
+ schema[tableName],
3691
+ tables,
3692
+ eagerRelations,
3693
+ insertInput,
3694
+ onConflictInput,
3695
+ uniqueSets,
3696
+ upsertArrayFieldName,
3697
+ typeName,
3698
+ false,
3699
+ typeNameMapper,
3700
+ filterCtx
3701
+ ) : void 0;
3702
+ const upsertSingleGenerated = onConflictInput ? generateUpsert3(
3703
+ db,
3704
+ tableName,
3705
+ schema[tableName],
3706
+ tables,
3707
+ eagerRelations,
3708
+ insertInput,
3709
+ onConflictInput,
3710
+ uniqueSets,
3711
+ upsertSingleFieldName,
3712
+ typeName,
3713
+ true,
3714
+ typeNameMapper,
3715
+ filterCtx
3716
+ ) : void 0;
3717
+ const updateGenerated = features.update ? generateUpdate3(
2463
3718
  db,
2464
3719
  tableName,
2465
3720
  schema[tableName],
@@ -2469,16 +3724,29 @@ var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes,
2469
3724
  tableFilters,
2470
3725
  updateFieldName,
2471
3726
  typeName,
2472
- typeNameMapper
2473
- );
2474
- const deleteGenerated = generateDelete3(
3727
+ typeNameMapper,
3728
+ filterCtx
3729
+ ) : void 0;
3730
+ const deleteGenerated = features.delete ? generateDelete3(
2475
3731
  db,
2476
3732
  tableName,
2477
3733
  schema[tableName],
2478
3734
  tableFilters,
2479
3735
  deleteFieldName,
2480
- typeName
2481
- );
3736
+ typeName,
3737
+ filterCtx,
3738
+ { tableName, relationMap: namedRelations, tables }
3739
+ ) : void 0;
3740
+ const aggregateType = features.aggregates ? generateAggregateTypes(schema[tableName], tableName, typeName, cacheCtx) : void 0;
3741
+ const aggregateGenerated = features.aggregates ? generateAggregate(
3742
+ db,
3743
+ tableName,
3744
+ schema[tableName],
3745
+ typeName,
3746
+ aggregateFieldName,
3747
+ tableFilters,
3748
+ filterCtx
3749
+ ) : void 0;
2482
3750
  queries[selectArrGenerated.name] = {
2483
3751
  type: selectArrOutput,
2484
3752
  args: selectArrGenerated.args,
@@ -2489,31 +3757,71 @@ var generateSchemaData3 = (db, schema, relations, relationsDepthLimit, prefixes,
2489
3757
  args: selectSingleGenerated.args,
2490
3758
  resolve: selectSingleGenerated.resolver
2491
3759
  };
2492
- mutations[insertArrGenerated.name] = {
2493
- type: arrTableItemOutput,
2494
- args: insertArrGenerated.args,
2495
- resolve: insertArrGenerated.resolver
2496
- };
2497
- mutations[insertSingleGenerated.name] = {
2498
- type: singleTableItemOutput,
2499
- args: insertSingleGenerated.args,
2500
- resolve: insertSingleGenerated.resolver
2501
- };
2502
- mutations[updateGenerated.name] = {
2503
- type: arrTableItemOutput,
2504
- args: updateGenerated.args,
2505
- resolve: updateGenerated.resolver
2506
- };
2507
- mutations[deleteGenerated.name] = {
2508
- type: arrTableItemOutput,
2509
- args: deleteGenerated.args,
2510
- resolve: deleteGenerated.resolver
2511
- };
2512
- [insertInput, updateInput, tableFilters, tableOrder].forEach((e) => {
3760
+ if (aggregateGenerated && aggregateType) {
3761
+ queries[aggregateGenerated.name] = {
3762
+ type: new GraphQLNonNull6(aggregateType),
3763
+ args: aggregateGenerated.args,
3764
+ resolve: aggregateGenerated.resolver
3765
+ };
3766
+ }
3767
+ if (insertArrGenerated) {
3768
+ mutations[insertArrGenerated.name] = {
3769
+ type: arrTableItemOutput,
3770
+ args: insertArrGenerated.args,
3771
+ resolve: insertArrGenerated.resolver
3772
+ };
3773
+ }
3774
+ if (insertSingleGenerated) {
3775
+ mutations[insertSingleGenerated.name] = {
3776
+ type: singleTableItemOutput,
3777
+ args: insertSingleGenerated.args,
3778
+ resolve: insertSingleGenerated.resolver
3779
+ };
3780
+ }
3781
+ if (upsertArrGenerated) {
3782
+ mutations[upsertArrGenerated.name] = {
3783
+ type: arrTableItemOutput,
3784
+ args: upsertArrGenerated.args,
3785
+ resolve: upsertArrGenerated.resolver
3786
+ };
3787
+ }
3788
+ if (upsertSingleGenerated) {
3789
+ mutations[upsertSingleGenerated.name] = {
3790
+ type: singleTableItemOutput,
3791
+ args: upsertSingleGenerated.args,
3792
+ resolve: upsertSingleGenerated.resolver
3793
+ };
3794
+ }
3795
+ if (updateGenerated) {
3796
+ mutations[updateGenerated.name] = {
3797
+ type: arrTableItemOutput,
3798
+ args: updateGenerated.args,
3799
+ resolve: updateGenerated.resolver
3800
+ };
3801
+ }
3802
+ if (deleteGenerated) {
3803
+ mutations[deleteGenerated.name] = {
3804
+ type: arrTableItemOutput,
3805
+ args: deleteGenerated.args,
3806
+ resolve: deleteGenerated.resolver
3807
+ };
3808
+ }
3809
+ const activeInputs = [
3810
+ // The insert input types the upsert mutations too, so either feature keeps it.
3811
+ ...features.insert || onConflictInput ? [insertInput] : [],
3812
+ ...onConflictInput ? [onConflictInput] : [],
3813
+ ...features.update ? [updateInput] : [],
3814
+ tableFilters,
3815
+ tableOrder
3816
+ ];
3817
+ activeInputs.forEach((e) => {
2513
3818
  inputs[e.name] = e;
2514
3819
  });
2515
3820
  outputs[selectSingleOutput.name] = selectSingleOutput;
2516
3821
  outputs[singleTableItemOutput.name] = singleTableItemOutput;
3822
+ if (aggregateType) {
3823
+ outputs[aggregateType.name] = aggregateType;
3824
+ }
2517
3825
  }
2518
3826
  const fieldResolvers = {};
2519
3827
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -2546,13 +3854,23 @@ var buildSchema = (db, config) => {
2546
3854
  const prefixes = {
2547
3855
  insert: config?.prefixes?.insert ?? "create",
2548
3856
  delete: config?.prefixes?.delete ?? "delete",
2549
- update: config?.prefixes?.update ?? "update"
3857
+ update: config?.prefixes?.update ?? "update",
3858
+ upsert: config?.prefixes?.upsert ?? "upsert"
2550
3859
  };
2551
3860
  const suffixes = {
2552
3861
  list: config?.suffixes?.list ?? "",
2553
3862
  single: config?.suffixes?.single ?? "Single"
2554
3863
  };
2555
3864
  const typeNameMapper = config?.typeNameMapper;
3865
+ const features = {
3866
+ aggregates: config?.features?.aggregates ?? true,
3867
+ relationAggregates: config?.features?.relationAggregates ?? true,
3868
+ distinct: config?.features?.distinct ?? true,
3869
+ insert: config?.features?.insert ?? true,
3870
+ update: config?.features?.update ?? true,
3871
+ delete: config?.features?.delete ?? true,
3872
+ upsert: config?.features?.upsert ?? false
3873
+ };
2556
3874
  const eagerOpt = config?.eagerLoadRelations;
2557
3875
  const shouldEagerLoad = eagerOpt === void 0 || eagerOpt === true ? () => true : eagerOpt === false ? () => false : eagerOpt;
2558
3876
  if (!typeNameMapper && suffixes.list === suffixes.single) {
@@ -2572,54 +3890,40 @@ var buildSchema = (db, config) => {
2572
3890
  );
2573
3891
  }
2574
3892
  }
3893
+ const generatorOptions = {
3894
+ relationsDepthLimit: config?.relationsDepthLimit,
3895
+ prefixes,
3896
+ suffixes,
3897
+ conflictDoNothing: config?.conflictDoNothing ?? false,
3898
+ typeNameMapper,
3899
+ shouldEagerLoad,
3900
+ features
3901
+ };
2575
3902
  let generatorOutput;
2576
3903
  if (is7(db, MySqlDatabase)) {
2577
- generatorOutput = generateSchemaData(
2578
- db,
2579
- schema,
2580
- relations,
2581
- config?.relationsDepthLimit,
2582
- prefixes,
2583
- suffixes,
2584
- typeNameMapper,
2585
- shouldEagerLoad
2586
- );
3904
+ generatorOutput = generateSchemaData(db, schema, relations, generatorOptions);
2587
3905
  } else if (is7(db, PgAsyncDatabase)) {
2588
- generatorOutput = generateSchemaData2(
2589
- db,
2590
- schema,
2591
- relations,
2592
- config?.relationsDepthLimit,
2593
- prefixes,
2594
- suffixes,
2595
- config?.conflictDoNothing ?? false,
2596
- typeNameMapper,
2597
- shouldEagerLoad
2598
- );
3906
+ generatorOutput = generateSchemaData2(db, schema, relations, generatorOptions);
2599
3907
  } else if (is7(db, BaseSQLiteDatabase)) {
2600
- generatorOutput = generateSchemaData3(
2601
- db,
2602
- schema,
2603
- relations,
2604
- config?.relationsDepthLimit,
2605
- prefixes,
2606
- suffixes,
2607
- typeNameMapper,
2608
- shouldEagerLoad
2609
- );
3908
+ generatorOutput = generateSchemaData3(db, schema, relations, generatorOptions);
2610
3909
  } else {
2611
3910
  throw new Error("Drizzle-GraphQL Error: Unknown database instance type");
2612
3911
  }
3912
+ const onError = config?.onError;
3913
+ applyErrorMapper(
3914
+ generatorOutput,
3915
+ onError ? (error) => onError(error) ?? defaultErrorMapper(error) : defaultErrorMapper
3916
+ );
2613
3917
  const { queries, mutations, inputs, types } = generatorOutput;
2614
3918
  const graphQLSchemaConfig = {
2615
3919
  types: [...Object.values(inputs), ...Object.values(types)],
2616
- query: new GraphQLObjectType4({
3920
+ query: new GraphQLObjectType5({
2617
3921
  name: "Query",
2618
3922
  fields: queries
2619
3923
  })
2620
3924
  };
2621
- if (config?.mutations !== false) {
2622
- const mutation = new GraphQLObjectType4({
3925
+ if (config?.mutations !== false && Object.keys(mutations).length) {
3926
+ const mutation = new GraphQLObjectType5({
2623
3927
  name: "Mutation",
2624
3928
  fields: mutations
2625
3929
  });
@@ -2629,8 +3933,15 @@ var buildSchema = (db, config) => {
2629
3933
  return { schema: outputSchema, entities: generatorOutput };
2630
3934
  };
2631
3935
  export {
3936
+ GraphQLBigIntString,
3937
+ GraphQLDate,
3938
+ GraphQLDateTime,
3939
+ GraphQLJSON,
3940
+ GraphQLUUID,
2632
3941
  buildSchema,
2633
3942
  createRelationResolverFactory,
3943
+ defaultErrorMapper,
3944
+ drizzleExecutorKey,
2634
3945
  extractFilters,
2635
3946
  extractOrderBy,
2636
3947
  extractRelationJoinColumns