@vantreeseba/drizzle-graphql 4.1.0 → 5.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
@@ -41,6 +41,7 @@ import {
41
41
  GraphQLBoolean as GraphQLBoolean2,
42
42
  GraphQLEnumType as GraphQLEnumType2,
43
43
  GraphQLError as GraphQLError3,
44
+ GraphQLFloat as GraphQLFloat2,
44
45
  GraphQLInputObjectType as GraphQLInputObjectType2,
45
46
  GraphQLInt as GraphQLInt2,
46
47
  GraphQLList as GraphQLList2,
@@ -293,23 +294,6 @@ var remapFromGraphQLArrayInput = (queryInput, table) => {
293
294
  return queryInput;
294
295
  };
295
296
 
296
- // src/util/type-converter/index.ts
297
- import { extractExtendedColumnType, is as is2 } from "drizzle-orm";
298
- import { MySqlInt, MySqlSerial } from "drizzle-orm/mysql-core";
299
- import { PgDate, PgDateString, PgInteger, PgSerial, PgTimestamp, PgTimestampString, PgUUID } from "drizzle-orm/pg-core";
300
- import { SQLiteInteger } from "drizzle-orm/sqlite-core";
301
- import {
302
- GraphQLBoolean,
303
- GraphQLEnumType,
304
- GraphQLFloat,
305
- GraphQLInputObjectType,
306
- GraphQLInt,
307
- GraphQLList,
308
- GraphQLNonNull,
309
- GraphQLObjectType,
310
- GraphQLString
311
- } from "graphql";
312
-
313
297
  // src/util/scalars/index.ts
314
298
  import { GraphQLError as GraphQLError2, GraphQLScalarType, Kind } from "graphql";
315
299
  import { GraphQLDate, GraphQLDateTime, GraphQLJSON, GraphQLUUID } from "graphql-scalars";
@@ -348,8 +332,54 @@ var GraphQLBigIntString = new GraphQLScalarType({
348
332
  return asDecimalString(ast.value);
349
333
  }
350
334
  });
335
+ var numericStringPattern = /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;
336
+ var asNumericString = (value) => {
337
+ if (typeof value === "bigint") {
338
+ return value.toString();
339
+ }
340
+ if (typeof value === "number") {
341
+ if (!Number.isFinite(value)) {
342
+ throw new GraphQLError2(`Decimal cannot represent non-finite value: ${value}`);
343
+ }
344
+ return String(value);
345
+ }
346
+ if (typeof value === "string") {
347
+ if (!numericStringPattern.test(value)) {
348
+ throw new GraphQLError2(`Decimal cannot represent non-numeric value: "${value}"`);
349
+ }
350
+ return value;
351
+ }
352
+ throw new GraphQLError2(`Decimal cannot represent value: ${JSON.stringify(value)}`);
353
+ };
354
+ var GraphQLDecimalString = new GraphQLScalarType({
355
+ name: "Decimal",
356
+ description: "An arbitrary-precision decimal, transported as a numeric string so that values beyond JavaScript's double-precision range survive the round-trip intact.",
357
+ serialize: asNumericString,
358
+ parseValue: asNumericString,
359
+ parseLiteral: (ast) => {
360
+ if (ast.kind !== Kind.STRING && ast.kind !== Kind.INT && ast.kind !== Kind.FLOAT) {
361
+ throw new GraphQLError2(`Decimal cannot represent a ${ast.kind}`, { nodes: ast });
362
+ }
363
+ return asNumericString(ast.value);
364
+ }
365
+ });
351
366
 
352
367
  // src/util/type-converter/index.ts
368
+ import { extractExtendedColumnType, is as is2 } from "drizzle-orm";
369
+ import { MySqlInt, MySqlSerial } from "drizzle-orm/mysql-core";
370
+ import { PgDate, PgDateString, PgInteger, PgSerial, PgTimestamp, PgTimestampString, PgUUID } from "drizzle-orm/pg-core";
371
+ import { SQLiteInteger } from "drizzle-orm/sqlite-core";
372
+ import {
373
+ GraphQLBoolean,
374
+ GraphQLEnumType,
375
+ GraphQLFloat,
376
+ GraphQLInputObjectType,
377
+ GraphQLInt,
378
+ GraphQLList,
379
+ GraphQLNonNull,
380
+ GraphQLObjectType,
381
+ GraphQLString
382
+ } from "graphql";
353
383
  var allowedNameChars = /^[a-zA-Z0-9_]+$/;
354
384
  var enumMap = /* @__PURE__ */ new WeakMap();
355
385
  var generateEnumCached = (column, columnName, tableName) => {
@@ -386,7 +416,7 @@ var geoXyInputType = new GraphQLInputObjectType({
386
416
  }
387
417
  });
388
418
  var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
389
- const { type: baseType } = extractExtendedColumnType(column);
419
+ const { type: baseType, constraint } = extractExtendedColumnType(column);
390
420
  switch (baseType) {
391
421
  case "boolean":
392
422
  return { type: GraphQLBoolean, description: "Boolean" };
@@ -405,6 +435,9 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
405
435
  if (column.enumValues?.length) {
406
436
  return { type: generateEnumCached(column, columnName, tableName) };
407
437
  }
438
+ if (constraint === "numeric" && !column.dimensions) {
439
+ return { type: GraphQLDecimalString, description: "Decimal" };
440
+ }
408
441
  if (column instanceof PgTimestamp || column instanceof PgTimestampString) {
409
442
  return { type: GraphQLDateTime, description: "DateTime" };
410
443
  }
@@ -414,6 +447,15 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
414
447
  if (column instanceof PgDateString) {
415
448
  return isInput ? { type: GraphQLString, description: "Date" } : { type: GraphQLDate, description: "Date" };
416
449
  }
450
+ {
451
+ const dims = column.dimensions;
452
+ if (dims !== void 0 && dims > 0) {
453
+ return {
454
+ type: new GraphQLList(new GraphQLNonNull(GraphQLString)),
455
+ description: "Array<String>"
456
+ };
457
+ }
458
+ }
417
459
  return { type: GraphQLString, description: "String" };
418
460
  case "bigint":
419
461
  return { type: GraphQLBigIntString, description: "BigInt" };
@@ -564,10 +606,10 @@ var resolveQueryExecutor = (db, context, tableName, buildTimeQueryBase) => {
564
606
  queryBase: buildTimeQueryBase ? executor?.query?.[tableName] ?? buildTimeQueryBase : buildTimeQueryBase
565
607
  };
566
608
  };
567
- var batchedPaginatedRelationQuery = async (db, targetTable, foreignCol, whereCondition, orderByArg, limit, offset, pkNames) => {
609
+ var batchedPaginatedRelationQuery = async (db, targetTable, foreignCol, whereCondition, orderByArg, limit, offset, pkNames, orderCtx) => {
568
610
  const cols = getColumns(targetTable);
569
611
  const orderExprs = [
570
- ...orderByArg ? extractOrderBy(targetTable, orderByArg) : [],
612
+ ...orderByArg ? extractOrderBy(targetTable, orderByArg, orderCtx) : [],
571
613
  ...primaryKeyOrderExprs(targetTable, pkNames)
572
614
  ];
573
615
  const orderClause = orderExprs.length ? sql` order by ${sql.join(orderExprs, sql`, `)}` : sql``;
@@ -631,12 +673,13 @@ var createRelationResolverFactory = (db, tables, filterCtx) => ({ tableName, rel
631
673
  orderByArg,
632
674
  limit ?? null,
633
675
  offset ?? null,
634
- targetPkNames
676
+ targetPkNames,
677
+ relationFilterCtx(filterCtx, targetTableName)
635
678
  );
636
679
  } else {
637
680
  let q = executor.select().from(targetTable).where(whereCondition);
638
681
  if (orderByArg) {
639
- q = q.orderBy(...extractOrderBy(targetTable, orderByArg));
682
+ q = q.orderBy(...extractOrderBy(targetTable, orderByArg, relationFilterCtx(filterCtx, targetTableName)));
640
683
  }
641
684
  rows = await q;
642
685
  }
@@ -725,6 +768,20 @@ var extractSelectedColumnsFromTreeSQLFormat = (tree, table, selectionCtx) => {
725
768
  }
726
769
  return Object.fromEntries(selectedColumns);
727
770
  };
771
+ var orderNulls = new GraphQLEnumType2({
772
+ name: "OrderNulls",
773
+ description: "Where NULL values sort relative to non-NULL values",
774
+ values: {
775
+ first: {
776
+ value: "first",
777
+ description: "NULL values sort before all non-NULL values"
778
+ },
779
+ last: {
780
+ value: "last",
781
+ description: "NULL values sort after all non-NULL values"
782
+ }
783
+ }
784
+ });
728
785
  var innerOrder = new GraphQLInputObjectType2({
729
786
  name: "InnerOrder",
730
787
  fields: {
@@ -749,6 +806,10 @@ var innerOrder = new GraphQLInputObjectType2({
749
806
  priority: {
750
807
  type: new GraphQLNonNull2(GraphQLInt2),
751
808
  description: "Priority of current field"
809
+ },
810
+ nulls: {
811
+ type: orderNulls,
812
+ description: "Where NULL values sort. Defaults to the database's own rule (PostgreSQL: last on asc, first on desc; MySQL/SQLite: first on asc, last on desc)"
752
813
  }
753
814
  }
754
815
  });
@@ -762,9 +823,25 @@ var resolveGenericFilterName = (column, columnName, columnGraphQLType) => {
762
823
  if (columnGraphQLType.type instanceof GraphQLEnumType2) {
763
824
  return columnGraphQLType.type.name;
764
825
  }
826
+ if (columnGraphQLType.type === GraphQLBigIntString) {
827
+ return "BigInt";
828
+ }
829
+ if (columnGraphQLType.type === GraphQLDecimalString) {
830
+ return "Decimal";
831
+ }
765
832
  if (columnGraphQLType.type instanceof GraphQLList2) {
766
833
  const desc2 = columnGraphQLType.description ?? "";
767
- return desc2.includes("Integer") ? "IntArray" : "FloatArray";
834
+ let inner = columnGraphQLType.type.ofType;
835
+ if (inner instanceof GraphQLNonNull2) {
836
+ inner = inner.ofType;
837
+ }
838
+ if (desc2.includes("Integer") || inner === GraphQLInt2) {
839
+ return "IntArray";
840
+ }
841
+ if (desc2.includes("Float") || inner === GraphQLFloat2) {
842
+ return "FloatArray";
843
+ }
844
+ return "StringArray";
768
845
  }
769
846
  const ct = column.columnType ?? "";
770
847
  if (ct === "PgTimestamp" || ct === "PgTimestampString" || ct === "PgDate") {
@@ -777,12 +854,12 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
777
854
  const genericName = resolveGenericFilterName(column, columnName, columnGraphQLType);
778
855
  const cached = cacheCtx.genericFilterCache.get(genericName);
779
856
  if (cached) {
780
- return cached.main;
857
+ return cached;
781
858
  }
782
859
  const colType = columnGraphQLType.type;
783
860
  const colDesc = columnGraphQLType.description;
784
861
  const colArr = new GraphQLList2(new GraphQLNonNull2(colType));
785
- const isId = genericName === "Id";
862
+ const omitStringOps = genericName === "Id" || genericName === "BigInt" || genericName === "Decimal";
786
863
  const baseFields = {
787
864
  eq: { type: colType, description: colDesc },
788
865
  ne: { type: colType, description: colDesc },
@@ -790,31 +867,60 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
790
867
  lte: { type: colType, description: colDesc },
791
868
  gt: { type: colType, description: colDesc },
792
869
  gte: { type: colType, description: colDesc },
793
- ...isId ? {} : {
870
+ ...omitStringOps ? {} : {
794
871
  like: { type: GraphQLString2 },
795
872
  notLike: { type: GraphQLString2 },
796
873
  ilike: { type: GraphQLString2 },
797
- notIlike: { type: GraphQLString2 }
874
+ notIlike: { type: GraphQLString2 },
875
+ startsWith: {
876
+ type: GraphQLString2,
877
+ description: "Matches values starting with the given string. `%`, `_` and `\\` are matched literally."
878
+ },
879
+ endsWith: {
880
+ type: GraphQLString2,
881
+ description: "Matches values ending with the given string. `%`, `_` and `\\` are matched literally."
882
+ },
883
+ contains: {
884
+ type: GraphQLString2,
885
+ description: "Matches values containing the given string. `%`, `_` and `\\` are matched literally."
886
+ },
887
+ iStartsWith: {
888
+ type: GraphQLString2,
889
+ description: "Case-insensitive `startsWith`."
890
+ },
891
+ iEndsWith: {
892
+ type: GraphQLString2,
893
+ description: "Case-insensitive `endsWith`."
894
+ },
895
+ iContains: {
896
+ type: GraphQLString2,
897
+ description: "Case-insensitive `contains`."
898
+ }
798
899
  },
799
900
  inArray: { type: colArr, description: `Array<${colDesc}>` },
800
901
  notInArray: { type: colArr, description: `Array<${colDesc}>` },
801
902
  isNull: { type: GraphQLBoolean2 },
802
903
  isNotNull: { type: GraphQLBoolean2 }
803
904
  };
804
- const orType = new GraphQLInputObjectType2({
805
- name: `${genericName}FilterOr`,
806
- fields: { ...baseFields }
807
- });
808
905
  const mainType = new GraphQLInputObjectType2({
809
906
  name: `${genericName}Filter`,
810
- fields: {
907
+ fields: () => ({
811
908
  ...baseFields,
812
909
  OR: {
813
- type: new GraphQLList2(new GraphQLNonNull2(orType))
910
+ type: new GraphQLList2(new GraphQLNonNull2(mainType)),
911
+ description: "At least one branch matches; ANDed with any sibling operators"
912
+ },
913
+ AND: {
914
+ type: new GraphQLList2(new GraphQLNonNull2(mainType)),
915
+ description: "Every branch matches"
916
+ },
917
+ NOT: {
918
+ type: mainType,
919
+ description: "Negates the nested operators"
814
920
  }
815
- }
921
+ })
816
922
  });
817
- cacheCtx.genericFilterCache.set(genericName, { main: mainType, or: orType });
923
+ cacheCtx.genericFilterCache.set(genericName, mainType);
818
924
  return mainType;
819
925
  };
820
926
  var orderMap = /* @__PURE__ */ new WeakMap();
@@ -868,19 +974,53 @@ var generateTableSelectTypeFieldsCached = (table, tableName) => {
868
974
  fieldMap.set(table, remapped);
869
975
  return remapped;
870
976
  };
871
- var generateTableOrderTypeCached = (table, tableName, typeNameMapper, cacheCtx) => {
977
+ var isFilterableRelation = (relation) => !relation.through;
978
+ var generateRelationOrderFields = (tableName, cacheCtx, typeNameMapper, columnFields, relationMap, tables) => {
979
+ const relations = relationMap?.[tableName];
980
+ if (!relations || !tables) {
981
+ return {};
982
+ }
983
+ const fields = {};
984
+ for (const [relationName, relEntry] of Object.entries(relations)) {
985
+ if (relationName in columnFields) {
986
+ continue;
987
+ }
988
+ const targetTable = tables[relEntry.targetTableName];
989
+ const relation = relEntry.relation ?? relEntry;
990
+ if (!targetTable || !is3(relation, One2) || !isFilterableRelation(relation)) {
991
+ continue;
992
+ }
993
+ fields[relationName] = {
994
+ type: generateTableOrderTypeCached(
995
+ targetTable,
996
+ relEntry.targetTableName,
997
+ typeNameMapper,
998
+ cacheCtx,
999
+ relationMap,
1000
+ tables
1001
+ ),
1002
+ description: `Order by columns of the related ${relationName} row`
1003
+ };
1004
+ }
1005
+ return fields;
1006
+ };
1007
+ var generateTableOrderTypeCached = (table, tableName, typeNameMapper, cacheCtx, relationMap, tables) => {
872
1008
  if (cacheCtx.orderTypeCache.has(table)) {
873
1009
  return cacheCtx.orderTypeCache.get(table);
874
1010
  }
875
- const orderColumns = generateTableOrderCached(table);
876
1011
  const order = new GraphQLInputObjectType2({
877
1012
  name: `${resolveTypeName(tableName, typeNameMapper)}OrderBy`,
878
- fields: orderColumns
1013
+ fields: () => {
1014
+ const orderColumns = generateTableOrderCached(table);
1015
+ return {
1016
+ ...orderColumns,
1017
+ ...generateRelationOrderFields(tableName, cacheCtx, typeNameMapper, orderColumns, relationMap, tables)
1018
+ };
1019
+ }
879
1020
  });
880
1021
  cacheCtx.orderTypeCache.set(table, order);
881
1022
  return order;
882
1023
  };
883
- var isFilterableRelation = (relation) => !relation.through;
884
1024
  var generateListRelationFilterCached = (targetTable, targetTableName, cacheCtx, typeNameMapper, relationMap, tables) => {
885
1025
  const cached = cacheCtx.listRelationFilterCache.get(targetTableName);
886
1026
  if (cached) {
@@ -919,7 +1059,7 @@ var generateRelationFilterFields = (tableName, cacheCtx, typeNameMapper, columnF
919
1059
  }
920
1060
  const targetTable = tables[relEntry.targetTableName];
921
1061
  const relation = relEntry.relation ?? relEntry;
922
- if (!targetTable || !isFilterableRelation(relation)) {
1062
+ if (!targetTable) {
923
1063
  continue;
924
1064
  }
925
1065
  fields[relationName] = is3(relation, One2) ? {
@@ -956,16 +1096,21 @@ var generateTableFilterTypeCached = (table, tableName, cacheCtx, typeNameMapper,
956
1096
  ...generateRelationFilterFields(tableName, cacheCtx, typeNameMapper, filterColumns, relationMap, tables)
957
1097
  };
958
1098
  };
959
- const orFilters = new GraphQLInputObjectType2({
960
- name: `${resolveTypeName(tableName, typeNameMapper)}FiltersOr`,
961
- fields: buildFields
962
- });
963
1099
  const filters = new GraphQLInputObjectType2({
964
1100
  name: `${resolveTypeName(tableName, typeNameMapper)}Filters`,
965
1101
  fields: () => ({
966
1102
  ...buildFields(),
967
1103
  OR: {
968
- type: new GraphQLList2(new GraphQLNonNull2(orFilters))
1104
+ type: new GraphQLList2(new GraphQLNonNull2(filters)),
1105
+ description: "At least one branch matches; ANDed with any sibling fields"
1106
+ },
1107
+ AND: {
1108
+ type: new GraphQLList2(new GraphQLNonNull2(filters)),
1109
+ description: "Every branch matches"
1110
+ },
1111
+ NOT: {
1112
+ type: filters,
1113
+ description: "Negates the nested filters"
969
1114
  }
970
1115
  })
971
1116
  });
@@ -974,7 +1119,7 @@ var generateTableFilterTypeCached = (table, tableName, cacheCtx, typeNameMapper,
974
1119
  };
975
1120
  var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromRelationName, withOrder, relationsDepthLimit, cacheCtx, typeNameMapper, usedTables = /* @__PURE__ */ new Set(), resolverFactory, currentDepth = 0, relationAggregateFactory) => {
976
1121
  const table = tables[tableName];
977
- const order = withOrder ? generateTableOrderTypeCached(table, tableName, typeNameMapper, cacheCtx) : void 0;
1122
+ const order = withOrder ? generateTableOrderTypeCached(table, tableName, typeNameMapper, cacheCtx, relationMap, tables) : void 0;
978
1123
  const filters = generateTableFilterTypeCached(table, tableName, cacheCtx, typeNameMapper, relationMap, tables);
979
1124
  const tableFields = generateTableSelectTypeFieldsCached(table, tableName);
980
1125
  const relationsForTable = relationMap[tableName];
@@ -1060,10 +1205,11 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1060
1205
  }
1061
1206
  const resolve = resolverFactory?.({ tableName, relationName, relEntry, isOne });
1062
1207
  if (isOne) {
1208
+ const isRequired = relation.optional === false;
1063
1209
  rawRelationFields.push([
1064
1210
  relationName,
1065
1211
  {
1066
- type: relType,
1212
+ type: isRequired ? new GraphQLNonNull2(relType) : relType,
1067
1213
  args: {
1068
1214
  where: { type: relSelectData.filters }
1069
1215
  },
@@ -1201,28 +1347,95 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
1201
1347
  outputs
1202
1348
  };
1203
1349
  };
1204
- 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]);
1205
- var extractOrderBy = (table, orderArgs) => orderByEntries(orderArgs).map(
1206
- ([column, direction]) => direction === "asc" ? asc(getColumns(table)[column]) : desc(getColumns(table)[column])
1207
- );
1208
- var extractFiltersColumn = (column, columnName, operators) => {
1209
- if (!operators.OR?.length) {
1210
- delete operators.OR;
1350
+ var orderByEntries = (orderArgs) => Object.entries(orderArgs).sort((a, b) => (b[1]?.priority ?? 0) - (a[1]?.priority ?? 0)).filter(([, config]) => config).map(([column, config]) => {
1351
+ if (typeof config === "object" && config.direction === void 0) {
1352
+ throw new GraphQLError3(`ORDER BY ${column}: ordering through a relation is not supported in this query`);
1353
+ }
1354
+ return [column, config.direction, config.nulls ?? void 0];
1355
+ });
1356
+ var orderExpressions = (expr, direction, nulls, dialectColumn) => {
1357
+ const directed = direction === "asc" ? asc(expr) : desc(expr);
1358
+ if (!nulls) {
1359
+ return [directed];
1360
+ }
1361
+ const isMySql = (dialectColumn.columnType ?? "").startsWith("MySql");
1362
+ if (isMySql) {
1363
+ const nullsKey = nulls === "first" ? desc(sql`(${expr} is null)`) : asc(sql`(${expr} is null)`);
1364
+ return [nullsKey, directed];
1365
+ }
1366
+ return [nulls === "first" ? sql`${directed} nulls first` : sql`${directed} nulls last`];
1367
+ };
1368
+ var extendRelationOrderChain = (parentTable, relationName, relEntry, ctx, chain) => {
1369
+ const targetTable = ctx.tables[relEntry.targetTableName];
1370
+ const relation = relEntry.relation ?? relEntry;
1371
+ if (!targetTable || !is3(relation, One2) || !isFilterableRelation(relation)) {
1372
+ throw new GraphQLError3(`ORDER BY ${relationName}: Relation cannot be used for ordering`);
1211
1373
  }
1212
- const entries = Object.entries(operators);
1213
- if (operators.OR) {
1214
- if (entries.length > 1) {
1215
- throw new GraphQLError3(`WHERE ${columnName}: Cannot specify both fields and 'OR' in column operators!`);
1374
+ ctx.aliases ??= { n: 0 };
1375
+ const aliasedTarget = aliasedTable(targetTable, `dgql_ord_${ctx.aliases.n++}`);
1376
+ const joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
1377
+ const relationWhere = relation.where ? relationsFilterToSQL(relation.isReversed ? parentTable : aliasedTarget, relation.where) : void 0;
1378
+ return {
1379
+ fromParts: [...chain?.fromParts ?? [], getTableAsAliasSQL(aliasedTarget)],
1380
+ conditions: [
1381
+ ...chain?.conditions ?? [],
1382
+ ...joinCondition ? [joinCondition] : [],
1383
+ ...relationWhere ? [relationWhere] : []
1384
+ ],
1385
+ table: aliasedTarget
1386
+ };
1387
+ };
1388
+ var collectOrderEntries = (table, tableKey, orderArgs, ctx, chain, out) => {
1389
+ const columns = getColumns(table);
1390
+ const relations = ctx?.relationMap[tableKey];
1391
+ for (const [key, config] of Object.entries(orderArgs)) {
1392
+ if (config === null || config === void 0) {
1393
+ continue;
1216
1394
  }
1217
- const variants2 = [];
1218
- for (const variant of operators.OR) {
1219
- const extracted = extractFiltersColumn(column, columnName, variant);
1220
- if (extracted) {
1221
- variants2.push(extracted);
1222
- }
1395
+ const column = columns[key];
1396
+ if (column) {
1397
+ out.push({
1398
+ expression: chain ? sql`(select ${column} from ${sql.join(chain.fromParts, sql`, `)} where ${and(...chain.conditions)})` : column,
1399
+ column,
1400
+ direction: config.direction,
1401
+ nulls: config.nulls ?? void 0,
1402
+ priority: config.priority ?? 0
1403
+ });
1404
+ continue;
1405
+ }
1406
+ const relEntry = relations?.[key];
1407
+ if (!relEntry || !ctx) {
1408
+ throw new GraphQLError3(`ORDER BY ${key}: Unknown column or relation`);
1223
1409
  }
1224
- return variants2.length ? variants2.length > 1 ? or(...variants2) : variants2[0] : void 0;
1410
+ const nextChain = extendRelationOrderChain(chain?.table ?? table, key, relEntry, ctx, chain);
1411
+ collectOrderEntries(nextChain.table, relEntry.targetTableName, config, ctx, nextChain, out);
1412
+ }
1413
+ };
1414
+ var extractOrderBy = (table, orderArgs, ctx) => {
1415
+ const entries = [];
1416
+ collectOrderEntries(table, ctx?.tableKey ?? "", orderArgs, ctx, void 0, entries);
1417
+ return entries.sort((a, b) => b.priority - a.priority).flatMap((entry) => orderExpressions(entry.expression, entry.direction, entry.nulls, entry.column));
1418
+ };
1419
+ var LIKE_ESCAPE_CHAR = "\\";
1420
+ var escapeLikeValue = (value) => value.replace(/[\\%_]/g, (char) => `\\${char}`);
1421
+ var safeLikeOps = {
1422
+ startsWith: { buildPattern: (value) => `${escapeLikeValue(value)}%`, insensitive: false },
1423
+ endsWith: { buildPattern: (value) => `%${escapeLikeValue(value)}`, insensitive: false },
1424
+ contains: { buildPattern: (value) => `%${escapeLikeValue(value)}%`, insensitive: false },
1425
+ iStartsWith: { buildPattern: (value) => `${escapeLikeValue(value)}%`, insensitive: true },
1426
+ iEndsWith: { buildPattern: (value) => `%${escapeLikeValue(value)}`, insensitive: true },
1427
+ iContains: { buildPattern: (value) => `%${escapeLikeValue(value)}%`, insensitive: true }
1428
+ };
1429
+ var safeLikeCondition = (column, pattern, insensitive) => {
1430
+ if (!insensitive) {
1431
+ return sql`${column} like ${pattern} escape ${LIKE_ESCAPE_CHAR}`;
1225
1432
  }
1433
+ const isPg = (column.columnType ?? "").startsWith("Pg");
1434
+ return isPg ? sql`${column} ilike ${pattern} escape ${LIKE_ESCAPE_CHAR}` : sql`lower(${column}) like ${pattern.toLowerCase()} escape ${LIKE_ESCAPE_CHAR}`;
1435
+ };
1436
+ var extractFiltersColumn = (column, columnName, operators) => {
1437
+ const { OR, AND, NOT, ...restOperators } = operators;
1438
+ const entries = Object.entries(restOperators);
1226
1439
  const singleValueOps = { eq, ne, gt, gte, lt, lte };
1227
1440
  const stringValueOps = { like, notLike, ilike, notIlike };
1228
1441
  const arrayValueOps = { inArray, notInArray };
@@ -1237,6 +1450,9 @@ var extractFiltersColumn = (column, columnName, operators) => {
1237
1450
  variants.push(singleValueOps[operatorName](column, singleValue));
1238
1451
  } else if (operatorName in stringValueOps) {
1239
1452
  variants.push(stringValueOps[operatorName](column, operatorValue));
1453
+ } else if (operatorName in safeLikeOps) {
1454
+ const { buildPattern, insensitive } = safeLikeOps[operatorName];
1455
+ variants.push(safeLikeCondition(column, buildPattern(operatorValue), insensitive));
1240
1456
  } else if (operatorName in arrayValueOps) {
1241
1457
  if (!operatorValue.length) {
1242
1458
  throw new GraphQLError3(`WHERE ${columnName}: Unable to use operator ${operatorName} with an empty array!`);
@@ -1245,6 +1461,34 @@ var extractFiltersColumn = (column, columnName, operators) => {
1245
1461
  variants.push(arrayValueOps[operatorName](column, arrayValue));
1246
1462
  } else if (operatorName in nullableOps) {
1247
1463
  variants.push(nullableOps[operatorName](column));
1464
+ } else {
1465
+ throw new GraphQLError3(`WHERE ${columnName}: Unknown operator: ${operatorName}`);
1466
+ }
1467
+ }
1468
+ if (AND?.length) {
1469
+ for (const variant of AND) {
1470
+ const extracted = extractFiltersColumn(column, columnName, variant);
1471
+ if (extracted) {
1472
+ variants.push(extracted);
1473
+ }
1474
+ }
1475
+ }
1476
+ if (NOT) {
1477
+ const extracted = extractFiltersColumn(column, columnName, NOT);
1478
+ if (extracted) {
1479
+ variants.push(not(extracted));
1480
+ }
1481
+ }
1482
+ if (OR?.length) {
1483
+ const orVariants = [];
1484
+ for (const variant of OR) {
1485
+ const extracted = extractFiltersColumn(column, columnName, variant);
1486
+ if (extracted) {
1487
+ orVariants.push(extracted);
1488
+ }
1489
+ }
1490
+ if (orVariants.length) {
1491
+ variants.push(orVariants.length > 1 ? or(...orVariants) : orVariants[0]);
1248
1492
  }
1249
1493
  }
1250
1494
  return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
@@ -1269,39 +1513,105 @@ var buildRelationJoinCondition = (parentTable, relation, aliasedTarget, relation
1269
1513
  }
1270
1514
  return conditions.length > 1 ? and(...conditions) : conditions[0];
1271
1515
  };
1516
+ var resolveJunctionColumn = (aliasedThrough, junctionRef, relationName) => {
1517
+ const throughColumns = getColumns(aliasedThrough);
1518
+ const key = junctionRef?._?.key;
1519
+ const byKey = key ? throughColumns[key] : void 0;
1520
+ if (byKey) {
1521
+ return byKey;
1522
+ }
1523
+ const columnName = junctionRef?._?.column?.name;
1524
+ const byName = columnName ? Object.values(throughColumns).find((c) => c.name === columnName) : void 0;
1525
+ if (!byName) {
1526
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1527
+ }
1528
+ return byName;
1529
+ };
1530
+ var buildThroughJoinConditions = (parentTable, relation, aliasedThrough, aliasedTarget, relationName) => {
1531
+ const sourceColumns = relation.sourceColumns;
1532
+ const targetColumns = relation.targetColumns;
1533
+ const through = relation.through;
1534
+ if (!sourceColumns?.length || !targetColumns?.length || through?.source.length !== sourceColumns.length || through.target.length !== targetColumns.length) {
1535
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1536
+ }
1537
+ const parentColumns = Object.values(getColumns(parentTable));
1538
+ const targetTableColumns = Object.values(getColumns(aliasedTarget));
1539
+ const correlationConditions = [];
1540
+ for (let i = 0; i < sourceColumns.length; i++) {
1541
+ const localColumn = parentColumns.find((c) => c.name === sourceColumns[i].name);
1542
+ if (!localColumn) {
1543
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1544
+ }
1545
+ correlationConditions.push(eq(localColumn, resolveJunctionColumn(aliasedThrough, through.source[i], relationName)));
1546
+ }
1547
+ const junctionJoinConditions = [];
1548
+ for (let i = 0; i < targetColumns.length; i++) {
1549
+ const foreignColumn = targetTableColumns.find((c) => c.name === targetColumns[i].name);
1550
+ if (!foreignColumn) {
1551
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1552
+ }
1553
+ junctionJoinConditions.push(
1554
+ eq(resolveJunctionColumn(aliasedThrough, through.target[i], relationName), foreignColumn)
1555
+ );
1556
+ }
1557
+ return {
1558
+ correlation: correlationConditions.length > 1 ? and(...correlationConditions) : correlationConditions[0],
1559
+ junctionJoin: junctionJoinConditions.length > 1 ? and(...junctionJoinConditions) : junctionJoinConditions[0]
1560
+ };
1561
+ };
1272
1562
  var buildRelationExists = (parentTable, relationName, relEntry, innerFilters, mode, ctx) => {
1273
1563
  const { targetTableName } = relEntry;
1274
1564
  const targetTable = ctx.tables[targetTableName];
1275
1565
  const relation = relEntry.relation ?? relEntry;
1276
- if (!targetTable || !isFilterableRelation(relation)) {
1566
+ if (!targetTable) {
1277
1567
  throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1278
1568
  }
1279
1569
  ctx.aliases ??= { n: 0 };
1280
1570
  const aliases = ctx.aliases;
1281
1571
  const aliasedTarget = aliasedTable(targetTable, `dgql_rel_${aliases.n++}`);
1282
- const joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
1572
+ const throughTable = relation.throughTable;
1573
+ let fromClause;
1574
+ let joinCondition;
1575
+ if (throughTable) {
1576
+ const aliasedThrough = aliasedTable(throughTable, `dgql_rel_${aliases.n++}`);
1577
+ const { correlation, junctionJoin } = buildThroughJoinConditions(
1578
+ parentTable,
1579
+ relation,
1580
+ aliasedThrough,
1581
+ aliasedTarget,
1582
+ relationName
1583
+ );
1584
+ fromClause = sql`${getTableAsAliasSQL(aliasedTarget)} inner join ${getTableAsAliasSQL(aliasedThrough)} on ${junctionJoin}`;
1585
+ joinCondition = correlation;
1586
+ } else {
1587
+ fromClause = getTableAsAliasSQL(aliasedTarget);
1588
+ joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
1589
+ }
1283
1590
  const relationWhere = relation.where ? relationsFilterToSQL(relation.isReversed ? parentTable : aliasedTarget, relation.where) : void 0;
1284
1591
  const inner = innerFilters ? extractFilters(aliasedTarget, targetTableName, innerFilters, { ...ctx, tableKey: targetTableName, aliases }) : void 0;
1285
1592
  if (mode === "every") {
1286
1593
  if (!inner) {
1287
1594
  return void 0;
1288
1595
  }
1289
- return sql`not exists (select 1 from ${getTableAsAliasSQL(aliasedTarget)} where ${and(joinCondition, relationWhere, not(inner))})`;
1596
+ return sql`not exists (select 1 from ${fromClause} where ${and(joinCondition, relationWhere, not(inner))})`;
1290
1597
  }
1291
1598
  const condition = and(joinCondition, relationWhere, inner);
1292
- return mode === "none" ? sql`not exists (select 1 from ${getTableAsAliasSQL(aliasedTarget)} where ${condition})` : sql`exists (select 1 from ${getTableAsAliasSQL(aliasedTarget)} where ${condition})`;
1599
+ return mode === "none" ? sql`not exists (select 1 from ${fromClause} where ${condition})` : sql`exists (select 1 from ${fromClause} where ${condition})`;
1293
1600
  };
1294
1601
  var extractRelationFilter = (parentTable, relationName, relEntry, value, ctx) => {
1295
1602
  const relation = relEntry.relation ?? relEntry;
1296
1603
  if (is3(relation, One2)) {
1297
1604
  return buildRelationExists(parentTable, relationName, relEntry, value, "some", ctx);
1298
1605
  }
1606
+ const relationMatchModes = ["some", "none", "every"];
1299
1607
  const variants = [];
1300
- for (const mode of ["some", "none", "every"]) {
1301
- const inner = value[mode];
1608
+ for (const [mode, inner] of Object.entries(value)) {
1302
1609
  if (inner === void 0 || inner === null) {
1303
1610
  continue;
1304
1611
  }
1612
+ if (!relationMatchModes.includes(mode)) {
1613
+ throw new GraphQLError3(`WHERE ${relationName}: Unknown relation filter key: ${mode}`);
1614
+ }
1305
1615
  const extracted = buildRelationExists(parentTable, relationName, relEntry, inner, mode, ctx);
1306
1616
  if (extracted) {
1307
1617
  variants.push(extracted);
@@ -1310,26 +1620,8 @@ var extractRelationFilter = (parentTable, relationName, relEntry, value, ctx) =>
1310
1620
  return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
1311
1621
  };
1312
1622
  var extractFilters = (table, tableName, filters, relationCtx) => {
1313
- if (!filters.OR?.length) {
1314
- delete filters.OR;
1315
- }
1316
- const entries = Object.entries(filters);
1317
- if (!entries.length) {
1318
- return;
1319
- }
1320
- if (filters.OR) {
1321
- if (entries.length > 1) {
1322
- throw new GraphQLError3(`WHERE ${tableName}: Cannot specify both fields and 'OR' in table filters!`);
1323
- }
1324
- const variants2 = [];
1325
- for (const variant of filters.OR) {
1326
- const extracted = extractFilters(table, tableName, variant, relationCtx);
1327
- if (extracted) {
1328
- variants2.push(extracted);
1329
- }
1330
- }
1331
- return variants2.length ? variants2.length > 1 ? or(...variants2) : variants2[0] : void 0;
1332
- }
1623
+ const { OR, AND, NOT, ...fieldFilters } = filters;
1624
+ const entries = Object.entries(fieldFilters);
1333
1625
  const columns = getColumns(table);
1334
1626
  const relations = relationCtx?.relationMap[relationCtx.tableKey];
1335
1627
  const variants = [];
@@ -1338,11 +1630,40 @@ var extractFilters = (table, tableName, filters, relationCtx) => {
1338
1630
  continue;
1339
1631
  }
1340
1632
  const column = columns[fieldName];
1341
- const extracted = column ? extractFiltersColumn(column, fieldName, operators) : relations?.[fieldName] && relationCtx ? extractRelationFilter(table, fieldName, relations[fieldName], operators, relationCtx) : void 0;
1633
+ if (!column && !(relations?.[fieldName] && relationCtx)) {
1634
+ throw new GraphQLError3(`WHERE ${tableName}: Unknown filter key: ${fieldName}`);
1635
+ }
1636
+ const extracted = column ? extractFiltersColumn(column, fieldName, operators) : extractRelationFilter(table, fieldName, relations[fieldName], operators, relationCtx);
1342
1637
  if (extracted) {
1343
1638
  variants.push(extracted);
1344
1639
  }
1345
1640
  }
1641
+ if (AND?.length) {
1642
+ for (const variant of AND) {
1643
+ const extracted = extractFilters(table, tableName, variant, relationCtx);
1644
+ if (extracted) {
1645
+ variants.push(extracted);
1646
+ }
1647
+ }
1648
+ }
1649
+ if (NOT) {
1650
+ const extracted = extractFilters(table, tableName, NOT, relationCtx);
1651
+ if (extracted) {
1652
+ variants.push(not(extracted));
1653
+ }
1654
+ }
1655
+ if (OR?.length) {
1656
+ const orVariants = [];
1657
+ for (const variant of OR) {
1658
+ const extracted = extractFilters(table, tableName, variant, relationCtx);
1659
+ if (extracted) {
1660
+ orVariants.push(extracted);
1661
+ }
1662
+ }
1663
+ if (orVariants.length) {
1664
+ variants.push(orVariants.length > 1 ? or(...orVariants) : orVariants[0]);
1665
+ }
1666
+ }
1346
1667
  return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
1347
1668
  };
1348
1669
  var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, originField, typeNameMapper, _isInitial = false, filterCtx) => {
@@ -1384,7 +1705,7 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
1384
1705
  } : void 0;
1385
1706
  const hasPagination = offset != null || limit != null;
1386
1707
  const pkNames = targetPkNames ?? [];
1387
- thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, relationArgs.orderBy) : hasPagination && pkNames.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0;
1708
+ thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, relationArgs.orderBy, relationFilterCtx(filterCtx, targetTableName)) : hasPagination && pkNames.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0;
1388
1709
  thisRecord.offset = offset;
1389
1710
  thisRecord.limit = limit;
1390
1711
  const relWith = relationField ? extractRelationsParamsInner(
@@ -1625,7 +1946,9 @@ var selectDistinctKeys = async (params) => {
1625
1946
  }
1626
1947
  const orderEntries = orderBy ? orderByEntries(orderBy) : [];
1627
1948
  const windowOrder = [
1628
- ...orderEntries.map(([column, direction]) => direction === "asc" ? asc(cols[column]) : desc(cols[column])),
1949
+ ...orderEntries.flatMap(
1950
+ ([column, direction, nulls]) => orderExpressions(cols[column], direction, nulls, cols[column])
1951
+ ),
1629
1952
  ...primaryKeyOrderExprs(table, pkNames)
1630
1953
  ];
1631
1954
  const rowNumber = sql`row_number() over (partition by ${sql.join(partitionCols, sql`, `)} order by ${sql.join(
@@ -1634,7 +1957,9 @@ var selectDistinctKeys = async (params) => {
1634
1957
  )})`.as(DISTINCT_RN);
1635
1958
  const sub = db.select({ ...cols, [DISTINCT_RN]: rowNumber }).from(table).where(where).as("__dgql_distinct");
1636
1959
  const outerOrder = [
1637
- ...orderEntries.map(([column, direction]) => direction === "asc" ? asc(sub[column]) : desc(sub[column])),
1960
+ ...orderEntries.flatMap(
1961
+ ([column, direction, nulls]) => orderExpressions(sub[column], direction, nulls, cols[column])
1962
+ ),
1638
1963
  ...pkNames.filter((name) => sub[name]).map((name) => asc(sub[name]))
1639
1964
  ];
1640
1965
  let query = db.select(Object.fromEntries(pkNames.map((name) => [name, sub[name]]))).from(sub).where(eq(sub[DISTINCT_RN], 1)).orderBy(...outerOrder);
@@ -1725,6 +2050,7 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
1725
2050
  const listFieldName = (mapped?.plural ?? uncapitalize(tableName)) + suffixes.list;
1726
2051
  const singleFieldName = mapped?.singular ?? uncapitalize(tableName) + suffixes.single;
1727
2052
  const aggregateFieldName = `${mapped?.plural ?? uncapitalize(tableName)}Aggregate`;
2053
+ const groupByFieldName = `${mapped?.plural ?? uncapitalize(tableName)}GroupBy`;
1728
2054
  const createArrayFieldName = `${prefixes.insert}${mapped ? capitalize(mapped.plural) : capitalize(tableName)}`;
1729
2055
  const createSingleFieldName = mapped ? `${prefixes.insert}${capitalize(mapped.singular)}` : `${prefixes.insert}${capitalize(tableName)}${suffixes.single}`;
1730
2056
  const upsertPrefix = prefixes.upsert ?? "upsert";
@@ -1732,19 +2058,38 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
1732
2058
  const upsertSingleFieldName = mapped ? `${upsertPrefix}${capitalize(mapped.singular)}` : `${upsertPrefix}${capitalize(tableName)}${suffixes.single}`;
1733
2059
  const updateFieldName = `${prefixes.update}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
1734
2060
  const deleteFieldName = `${prefixes.delete}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
2061
+ const writeSingleSuffix = suffixes.single === "" ? "Single" : suffixes.single;
2062
+ const updateSingleFieldName = `${updateFieldName}${writeSingleSuffix}`;
2063
+ const deleteSingleFieldName = `${deleteFieldName}${writeSingleSuffix}`;
1735
2064
  return {
1736
2065
  typeName,
1737
2066
  listFieldName,
1738
2067
  singleFieldName,
1739
2068
  aggregateFieldName,
2069
+ groupByFieldName,
1740
2070
  createArrayFieldName,
1741
2071
  createSingleFieldName,
1742
2072
  upsertArrayFieldName,
1743
2073
  upsertSingleFieldName,
1744
2074
  updateFieldName,
1745
- deleteFieldName
2075
+ updateSingleFieldName,
2076
+ deleteFieldName,
2077
+ deleteSingleFieldName
1746
2078
  };
1747
2079
  };
2080
+ var extractRequiredFilters = (table, tableName, where, fieldName, relationCtx) => {
2081
+ const filters = where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2082
+ if (!filters) {
2083
+ throw new GraphQLError3(`${fieldName} requires a 'where' argument with at least one filter!`);
2084
+ }
2085
+ return filters;
2086
+ };
2087
+ var assertSingleMatch = async (executor, table, filters, fieldName) => {
2088
+ const matched = await executor.select({ found: sql`1` }).from(table).where(filters).limit(2);
2089
+ if (matched.length > 1) {
2090
+ throw new GraphQLError3(`${fieldName}: 'where' matched more than one row \u2014 nothing was written!`);
2091
+ }
2092
+ };
1748
2093
  var selectArrayArgs = (orderArgs, filterArgs, distinctEnum) => ({
1749
2094
  offset: { type: GraphQLInt2 },
1750
2095
  limit: { type: GraphQLInt2 },
@@ -1803,9 +2148,9 @@ var runRelationalSelect = async (opts) => {
1803
2148
  // drizzle-orm v1 RQB calls orderBy/where with the aliased table proxy — use it
1804
2149
  // directly so column refs match the CTE alias.
1805
2150
  orderBy: distinctKeys ? (aliasedTable2) => [
1806
- ...orderBy ? extractOrderBy(aliasedTable2, orderBy) : [],
2151
+ ...orderBy ? extractOrderBy(aliasedTable2, orderBy, relationFilterCtx(filterCtx, tableName)) : [],
1807
2152
  ...primaryKeyOrderExprs(aliasedTable2, pkNames)
1808
- ] : orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, orderBy) : needsDefaultOrder && pkNames?.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0,
2153
+ ] : orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, orderBy, relationFilterCtx(filterCtx, tableName)) : needsDefaultOrder && pkNames?.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0,
1809
2154
  where: distinctKeys ? { RAW: (aliasedTable2) => primaryKeyRestriction(aliasedTable2, pkNames, distinctKeys) } : where ? {
1810
2155
  RAW: (aliasedTable2) => extractFilters(aliasedTable2, tableName, where, relationFilterCtx(filterCtx, tableName))
1811
2156
  } : void 0,
@@ -1892,7 +2237,7 @@ import { is as is4, One as One3 } from "drizzle-orm";
1892
2237
  import { getTableConfig, MySqlTable } from "drizzle-orm/mysql-core";
1893
2238
  import {
1894
2239
  GraphQLBoolean as GraphQLBoolean3,
1895
- GraphQLError as GraphQLError4,
2240
+ GraphQLError as GraphQLError5,
1896
2241
  GraphQLList as GraphQLList4,
1897
2242
  GraphQLNonNull as GraphQLNonNull4,
1898
2243
  GraphQLObjectType as GraphQLObjectType4
@@ -1905,15 +2250,23 @@ import {
1905
2250
  avg,
1906
2251
  count,
1907
2252
  countDistinct,
2253
+ eq as eq2,
1908
2254
  extractExtendedColumnType as extractExtendedColumnType2,
1909
2255
  getColumns as getColumns2,
2256
+ gt as gt2,
2257
+ gte as gte2,
1910
2258
  inArray as inArray2,
2259
+ lt as lt2,
2260
+ lte as lte2,
1911
2261
  max,
1912
2262
  min,
2263
+ ne as ne2,
1913
2264
  sum
1914
2265
  } from "drizzle-orm";
1915
2266
  import {
1916
- GraphQLFloat as GraphQLFloat2,
2267
+ GraphQLError as GraphQLError4,
2268
+ GraphQLFloat as GraphQLFloat3,
2269
+ GraphQLInputObjectType as GraphQLInputObjectType3,
1917
2270
  GraphQLInt as GraphQLInt3,
1918
2271
  GraphQLList as GraphQLList3,
1919
2272
  GraphQLNonNull as GraphQLNonNull3,
@@ -1970,7 +2323,7 @@ var generateAggregateTypes = (table, tableName, typeName, cacheCtx) => {
1970
2323
  fields[op] = {
1971
2324
  type: new GraphQLObjectType3({
1972
2325
  name: `${typeName}${capitalize(op)}Aggregate`,
1973
- fields: Object.fromEntries(Object.keys(numeric).map((columnName) => [columnName, { type: GraphQLFloat2 }]))
2326
+ fields: Object.fromEntries(Object.keys(numeric).map((columnName) => [columnName, { type: GraphQLFloat3 }]))
1974
2327
  })
1975
2328
  };
1976
2329
  }
@@ -2034,9 +2387,9 @@ var aggregateTarget = (table, tableName, typeName) => {
2034
2387
  )
2035
2388
  };
2036
2389
  };
2037
- var parseAggregateRequest = (info, target) => {
2390
+ var parseAggregateRequest = (info, target, rootTypeName = `${target.typeName}Aggregate`) => {
2038
2391
  const parsedInfo = parseResolveInfo(info, { deep: true });
2039
- const selectionTree = parsedInfo.fieldsByTypeName[`${target.typeName}Aggregate`] ?? {};
2392
+ const selectionTree = parsedInfo.fieldsByTypeName[rootTypeName] ?? {};
2040
2393
  const request = {
2041
2394
  count: false,
2042
2395
  ops: { avg: [], sum: [], min: [], max: [], countNonNull: [], countDistinct: [] },
@@ -2174,6 +2527,184 @@ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filt
2174
2527
  return { type, resolve };
2175
2528
  };
2176
2529
  };
2530
+ var GROUP_COL = `group${SEP}`;
2531
+ var HAVING_OPS = { eq: eq2, ne: ne2, gt: gt2, gte: gte2, lt: lt2, lte: lte2 };
2532
+ var groupableColumns = (table, tableName) => {
2533
+ const { orderable } = classifyAggregateColumns(table, tableName);
2534
+ const groupable = { ...orderable };
2535
+ for (const [columnName, column] of Object.entries(getColumns2(table))) {
2536
+ if (groupable[columnName]) {
2537
+ continue;
2538
+ }
2539
+ const { type: dataType } = extractExtendedColumnType2(column);
2540
+ if (dataType !== "boolean") {
2541
+ continue;
2542
+ }
2543
+ groupable[columnName] = {
2544
+ column,
2545
+ converted: drizzleColumnToGraphQLType(column, columnName, tableName, true, false, false)
2546
+ };
2547
+ }
2548
+ return groupable;
2549
+ };
2550
+ var generateGroupByEnum = (table, tableName, typeName) => {
2551
+ const groupable = groupableColumns(table, tableName);
2552
+ return generateColumnEnum(
2553
+ table,
2554
+ `${typeName}GroupByColumn`,
2555
+ `Columns of ${typeName} that a query can group by`,
2556
+ (_column, columnName) => Boolean(groupable[columnName])
2557
+ );
2558
+ };
2559
+ var aggregateNumberFilter = new GraphQLInputObjectType3({
2560
+ name: "AggregateNumberFilter",
2561
+ description: "Compares an aggregated value. Several operators in one filter are ANDed together.",
2562
+ fields: Object.fromEntries(Object.keys(HAVING_OPS).map((op) => [op, { type: GraphQLFloat3 }]))
2563
+ });
2564
+ var generateHavingInput = (table, tableName, typeName) => {
2565
+ const { numeric, orderable, all } = classifyAggregateColumns(table, tableName);
2566
+ const fields = {
2567
+ count: { type: aggregateNumberFilter, description: "Filters groups by how many rows they contain" }
2568
+ };
2569
+ const opColumns = {
2570
+ avg: numeric,
2571
+ sum: numeric,
2572
+ min: numeric,
2573
+ max: numeric,
2574
+ countNonNull: all,
2575
+ countDistinct: orderable
2576
+ };
2577
+ for (const [op, columns] of Object.entries(opColumns)) {
2578
+ const columnNames = Object.keys(columns);
2579
+ if (!columnNames.length) {
2580
+ continue;
2581
+ }
2582
+ fields[op] = {
2583
+ type: new GraphQLInputObjectType3({
2584
+ name: `${typeName}${capitalize(op)}Having`,
2585
+ fields: Object.fromEntries(columnNames.map((columnName) => [columnName, { type: aggregateNumberFilter }]))
2586
+ })
2587
+ };
2588
+ }
2589
+ return new GraphQLInputObjectType3({
2590
+ name: `${typeName}Having`,
2591
+ description: `Filters ${typeName} groups by their aggregated values`,
2592
+ fields
2593
+ });
2594
+ };
2595
+ var generateGroupByType = (table, tableName, typeName, cacheCtx) => {
2596
+ const groupable = groupableColumns(table, tableName);
2597
+ if (!Object.keys(groupable).length) {
2598
+ return void 0;
2599
+ }
2600
+ const keysType = new GraphQLObjectType3({
2601
+ name: `${typeName}GroupKeys`,
2602
+ description: `The grouped column values of one ${typeName} group. A column the query did not group by is null.`,
2603
+ fields: Object.fromEntries(
2604
+ Object.entries(groupable).map(([columnName, { converted }]) => [
2605
+ columnName,
2606
+ { type: converted.type, description: converted.description }
2607
+ ])
2608
+ )
2609
+ });
2610
+ const aggregateType = generateAggregateTypes(table, tableName, typeName, cacheCtx);
2611
+ const aggregateFields = Object.fromEntries(
2612
+ Object.values(aggregateType.getFields()).map((field) => [
2613
+ field.name,
2614
+ { type: field.type, description: field.description ?? void 0 }
2615
+ ])
2616
+ );
2617
+ return new GraphQLObjectType3({
2618
+ name: `${typeName}GroupBy`,
2619
+ fields: { group: { type: new GraphQLNonNull3(keysType) }, ...aggregateFields }
2620
+ });
2621
+ };
2622
+ var havingComparisons = (expression, filter) => Object.entries(filter).filter(([op, value]) => value != null && op in HAVING_OPS).map(([op, value]) => HAVING_OPS[op](expression, value));
2623
+ var buildHavingCondition = (having, columns) => {
2624
+ if (!having) {
2625
+ return void 0;
2626
+ }
2627
+ const conditions = [];
2628
+ for (const [key, value] of Object.entries(having)) {
2629
+ if (value == null) {
2630
+ continue;
2631
+ }
2632
+ if (key === "count") {
2633
+ conditions.push(...havingComparisons(count(), value));
2634
+ continue;
2635
+ }
2636
+ if (!AGGREGATE_OPS.includes(key)) {
2637
+ continue;
2638
+ }
2639
+ for (const [columnName, filter] of Object.entries(value)) {
2640
+ const column = columns[columnName];
2641
+ if (!column || filter == null) {
2642
+ continue;
2643
+ }
2644
+ conditions.push(...havingComparisons(OP_FNS[key](column), filter));
2645
+ }
2646
+ }
2647
+ return conditions.length ? and2(...conditions) : void 0;
2648
+ };
2649
+ var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, groupByEnum, havingInput, filterCtx) => {
2650
+ const target = aggregateTarget(table, tableName, typeName);
2651
+ const groupable = groupableColumns(table, tableName);
2652
+ const columns = getColumns2(table);
2653
+ const rootTypeName = `${typeName}GroupBy`;
2654
+ const queryArgs = {
2655
+ groupBy: {
2656
+ type: new GraphQLNonNull3(new GraphQLList3(new GraphQLNonNull3(groupByEnum))),
2657
+ description: "Columns to group by. One result row per distinct combination of their values."
2658
+ },
2659
+ where: { type: filterArgs, description: "Filters the rows before they are grouped." },
2660
+ having: { type: havingInput, description: "Filters the groups after they are aggregated." }
2661
+ };
2662
+ return {
2663
+ name: fieldName,
2664
+ resolver: async (_source, args, context, info) => {
2665
+ try {
2666
+ const requestedKeys = [...new Set(args.groupBy ?? [])];
2667
+ if (!requestedKeys.length) {
2668
+ throw new GraphQLError4("At least one column to group by is required!");
2669
+ }
2670
+ const keyColumns = requestedKeys.map((columnName) => {
2671
+ const groupableColumn = groupable[columnName];
2672
+ if (!groupableColumn) {
2673
+ throw new GraphQLError4(`Cannot group ${typeName} by ${columnName}!`);
2674
+ }
2675
+ return [columnName, groupableColumn.column];
2676
+ });
2677
+ const request = parseAggregateRequest(info, target, rootTypeName);
2678
+ const selection = {
2679
+ ...Object.fromEntries(keyColumns.map(([columnName, column]) => [`${GROUP_COL}${columnName}`, column])),
2680
+ ...request.selection
2681
+ };
2682
+ let query = resolveExecutor(db, context).select(selection).from(table);
2683
+ if (args.where) {
2684
+ query = query.where(extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)));
2685
+ }
2686
+ query = query.groupBy(...keyColumns.map(([, column]) => column));
2687
+ const havingCondition = buildHavingCondition(args.having, columns);
2688
+ if (havingCondition) {
2689
+ query = query.having(havingCondition);
2690
+ }
2691
+ const rows = await query;
2692
+ return rows.map((row) => {
2693
+ const group = {};
2694
+ for (const [columnName, column] of keyColumns) {
2695
+ const value = row[`${GROUP_COL}${columnName}`];
2696
+ const decoded = typeof value === "string" && target.dateTimeColumns.has(columnName) ? parseDriverDateTime(value) : value;
2697
+ group[columnName] = value == null ? null : remapToGraphQLCore(columnName, decoded, tableName, column);
2698
+ }
2699
+ return { group, ...assembleAggregateRow(row, request, target) };
2700
+ });
2701
+ } catch (e) {
2702
+ throw toGraphQLError(e);
2703
+ }
2704
+ },
2705
+ args: queryArgs
2706
+ };
2707
+ };
2177
2708
 
2178
2709
  // src/util/builders/mysql.ts
2179
2710
  var generateSelectArray = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
@@ -2268,7 +2799,7 @@ var generateInsertArray = (db, _tableName, table, baseType, fieldName) => {
2268
2799
  try {
2269
2800
  const input = remapFromGraphQLArrayInput(args.values, table);
2270
2801
  if (!input.length) {
2271
- throw new GraphQLError4("No values were provided!");
2802
+ throw new GraphQLError5("No values were provided!");
2272
2803
  }
2273
2804
  await resolveExecutor(db, context).insert(table).values(input);
2274
2805
  return { isSuccess: true };
@@ -2316,7 +2847,7 @@ var generateUpsert = (db, table, baseType, onConflictType, fieldName, single) =>
2316
2847
  try {
2317
2848
  const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
2318
2849
  if (!input.length) {
2319
- throw new GraphQLError4("No values were provided!");
2850
+ throw new GraphQLError5("No values were provided!");
2320
2851
  }
2321
2852
  const plan = resolveConflictPlan({
2322
2853
  table,
@@ -2341,13 +2872,13 @@ var generateUpsert = (db, table, baseType, onConflictType, fieldName, single) =>
2341
2872
  args: queryArgs
2342
2873
  };
2343
2874
  };
2344
- var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filterCtx) => {
2875
+ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, single, requireWhere, filterCtx) => {
2345
2876
  const queryArgs = {
2346
2877
  set: {
2347
2878
  type: new GraphQLNonNull4(setArgs)
2348
2879
  },
2349
2880
  where: {
2350
- type: filterArgs
2881
+ type: single || requireWhere ? new GraphQLNonNull4(filterArgs) : filterArgs
2351
2882
  }
2352
2883
  };
2353
2884
  return {
@@ -2357,12 +2888,16 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
2357
2888
  const { where, set } = args;
2358
2889
  const input = remapFromGraphQLSingleInput(set, table);
2359
2890
  if (!Object.keys(input).length) {
2360
- throw new GraphQLError4("Unable to update with no values specified!");
2891
+ throw new GraphQLError5("Unable to update with no values specified!");
2361
2892
  }
2893
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
2894
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2362
2895
  const executor = resolveExecutor(db, context);
2896
+ if (single) {
2897
+ await assertSingleMatch(executor, table, filters, fieldName);
2898
+ }
2363
2899
  let query = executor.update(table).set(input);
2364
- if (where) {
2365
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
2900
+ if (filters) {
2366
2901
  query = query.where(filters);
2367
2902
  }
2368
2903
  await query;
@@ -2374,10 +2909,10 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
2374
2909
  args: queryArgs
2375
2910
  };
2376
2911
  };
2377
- var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) => {
2912
+ var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requireWhere, filterCtx) => {
2378
2913
  const queryArgs = {
2379
2914
  where: {
2380
- type: filterArgs
2915
+ type: single || requireWhere ? new GraphQLNonNull4(filterArgs) : filterArgs
2381
2916
  }
2382
2917
  };
2383
2918
  return {
@@ -2385,10 +2920,14 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) =>
2385
2920
  resolver: async (_source, args, context, _info) => {
2386
2921
  try {
2387
2922
  const { where } = args;
2923
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
2924
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2388
2925
  const executor = resolveExecutor(db, context);
2926
+ if (single) {
2927
+ await assertSingleMatch(executor, table, filters, fieldName);
2928
+ }
2389
2929
  let query = executor.delete(table);
2390
- if (where) {
2391
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
2930
+ if (filters) {
2392
2931
  query = query.where(filters);
2393
2932
  }
2394
2933
  await query;
@@ -2471,12 +3010,15 @@ var generateSchemaData = (db, schema, relations, options) => {
2471
3010
  listFieldName,
2472
3011
  singleFieldName,
2473
3012
  aggregateFieldName,
3013
+ groupByFieldName,
2474
3014
  createArrayFieldName,
2475
3015
  createSingleFieldName,
2476
3016
  upsertArrayFieldName,
2477
3017
  upsertSingleFieldName,
2478
3018
  updateFieldName,
2479
- deleteFieldName
3019
+ updateSingleFieldName,
3020
+ deleteFieldName,
3021
+ deleteSingleFieldName
2480
3022
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
2481
3023
  const selectArrGenerated = generateSelectArray(
2482
3024
  db,
@@ -2521,9 +3063,41 @@ var generateSchemaData = (db, schema, relations, options) => {
2521
3063
  updateInput,
2522
3064
  tableFilters,
2523
3065
  updateFieldName,
3066
+ false,
3067
+ features.requireWhere,
3068
+ filterCtx
3069
+ ) : void 0;
3070
+ const updateSingleGenerated = features.update ? generateUpdate(
3071
+ db,
3072
+ tableName,
3073
+ schema[tableName],
3074
+ updateInput,
3075
+ tableFilters,
3076
+ updateSingleFieldName,
3077
+ true,
3078
+ features.requireWhere,
3079
+ filterCtx
3080
+ ) : void 0;
3081
+ const deleteGenerated = features.delete ? generateDelete(
3082
+ db,
3083
+ tableName,
3084
+ schema[tableName],
3085
+ tableFilters,
3086
+ deleteFieldName,
3087
+ false,
3088
+ features.requireWhere,
3089
+ filterCtx
3090
+ ) : void 0;
3091
+ const deleteSingleGenerated = features.delete ? generateDelete(
3092
+ db,
3093
+ tableName,
3094
+ schema[tableName],
3095
+ tableFilters,
3096
+ deleteSingleFieldName,
3097
+ true,
3098
+ features.requireWhere,
2524
3099
  filterCtx
2525
3100
  ) : void 0;
2526
- const deleteGenerated = features.delete ? generateDelete(db, tableName, schema[tableName], tableFilters, deleteFieldName, filterCtx) : void 0;
2527
3101
  const aggregateType = features.aggregates ? generateAggregateTypes(schema[tableName], tableName, typeName, cacheCtx) : void 0;
2528
3102
  const aggregateGenerated = features.aggregates ? generateAggregate(
2529
3103
  db,
@@ -2534,6 +3108,20 @@ var generateSchemaData = (db, schema, relations, options) => {
2534
3108
  tableFilters,
2535
3109
  filterCtx
2536
3110
  ) : void 0;
3111
+ const groupByType = features.aggregates && features.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
3112
+ const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
3113
+ const havingInput = groupByEnum ? generateHavingInput(schema[tableName], tableName, typeName) : void 0;
3114
+ const groupByGenerated = groupByType && groupByEnum && havingInput ? generateGroupBy(
3115
+ db,
3116
+ tableName,
3117
+ schema[tableName],
3118
+ typeName,
3119
+ groupByFieldName,
3120
+ tableFilters,
3121
+ groupByEnum,
3122
+ havingInput,
3123
+ filterCtx
3124
+ ) : void 0;
2537
3125
  queries[selectArrGenerated.name] = {
2538
3126
  type: selectArrOutput,
2539
3127
  args: selectArrGenerated.args,
@@ -2553,13 +3141,23 @@ var generateSchemaData = (db, schema, relations, options) => {
2553
3141
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
2554
3142
  };
2555
3143
  }
3144
+ if (groupByGenerated && groupByType) {
3145
+ queries[groupByGenerated.name] = {
3146
+ type: new GraphQLNonNull4(new GraphQLList4(new GraphQLNonNull4(groupByType))),
3147
+ args: groupByGenerated.args,
3148
+ resolve: groupByGenerated.resolver,
3149
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
3150
+ };
3151
+ }
2556
3152
  for (const generated of [
2557
3153
  insertArrGenerated,
2558
3154
  insertSingleGenerated,
2559
3155
  upsertArrGenerated,
2560
3156
  upsertSingleGenerated,
2561
3157
  updateGenerated,
2562
- deleteGenerated
3158
+ updateSingleGenerated,
3159
+ deleteGenerated,
3160
+ deleteSingleGenerated
2563
3161
  ]) {
2564
3162
  if (generated) {
2565
3163
  mutations[generated.name] = {
@@ -2584,6 +3182,10 @@ var generateSchemaData = (db, schema, relations, options) => {
2584
3182
  if (aggregateType) {
2585
3183
  outputs[aggregateType.name] = aggregateType;
2586
3184
  }
3185
+ if (groupByType && havingInput) {
3186
+ outputs[groupByType.name] = groupByType;
3187
+ inputs[havingInput.name] = havingInput;
3188
+ }
2587
3189
  }
2588
3190
  const fieldResolvers = {};
2589
3191
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -2606,7 +3208,7 @@ var generateSchemaData = (db, schema, relations, options) => {
2606
3208
  import { is as is5, One as One4 } from "drizzle-orm";
2607
3209
  import { getTableConfig as getTableConfig2, PgTable } from "drizzle-orm/pg-core";
2608
3210
  import {
2609
- GraphQLError as GraphQLError5,
3211
+ GraphQLError as GraphQLError6,
2610
3212
  GraphQLList as GraphQLList5,
2611
3213
  GraphQLNonNull as GraphQLNonNull5
2612
3214
  } from "graphql";
@@ -2675,7 +3277,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
2675
3277
  }
2676
3278
  if (orderBy) {
2677
3279
  q = q.orderBy(
2678
- ...extractOrderBy(table, orderBy),
3280
+ ...extractOrderBy(table, orderBy, relationFilterCtx(filterCtx, tableName)),
2679
3281
  ...distinctKeys ? primaryKeyOrderExprs(table, pkNames) : []
2680
3282
  );
2681
3283
  } else if ((distinctKeys || offset != null || limit != null) && pkNames.length) {
@@ -2736,7 +3338,7 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
2736
3338
  q = q.where(extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)));
2737
3339
  }
2738
3340
  if (orderBy) {
2739
- q = q.orderBy(...extractOrderBy(table, orderBy));
3341
+ q = q.orderBy(...extractOrderBy(table, orderBy, relationFilterCtx(filterCtx, tableName)));
2740
3342
  } else if (pkNames.length) {
2741
3343
  q = q.orderBy(...primaryKeyOrderExprs(table, pkNames));
2742
3344
  }
@@ -2767,7 +3369,7 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
2767
3369
  try {
2768
3370
  const input = remapFromGraphQLArrayInput(args.values, table);
2769
3371
  if (!input.length) {
2770
- throw new GraphQLError5("No values were provided!");
3372
+ throw new GraphQLError6("No values were provided!");
2771
3373
  }
2772
3374
  const parsedInfo = parseResolveInfo3(info, {
2773
3375
  deep: true
@@ -2857,7 +3459,7 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
2857
3459
  try {
2858
3460
  const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
2859
3461
  if (!input.length) {
2860
- throw new GraphQLError5("No values were provided!");
3462
+ throw new GraphQLError6("No values were provided!");
2861
3463
  }
2862
3464
  const parsedInfo = parseResolveInfo3(info, { deep: true });
2863
3465
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -2896,13 +3498,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
2896
3498
  args: queryArgs
2897
3499
  };
2898
3500
  };
2899
- var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
3501
+ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx) => {
2900
3502
  const queryArgs = {
2901
3503
  set: {
2902
3504
  type: new GraphQLNonNull5(setArgs)
2903
3505
  },
2904
3506
  where: {
2905
- type: filterArgs
3507
+ type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
2906
3508
  }
2907
3509
  };
2908
3510
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -2926,18 +3528,28 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
2926
3528
  });
2927
3529
  const input = remapFromGraphQLSingleInput(set, table);
2928
3530
  if (!Object.keys(input).length) {
2929
- throw new GraphQLError5("Unable to update with no values specified!");
3531
+ throw new GraphQLError6("Unable to update with no values specified!");
2930
3532
  }
3533
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
3534
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2931
3535
  const executor = resolveExecutor(db, context);
3536
+ if (single) {
3537
+ await assertSingleMatch(executor, table, filters, fieldName);
3538
+ }
2932
3539
  let query = executor.update(table).set(input);
2933
- if (where) {
2934
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
3540
+ if (filters) {
2935
3541
  query = query.where(filters);
2936
3542
  }
2937
3543
  query = query.returning(columns);
2938
3544
  const result = await query;
3545
+ if (single && result.length > 1) {
3546
+ throw new GraphQLError6(`${fieldName}: 'where' matched more than one row!`);
3547
+ }
3548
+ if (single && !result[0]) {
3549
+ return void 0;
3550
+ }
2939
3551
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
2940
- return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
3552
+ return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
2941
3553
  } catch (e) {
2942
3554
  throw toGraphQLError(e);
2943
3555
  }
@@ -2945,10 +3557,10 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
2945
3557
  args: queryArgs
2946
3558
  };
2947
3559
  };
2948
- var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
3560
+ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
2949
3561
  const queryArgs = {
2950
3562
  where: {
2951
- type: filterArgs
3563
+ type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
2952
3564
  }
2953
3565
  };
2954
3566
  return {
@@ -2964,14 +3576,24 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, fi
2964
3576
  table,
2965
3577
  selectionCtx
2966
3578
  );
3579
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
3580
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2967
3581
  const executor = resolveExecutor(db, context);
3582
+ if (single) {
3583
+ await assertSingleMatch(executor, table, filters, fieldName);
3584
+ }
2968
3585
  let query = executor.delete(table);
2969
- if (where) {
2970
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
3586
+ if (filters) {
2971
3587
  query = query.where(filters);
2972
3588
  }
2973
3589
  query = query.returning(columns);
2974
3590
  const result = await query;
3591
+ if (single && result.length > 1) {
3592
+ throw new GraphQLError6(`${fieldName}: 'where' matched more than one row!`);
3593
+ }
3594
+ if (single) {
3595
+ return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
3596
+ }
2975
3597
  return remapToGraphQLArrayOutput(result, tableName, table);
2976
3598
  } catch (e) {
2977
3599
  throw toGraphQLError(e);
@@ -3047,12 +3669,15 @@ function generateSchemaData2(db, schema, relations, options) {
3047
3669
  listFieldName,
3048
3670
  singleFieldName,
3049
3671
  aggregateFieldName,
3672
+ groupByFieldName,
3050
3673
  createArrayFieldName,
3051
3674
  createSingleFieldName,
3052
3675
  upsertArrayFieldName,
3053
3676
  upsertSingleFieldName,
3054
3677
  updateFieldName,
3055
- deleteFieldName
3678
+ updateSingleFieldName,
3679
+ deleteFieldName,
3680
+ deleteSingleFieldName
3056
3681
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
3057
3682
  const selectArrGenerated = generateSelectArray2(
3058
3683
  db,
@@ -3151,6 +3776,23 @@ function generateSchemaData2(db, schema, relations, options) {
3151
3776
  tableFilters,
3152
3777
  updateFieldName,
3153
3778
  typeName,
3779
+ false,
3780
+ features.requireWhere,
3781
+ typeNameMapper,
3782
+ filterCtx
3783
+ ) : void 0;
3784
+ const updateSingleGenerated = features.update ? generateUpdate2(
3785
+ db,
3786
+ tableName,
3787
+ schema[tableName],
3788
+ tables,
3789
+ eagerRelations,
3790
+ updateInput,
3791
+ tableFilters,
3792
+ updateSingleFieldName,
3793
+ typeName,
3794
+ true,
3795
+ features.requireWhere,
3154
3796
  typeNameMapper,
3155
3797
  filterCtx
3156
3798
  ) : void 0;
@@ -3161,6 +3803,20 @@ function generateSchemaData2(db, schema, relations, options) {
3161
3803
  tableFilters,
3162
3804
  deleteFieldName,
3163
3805
  typeName,
3806
+ false,
3807
+ features.requireWhere,
3808
+ filterCtx,
3809
+ { tableName, relationMap: namedRelations, tables }
3810
+ ) : void 0;
3811
+ const deleteSingleGenerated = features.delete ? generateDelete2(
3812
+ db,
3813
+ tableName,
3814
+ schema[tableName],
3815
+ tableFilters,
3816
+ deleteSingleFieldName,
3817
+ typeName,
3818
+ true,
3819
+ features.requireWhere,
3164
3820
  filterCtx,
3165
3821
  { tableName, relationMap: namedRelations, tables }
3166
3822
  ) : void 0;
@@ -3174,6 +3830,20 @@ function generateSchemaData2(db, schema, relations, options) {
3174
3830
  tableFilters,
3175
3831
  filterCtx
3176
3832
  ) : void 0;
3833
+ const groupByType = features.aggregates && features.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
3834
+ const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
3835
+ const havingInput = groupByEnum ? generateHavingInput(schema[tableName], tableName, typeName) : void 0;
3836
+ const groupByGenerated = groupByType && groupByEnum && havingInput ? generateGroupBy(
3837
+ db,
3838
+ tableName,
3839
+ schema[tableName],
3840
+ typeName,
3841
+ groupByFieldName,
3842
+ tableFilters,
3843
+ groupByEnum,
3844
+ havingInput,
3845
+ filterCtx
3846
+ ) : void 0;
3177
3847
  queries[selectArrGenerated.name] = {
3178
3848
  type: selectArrOutput,
3179
3849
  args: selectArrGenerated.args,
@@ -3193,6 +3863,14 @@ function generateSchemaData2(db, schema, relations, options) {
3193
3863
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
3194
3864
  };
3195
3865
  }
3866
+ if (groupByGenerated && groupByType) {
3867
+ queries[groupByGenerated.name] = {
3868
+ type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(groupByType))),
3869
+ args: groupByGenerated.args,
3870
+ resolve: groupByGenerated.resolver,
3871
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
3872
+ };
3873
+ }
3196
3874
  if (insertArrGenerated) {
3197
3875
  mutations[insertArrGenerated.name] = {
3198
3876
  type: arrTableItemOutput,
@@ -3228,6 +3906,13 @@ function generateSchemaData2(db, schema, relations, options) {
3228
3906
  resolve: updateGenerated.resolver
3229
3907
  };
3230
3908
  }
3909
+ if (updateSingleGenerated) {
3910
+ mutations[updateSingleGenerated.name] = {
3911
+ type: singleTableItemOutput,
3912
+ args: updateSingleGenerated.args,
3913
+ resolve: updateSingleGenerated.resolver
3914
+ };
3915
+ }
3231
3916
  if (deleteGenerated) {
3232
3917
  mutations[deleteGenerated.name] = {
3233
3918
  type: arrTableItemOutput,
@@ -3235,6 +3920,13 @@ function generateSchemaData2(db, schema, relations, options) {
3235
3920
  resolve: deleteGenerated.resolver
3236
3921
  };
3237
3922
  }
3923
+ if (deleteSingleGenerated) {
3924
+ mutations[deleteSingleGenerated.name] = {
3925
+ type: singleTableItemOutput,
3926
+ args: deleteSingleGenerated.args,
3927
+ resolve: deleteSingleGenerated.resolver
3928
+ };
3929
+ }
3238
3930
  const activeInputs = [
3239
3931
  // The insert input types the upsert mutations too, so either feature keeps it.
3240
3932
  ...features.insert || onConflictInput ? [insertInput] : [],
@@ -3251,6 +3943,10 @@ function generateSchemaData2(db, schema, relations, options) {
3251
3943
  if (aggregateType) {
3252
3944
  outputs[aggregateType.name] = aggregateType;
3253
3945
  }
3946
+ if (groupByType && havingInput) {
3947
+ outputs[groupByType.name] = groupByType;
3948
+ inputs[havingInput.name] = havingInput;
3949
+ }
3254
3950
  }
3255
3951
  const fieldResolvers = {};
3256
3952
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -3273,7 +3969,7 @@ function generateSchemaData2(db, schema, relations, options) {
3273
3969
  import { is as is6, One as One5 } from "drizzle-orm";
3274
3970
  import { getTableConfig as getTableConfig3, SQLiteTable } from "drizzle-orm/sqlite-core";
3275
3971
  import {
3276
- GraphQLError as GraphQLError6,
3972
+ GraphQLError as GraphQLError7,
3277
3973
  GraphQLList as GraphQLList6,
3278
3974
  GraphQLNonNull as GraphQLNonNull6
3279
3975
  } from "graphql";
@@ -3372,7 +4068,7 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
3372
4068
  try {
3373
4069
  const input = remapFromGraphQLArrayInput(args.values, table);
3374
4070
  if (!input.length) {
3375
- throw new GraphQLError6("No values were provided!");
4071
+ throw new GraphQLError7("No values were provided!");
3376
4072
  }
3377
4073
  const parsedInfo = parseResolveInfo4(info, {
3378
4074
  deep: true
@@ -3462,7 +4158,7 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
3462
4158
  try {
3463
4159
  const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
3464
4160
  if (!input.length) {
3465
- throw new GraphQLError6("No values were provided!");
4161
+ throw new GraphQLError7("No values were provided!");
3466
4162
  }
3467
4163
  const parsedInfo = parseResolveInfo4(info, { deep: true });
3468
4164
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -3501,13 +4197,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
3501
4197
  args: queryArgs
3502
4198
  };
3503
4199
  };
3504
- var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
4200
+ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx) => {
3505
4201
  const queryArgs = {
3506
4202
  set: {
3507
4203
  type: new GraphQLNonNull6(setArgs)
3508
4204
  },
3509
4205
  where: {
3510
- type: filterArgs
4206
+ type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
3511
4207
  }
3512
4208
  };
3513
4209
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -3531,18 +4227,28 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
3531
4227
  });
3532
4228
  const input = remapFromGraphQLSingleInput(set, table);
3533
4229
  if (!Object.keys(input).length) {
3534
- throw new GraphQLError6("Unable to update with no values specified!");
4230
+ throw new GraphQLError7("Unable to update with no values specified!");
3535
4231
  }
4232
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
4233
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
3536
4234
  const executor = resolveExecutor(db, context);
4235
+ if (single) {
4236
+ await assertSingleMatch(executor, table, filters, fieldName);
4237
+ }
3537
4238
  let query = executor.update(table).set(input);
3538
- if (where) {
3539
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
4239
+ if (filters) {
3540
4240
  query = query.where(filters);
3541
4241
  }
3542
4242
  query = query.returning(columns);
3543
4243
  const result = await query;
4244
+ if (single && result.length > 1) {
4245
+ throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
4246
+ }
4247
+ if (single && !result[0]) {
4248
+ return void 0;
4249
+ }
3544
4250
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
3545
- return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
4251
+ return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
3546
4252
  } catch (e) {
3547
4253
  throw toGraphQLError(e);
3548
4254
  }
@@ -3550,10 +4256,10 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
3550
4256
  args: queryArgs
3551
4257
  };
3552
4258
  };
3553
- var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
4259
+ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
3554
4260
  const queryArgs = {
3555
4261
  where: {
3556
- type: filterArgs
4262
+ type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
3557
4263
  }
3558
4264
  };
3559
4265
  return {
@@ -3569,14 +4275,24 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, fi
3569
4275
  table,
3570
4276
  selectionCtx
3571
4277
  );
4278
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
4279
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
3572
4280
  const executor = resolveExecutor(db, context);
4281
+ if (single) {
4282
+ await assertSingleMatch(executor, table, filters, fieldName);
4283
+ }
3573
4284
  let query = executor.delete(table);
3574
- if (where) {
3575
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
4285
+ if (filters) {
3576
4286
  query = query.where(filters);
3577
4287
  }
3578
4288
  query = query.returning(columns);
3579
4289
  const result = await query;
4290
+ if (single && result.length > 1) {
4291
+ throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
4292
+ }
4293
+ if (single) {
4294
+ return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
4295
+ }
3580
4296
  return remapToGraphQLArrayOutput(result, tableName, table);
3581
4297
  } catch (e) {
3582
4298
  throw toGraphQLError(e);
@@ -3653,12 +4369,15 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3653
4369
  listFieldName,
3654
4370
  singleFieldName,
3655
4371
  aggregateFieldName,
4372
+ groupByFieldName,
3656
4373
  createArrayFieldName,
3657
4374
  createSingleFieldName,
3658
4375
  upsertArrayFieldName,
3659
4376
  upsertSingleFieldName,
3660
4377
  updateFieldName,
3661
- deleteFieldName
4378
+ updateSingleFieldName,
4379
+ deleteFieldName,
4380
+ deleteSingleFieldName
3662
4381
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
3663
4382
  const selectArrGenerated = generateSelectArray3(
3664
4383
  db,
@@ -3757,6 +4476,23 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3757
4476
  tableFilters,
3758
4477
  updateFieldName,
3759
4478
  typeName,
4479
+ false,
4480
+ features.requireWhere,
4481
+ typeNameMapper,
4482
+ filterCtx
4483
+ ) : void 0;
4484
+ const updateSingleGenerated = features.update ? generateUpdate3(
4485
+ db,
4486
+ tableName,
4487
+ schema[tableName],
4488
+ tables,
4489
+ eagerRelations,
4490
+ updateInput,
4491
+ tableFilters,
4492
+ updateSingleFieldName,
4493
+ typeName,
4494
+ true,
4495
+ features.requireWhere,
3760
4496
  typeNameMapper,
3761
4497
  filterCtx
3762
4498
  ) : void 0;
@@ -3767,6 +4503,20 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3767
4503
  tableFilters,
3768
4504
  deleteFieldName,
3769
4505
  typeName,
4506
+ false,
4507
+ features.requireWhere,
4508
+ filterCtx,
4509
+ { tableName, relationMap: namedRelations, tables }
4510
+ ) : void 0;
4511
+ const deleteSingleGenerated = features.delete ? generateDelete3(
4512
+ db,
4513
+ tableName,
4514
+ schema[tableName],
4515
+ tableFilters,
4516
+ deleteSingleFieldName,
4517
+ typeName,
4518
+ true,
4519
+ features.requireWhere,
3770
4520
  filterCtx,
3771
4521
  { tableName, relationMap: namedRelations, tables }
3772
4522
  ) : void 0;
@@ -3780,6 +4530,20 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3780
4530
  tableFilters,
3781
4531
  filterCtx
3782
4532
  ) : void 0;
4533
+ const groupByType = features.aggregates && features.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
4534
+ const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
4535
+ const havingInput = groupByEnum ? generateHavingInput(schema[tableName], tableName, typeName) : void 0;
4536
+ const groupByGenerated = groupByType && groupByEnum && havingInput ? generateGroupBy(
4537
+ db,
4538
+ tableName,
4539
+ schema[tableName],
4540
+ typeName,
4541
+ groupByFieldName,
4542
+ tableFilters,
4543
+ groupByEnum,
4544
+ havingInput,
4545
+ filterCtx
4546
+ ) : void 0;
3783
4547
  queries[selectArrGenerated.name] = {
3784
4548
  type: selectArrOutput,
3785
4549
  args: selectArrGenerated.args,
@@ -3799,6 +4563,14 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3799
4563
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
3800
4564
  };
3801
4565
  }
4566
+ if (groupByGenerated && groupByType) {
4567
+ queries[groupByGenerated.name] = {
4568
+ type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(groupByType))),
4569
+ args: groupByGenerated.args,
4570
+ resolve: groupByGenerated.resolver,
4571
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
4572
+ };
4573
+ }
3802
4574
  if (insertArrGenerated) {
3803
4575
  mutations[insertArrGenerated.name] = {
3804
4576
  type: arrTableItemOutput,
@@ -3834,6 +4606,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3834
4606
  resolve: updateGenerated.resolver
3835
4607
  };
3836
4608
  }
4609
+ if (updateSingleGenerated) {
4610
+ mutations[updateSingleGenerated.name] = {
4611
+ type: singleTableItemOutput,
4612
+ args: updateSingleGenerated.args,
4613
+ resolve: updateSingleGenerated.resolver
4614
+ };
4615
+ }
3837
4616
  if (deleteGenerated) {
3838
4617
  mutations[deleteGenerated.name] = {
3839
4618
  type: arrTableItemOutput,
@@ -3841,6 +4620,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3841
4620
  resolve: deleteGenerated.resolver
3842
4621
  };
3843
4622
  }
4623
+ if (deleteSingleGenerated) {
4624
+ mutations[deleteSingleGenerated.name] = {
4625
+ type: singleTableItemOutput,
4626
+ args: deleteSingleGenerated.args,
4627
+ resolve: deleteSingleGenerated.resolver
4628
+ };
4629
+ }
3844
4630
  const activeInputs = [
3845
4631
  // The insert input types the upsert mutations too, so either feature keeps it.
3846
4632
  ...features.insert || onConflictInput ? [insertInput] : [],
@@ -3857,6 +4643,10 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3857
4643
  if (aggregateType) {
3858
4644
  outputs[aggregateType.name] = aggregateType;
3859
4645
  }
4646
+ if (groupByType && havingInput) {
4647
+ outputs[groupByType.name] = groupByType;
4648
+ inputs[havingInput.name] = havingInput;
4649
+ }
3860
4650
  }
3861
4651
  const fieldResolvers = {};
3862
4652
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -3899,12 +4689,14 @@ var buildSchema = (db, config) => {
3899
4689
  const typeNameMapper = config?.typeNameMapper;
3900
4690
  const features = {
3901
4691
  aggregates: config?.features?.aggregates ?? true,
4692
+ groupBy: config?.features?.groupBy ?? true,
3902
4693
  relationAggregates: config?.features?.relationAggregates ?? true,
3903
4694
  distinct: config?.features?.distinct ?? true,
3904
4695
  insert: config?.features?.insert ?? true,
3905
4696
  update: config?.features?.update ?? true,
3906
4697
  delete: config?.features?.delete ?? true,
3907
- upsert: config?.features?.upsert ?? false
4698
+ upsert: config?.features?.upsert ?? false,
4699
+ requireWhere: config?.features?.requireWhere ?? false
3908
4700
  };
3909
4701
  const complexityConfig = config?.complexity ?? true;
3910
4702
  const complexity = complexityConfig === false ? void 0 : {
@@ -3977,6 +4769,7 @@ export {
3977
4769
  GraphQLBigIntString,
3978
4770
  GraphQLDate,
3979
4771
  GraphQLDateTime,
4772
+ GraphQLDecimalString,
3980
4773
  GraphQLJSON,
3981
4774
  GraphQLUUID,
3982
4775
  buildSchema,