@vantreeseba/drizzle-graphql 4.2.0 → 5.1.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,11 +806,15 @@ 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
  });
755
- var resolveGenericFilterName = (column, columnName, columnGraphQLType) => {
756
- if (columnName === "id" || columnName.endsWith("Id")) {
816
+ var resolveGenericFilterName = (column, columnGraphQLType) => {
817
+ if (columnGraphQLType.type === GraphQLUUID) {
757
818
  return "Id";
758
819
  }
759
820
  if (columnGraphQLType.type === GraphQLBoolean2) {
@@ -762,27 +823,50 @@ 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") {
771
848
  return "DateTime";
772
849
  }
850
+ if (columnGraphQLType.type === GraphQLInt2) {
851
+ return "Int";
852
+ }
853
+ if (columnGraphQLType.type === GraphQLFloat2) {
854
+ return "Float";
855
+ }
773
856
  return "String";
774
857
  };
858
+ var FILTERS_WITHOUT_STRING_OPS = /* @__PURE__ */ new Set(["Id", "Int", "Float", "BigInt", "Decimal"]);
775
859
  var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
776
860
  const columnGraphQLType = drizzleColumnToGraphQLType(column, columnName, tableName, true, false, true);
777
- const genericName = resolveGenericFilterName(column, columnName, columnGraphQLType);
861
+ const genericName = resolveGenericFilterName(column, columnGraphQLType);
778
862
  const cached = cacheCtx.genericFilterCache.get(genericName);
779
863
  if (cached) {
780
- return cached.main;
864
+ return cached;
781
865
  }
782
866
  const colType = columnGraphQLType.type;
783
867
  const colDesc = columnGraphQLType.description;
784
868
  const colArr = new GraphQLList2(new GraphQLNonNull2(colType));
785
- const isId = genericName === "Id";
869
+ const omitStringOps = FILTERS_WITHOUT_STRING_OPS.has(genericName);
786
870
  const baseFields = {
787
871
  eq: { type: colType, description: colDesc },
788
872
  ne: { type: colType, description: colDesc },
@@ -790,31 +874,60 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
790
874
  lte: { type: colType, description: colDesc },
791
875
  gt: { type: colType, description: colDesc },
792
876
  gte: { type: colType, description: colDesc },
793
- ...isId ? {} : {
877
+ ...omitStringOps ? {} : {
794
878
  like: { type: GraphQLString2 },
795
879
  notLike: { type: GraphQLString2 },
796
880
  ilike: { type: GraphQLString2 },
797
- notIlike: { type: GraphQLString2 }
881
+ notIlike: { type: GraphQLString2 },
882
+ startsWith: {
883
+ type: GraphQLString2,
884
+ description: "Matches values starting with the given string. `%`, `_` and `\\` are matched literally."
885
+ },
886
+ endsWith: {
887
+ type: GraphQLString2,
888
+ description: "Matches values ending with the given string. `%`, `_` and `\\` are matched literally."
889
+ },
890
+ contains: {
891
+ type: GraphQLString2,
892
+ description: "Matches values containing the given string. `%`, `_` and `\\` are matched literally."
893
+ },
894
+ iStartsWith: {
895
+ type: GraphQLString2,
896
+ description: "Case-insensitive `startsWith`."
897
+ },
898
+ iEndsWith: {
899
+ type: GraphQLString2,
900
+ description: "Case-insensitive `endsWith`."
901
+ },
902
+ iContains: {
903
+ type: GraphQLString2,
904
+ description: "Case-insensitive `contains`."
905
+ }
798
906
  },
799
907
  inArray: { type: colArr, description: `Array<${colDesc}>` },
800
908
  notInArray: { type: colArr, description: `Array<${colDesc}>` },
801
909
  isNull: { type: GraphQLBoolean2 },
802
910
  isNotNull: { type: GraphQLBoolean2 }
803
911
  };
804
- const orType = new GraphQLInputObjectType2({
805
- name: `${genericName}FilterOr`,
806
- fields: { ...baseFields }
807
- });
808
912
  const mainType = new GraphQLInputObjectType2({
809
913
  name: `${genericName}Filter`,
810
- fields: {
914
+ fields: () => ({
811
915
  ...baseFields,
812
916
  OR: {
813
- type: new GraphQLList2(new GraphQLNonNull2(orType))
917
+ type: new GraphQLList2(new GraphQLNonNull2(mainType)),
918
+ description: "At least one branch matches; ANDed with any sibling operators"
919
+ },
920
+ AND: {
921
+ type: new GraphQLList2(new GraphQLNonNull2(mainType)),
922
+ description: "Every branch matches"
923
+ },
924
+ NOT: {
925
+ type: mainType,
926
+ description: "Negates the nested operators"
814
927
  }
815
- }
928
+ })
816
929
  });
817
- cacheCtx.genericFilterCache.set(genericName, { main: mainType, or: orType });
930
+ cacheCtx.genericFilterCache.set(genericName, mainType);
818
931
  return mainType;
819
932
  };
820
933
  var orderMap = /* @__PURE__ */ new WeakMap();
@@ -868,19 +981,53 @@ var generateTableSelectTypeFieldsCached = (table, tableName) => {
868
981
  fieldMap.set(table, remapped);
869
982
  return remapped;
870
983
  };
871
- var generateTableOrderTypeCached = (table, tableName, typeNameMapper, cacheCtx) => {
984
+ var isFilterableRelation = (relation) => !relation.through;
985
+ var generateRelationOrderFields = (tableName, cacheCtx, typeNameMapper, columnFields, relationMap, tables) => {
986
+ const relations = relationMap?.[tableName];
987
+ if (!relations || !tables) {
988
+ return {};
989
+ }
990
+ const fields = {};
991
+ for (const [relationName, relEntry] of Object.entries(relations)) {
992
+ if (relationName in columnFields) {
993
+ continue;
994
+ }
995
+ const targetTable = tables[relEntry.targetTableName];
996
+ const relation = relEntry.relation ?? relEntry;
997
+ if (!targetTable || !is3(relation, One2) || !isFilterableRelation(relation)) {
998
+ continue;
999
+ }
1000
+ fields[relationName] = {
1001
+ type: generateTableOrderTypeCached(
1002
+ targetTable,
1003
+ relEntry.targetTableName,
1004
+ typeNameMapper,
1005
+ cacheCtx,
1006
+ relationMap,
1007
+ tables
1008
+ ),
1009
+ description: `Order by columns of the related ${relationName} row`
1010
+ };
1011
+ }
1012
+ return fields;
1013
+ };
1014
+ var generateTableOrderTypeCached = (table, tableName, typeNameMapper, cacheCtx, relationMap, tables) => {
872
1015
  if (cacheCtx.orderTypeCache.has(table)) {
873
1016
  return cacheCtx.orderTypeCache.get(table);
874
1017
  }
875
- const orderColumns = generateTableOrderCached(table);
876
1018
  const order = new GraphQLInputObjectType2({
877
1019
  name: `${resolveTypeName(tableName, typeNameMapper)}OrderBy`,
878
- fields: orderColumns
1020
+ fields: () => {
1021
+ const orderColumns = generateTableOrderCached(table);
1022
+ return {
1023
+ ...orderColumns,
1024
+ ...generateRelationOrderFields(tableName, cacheCtx, typeNameMapper, orderColumns, relationMap, tables)
1025
+ };
1026
+ }
879
1027
  });
880
1028
  cacheCtx.orderTypeCache.set(table, order);
881
1029
  return order;
882
1030
  };
883
- var isFilterableRelation = (relation) => !relation.through;
884
1031
  var generateListRelationFilterCached = (targetTable, targetTableName, cacheCtx, typeNameMapper, relationMap, tables) => {
885
1032
  const cached = cacheCtx.listRelationFilterCache.get(targetTableName);
886
1033
  if (cached) {
@@ -919,7 +1066,7 @@ var generateRelationFilterFields = (tableName, cacheCtx, typeNameMapper, columnF
919
1066
  }
920
1067
  const targetTable = tables[relEntry.targetTableName];
921
1068
  const relation = relEntry.relation ?? relEntry;
922
- if (!targetTable || !isFilterableRelation(relation)) {
1069
+ if (!targetTable) {
923
1070
  continue;
924
1071
  }
925
1072
  fields[relationName] = is3(relation, One2) ? {
@@ -956,16 +1103,21 @@ var generateTableFilterTypeCached = (table, tableName, cacheCtx, typeNameMapper,
956
1103
  ...generateRelationFilterFields(tableName, cacheCtx, typeNameMapper, filterColumns, relationMap, tables)
957
1104
  };
958
1105
  };
959
- const orFilters = new GraphQLInputObjectType2({
960
- name: `${resolveTypeName(tableName, typeNameMapper)}FiltersOr`,
961
- fields: buildFields
962
- });
963
1106
  const filters = new GraphQLInputObjectType2({
964
1107
  name: `${resolveTypeName(tableName, typeNameMapper)}Filters`,
965
1108
  fields: () => ({
966
1109
  ...buildFields(),
967
1110
  OR: {
968
- type: new GraphQLList2(new GraphQLNonNull2(orFilters))
1111
+ type: new GraphQLList2(new GraphQLNonNull2(filters)),
1112
+ description: "At least one branch matches; ANDed with any sibling fields"
1113
+ },
1114
+ AND: {
1115
+ type: new GraphQLList2(new GraphQLNonNull2(filters)),
1116
+ description: "Every branch matches"
1117
+ },
1118
+ NOT: {
1119
+ type: filters,
1120
+ description: "Negates the nested filters"
969
1121
  }
970
1122
  })
971
1123
  });
@@ -974,7 +1126,7 @@ var generateTableFilterTypeCached = (table, tableName, cacheCtx, typeNameMapper,
974
1126
  };
975
1127
  var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromRelationName, withOrder, relationsDepthLimit, cacheCtx, typeNameMapper, usedTables = /* @__PURE__ */ new Set(), resolverFactory, currentDepth = 0, relationAggregateFactory) => {
976
1128
  const table = tables[tableName];
977
- const order = withOrder ? generateTableOrderTypeCached(table, tableName, typeNameMapper, cacheCtx) : void 0;
1129
+ const order = withOrder ? generateTableOrderTypeCached(table, tableName, typeNameMapper, cacheCtx, relationMap, tables) : void 0;
978
1130
  const filters = generateTableFilterTypeCached(table, tableName, cacheCtx, typeNameMapper, relationMap, tables);
979
1131
  const tableFields = generateTableSelectTypeFieldsCached(table, tableName);
980
1132
  const relationsForTable = relationMap[tableName];
@@ -1060,10 +1212,11 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1060
1212
  }
1061
1213
  const resolve = resolverFactory?.({ tableName, relationName, relEntry, isOne });
1062
1214
  if (isOne) {
1215
+ const isRequired = relation.optional === false;
1063
1216
  rawRelationFields.push([
1064
1217
  relationName,
1065
1218
  {
1066
- type: relType,
1219
+ type: isRequired ? new GraphQLNonNull2(relType) : relType,
1067
1220
  args: {
1068
1221
  where: { type: relSelectData.filters }
1069
1222
  },
@@ -1201,28 +1354,95 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
1201
1354
  outputs
1202
1355
  };
1203
1356
  };
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;
1357
+ var orderByEntries = (orderArgs) => Object.entries(orderArgs).sort((a, b) => (b[1]?.priority ?? 0) - (a[1]?.priority ?? 0)).filter(([, config]) => config).map(([column, config]) => {
1358
+ if (typeof config === "object" && config.direction === void 0) {
1359
+ throw new GraphQLError3(`ORDER BY ${column}: ordering through a relation is not supported in this query`);
1360
+ }
1361
+ return [column, config.direction, config.nulls ?? void 0];
1362
+ });
1363
+ var orderExpressions = (expr, direction, nulls, dialectColumn) => {
1364
+ const directed = direction === "asc" ? asc(expr) : desc(expr);
1365
+ if (!nulls) {
1366
+ return [directed];
1367
+ }
1368
+ const isMySql = (dialectColumn.columnType ?? "").startsWith("MySql");
1369
+ if (isMySql) {
1370
+ const nullsKey = nulls === "first" ? desc(sql`(${expr} is null)`) : asc(sql`(${expr} is null)`);
1371
+ return [nullsKey, directed];
1211
1372
  }
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!`);
1373
+ return [nulls === "first" ? sql`${directed} nulls first` : sql`${directed} nulls last`];
1374
+ };
1375
+ var extendRelationOrderChain = (parentTable, relationName, relEntry, ctx, chain) => {
1376
+ const targetTable = ctx.tables[relEntry.targetTableName];
1377
+ const relation = relEntry.relation ?? relEntry;
1378
+ if (!targetTable || !is3(relation, One2) || !isFilterableRelation(relation)) {
1379
+ throw new GraphQLError3(`ORDER BY ${relationName}: Relation cannot be used for ordering`);
1380
+ }
1381
+ ctx.aliases ??= { n: 0 };
1382
+ const aliasedTarget = aliasedTable(targetTable, `dgql_ord_${ctx.aliases.n++}`);
1383
+ const joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
1384
+ const relationWhere = relation.where ? relationsFilterToSQL(relation.isReversed ? parentTable : aliasedTarget, relation.where) : void 0;
1385
+ return {
1386
+ fromParts: [...chain?.fromParts ?? [], getTableAsAliasSQL(aliasedTarget)],
1387
+ conditions: [
1388
+ ...chain?.conditions ?? [],
1389
+ ...joinCondition ? [joinCondition] : [],
1390
+ ...relationWhere ? [relationWhere] : []
1391
+ ],
1392
+ table: aliasedTarget
1393
+ };
1394
+ };
1395
+ var collectOrderEntries = (table, tableKey, orderArgs, ctx, chain, out) => {
1396
+ const columns = getColumns(table);
1397
+ const relations = ctx?.relationMap[tableKey];
1398
+ for (const [key, config] of Object.entries(orderArgs)) {
1399
+ if (config === null || config === void 0) {
1400
+ continue;
1216
1401
  }
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
- }
1402
+ const column = columns[key];
1403
+ if (column) {
1404
+ out.push({
1405
+ expression: chain ? sql`(select ${column} from ${sql.join(chain.fromParts, sql`, `)} where ${and(...chain.conditions)})` : column,
1406
+ column,
1407
+ direction: config.direction,
1408
+ nulls: config.nulls ?? void 0,
1409
+ priority: config.priority ?? 0
1410
+ });
1411
+ continue;
1412
+ }
1413
+ const relEntry = relations?.[key];
1414
+ if (!relEntry || !ctx) {
1415
+ throw new GraphQLError3(`ORDER BY ${key}: Unknown column or relation`);
1223
1416
  }
1224
- return variants2.length ? variants2.length > 1 ? or(...variants2) : variants2[0] : void 0;
1417
+ const nextChain = extendRelationOrderChain(chain?.table ?? table, key, relEntry, ctx, chain);
1418
+ collectOrderEntries(nextChain.table, relEntry.targetTableName, config, ctx, nextChain, out);
1419
+ }
1420
+ };
1421
+ var extractOrderBy = (table, orderArgs, ctx) => {
1422
+ const entries = [];
1423
+ collectOrderEntries(table, ctx?.tableKey ?? "", orderArgs, ctx, void 0, entries);
1424
+ return entries.sort((a, b) => b.priority - a.priority).flatMap((entry) => orderExpressions(entry.expression, entry.direction, entry.nulls, entry.column));
1425
+ };
1426
+ var LIKE_ESCAPE_CHAR = "\\";
1427
+ var escapeLikeValue = (value) => value.replace(/[\\%_]/g, (char) => `\\${char}`);
1428
+ var safeLikeOps = {
1429
+ startsWith: { buildPattern: (value) => `${escapeLikeValue(value)}%`, insensitive: false },
1430
+ endsWith: { buildPattern: (value) => `%${escapeLikeValue(value)}`, insensitive: false },
1431
+ contains: { buildPattern: (value) => `%${escapeLikeValue(value)}%`, insensitive: false },
1432
+ iStartsWith: { buildPattern: (value) => `${escapeLikeValue(value)}%`, insensitive: true },
1433
+ iEndsWith: { buildPattern: (value) => `%${escapeLikeValue(value)}`, insensitive: true },
1434
+ iContains: { buildPattern: (value) => `%${escapeLikeValue(value)}%`, insensitive: true }
1435
+ };
1436
+ var safeLikeCondition = (column, pattern, insensitive) => {
1437
+ if (!insensitive) {
1438
+ return sql`${column} like ${pattern} escape ${LIKE_ESCAPE_CHAR}`;
1225
1439
  }
1440
+ const isPg = (column.columnType ?? "").startsWith("Pg");
1441
+ return isPg ? sql`${column} ilike ${pattern} escape ${LIKE_ESCAPE_CHAR}` : sql`lower(${column}) like ${pattern.toLowerCase()} escape ${LIKE_ESCAPE_CHAR}`;
1442
+ };
1443
+ var extractFiltersColumn = (column, columnName, operators) => {
1444
+ const { OR, AND, NOT, ...restOperators } = operators;
1445
+ const entries = Object.entries(restOperators);
1226
1446
  const singleValueOps = { eq, ne, gt, gte, lt, lte };
1227
1447
  const stringValueOps = { like, notLike, ilike, notIlike };
1228
1448
  const arrayValueOps = { inArray, notInArray };
@@ -1237,6 +1457,9 @@ var extractFiltersColumn = (column, columnName, operators) => {
1237
1457
  variants.push(singleValueOps[operatorName](column, singleValue));
1238
1458
  } else if (operatorName in stringValueOps) {
1239
1459
  variants.push(stringValueOps[operatorName](column, operatorValue));
1460
+ } else if (operatorName in safeLikeOps) {
1461
+ const { buildPattern, insensitive } = safeLikeOps[operatorName];
1462
+ variants.push(safeLikeCondition(column, buildPattern(operatorValue), insensitive));
1240
1463
  } else if (operatorName in arrayValueOps) {
1241
1464
  if (!operatorValue.length) {
1242
1465
  throw new GraphQLError3(`WHERE ${columnName}: Unable to use operator ${operatorName} with an empty array!`);
@@ -1245,6 +1468,34 @@ var extractFiltersColumn = (column, columnName, operators) => {
1245
1468
  variants.push(arrayValueOps[operatorName](column, arrayValue));
1246
1469
  } else if (operatorName in nullableOps) {
1247
1470
  variants.push(nullableOps[operatorName](column));
1471
+ } else {
1472
+ throw new GraphQLError3(`WHERE ${columnName}: Unknown operator: ${operatorName}`);
1473
+ }
1474
+ }
1475
+ if (AND?.length) {
1476
+ for (const variant of AND) {
1477
+ const extracted = extractFiltersColumn(column, columnName, variant);
1478
+ if (extracted) {
1479
+ variants.push(extracted);
1480
+ }
1481
+ }
1482
+ }
1483
+ if (NOT) {
1484
+ const extracted = extractFiltersColumn(column, columnName, NOT);
1485
+ if (extracted) {
1486
+ variants.push(not(extracted));
1487
+ }
1488
+ }
1489
+ if (OR?.length) {
1490
+ const orVariants = [];
1491
+ for (const variant of OR) {
1492
+ const extracted = extractFiltersColumn(column, columnName, variant);
1493
+ if (extracted) {
1494
+ orVariants.push(extracted);
1495
+ }
1496
+ }
1497
+ if (orVariants.length) {
1498
+ variants.push(orVariants.length > 1 ? or(...orVariants) : orVariants[0]);
1248
1499
  }
1249
1500
  }
1250
1501
  return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
@@ -1269,39 +1520,105 @@ var buildRelationJoinCondition = (parentTable, relation, aliasedTarget, relation
1269
1520
  }
1270
1521
  return conditions.length > 1 ? and(...conditions) : conditions[0];
1271
1522
  };
1523
+ var resolveJunctionColumn = (aliasedThrough, junctionRef, relationName) => {
1524
+ const throughColumns = getColumns(aliasedThrough);
1525
+ const key = junctionRef?._?.key;
1526
+ const byKey = key ? throughColumns[key] : void 0;
1527
+ if (byKey) {
1528
+ return byKey;
1529
+ }
1530
+ const columnName = junctionRef?._?.column?.name;
1531
+ const byName = columnName ? Object.values(throughColumns).find((c) => c.name === columnName) : void 0;
1532
+ if (!byName) {
1533
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1534
+ }
1535
+ return byName;
1536
+ };
1537
+ var buildThroughJoinConditions = (parentTable, relation, aliasedThrough, aliasedTarget, relationName) => {
1538
+ const sourceColumns = relation.sourceColumns;
1539
+ const targetColumns = relation.targetColumns;
1540
+ const through = relation.through;
1541
+ if (!sourceColumns?.length || !targetColumns?.length || through?.source.length !== sourceColumns.length || through.target.length !== targetColumns.length) {
1542
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1543
+ }
1544
+ const parentColumns = Object.values(getColumns(parentTable));
1545
+ const targetTableColumns = Object.values(getColumns(aliasedTarget));
1546
+ const correlationConditions = [];
1547
+ for (let i = 0; i < sourceColumns.length; i++) {
1548
+ const localColumn = parentColumns.find((c) => c.name === sourceColumns[i].name);
1549
+ if (!localColumn) {
1550
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1551
+ }
1552
+ correlationConditions.push(eq(localColumn, resolveJunctionColumn(aliasedThrough, through.source[i], relationName)));
1553
+ }
1554
+ const junctionJoinConditions = [];
1555
+ for (let i = 0; i < targetColumns.length; i++) {
1556
+ const foreignColumn = targetTableColumns.find((c) => c.name === targetColumns[i].name);
1557
+ if (!foreignColumn) {
1558
+ throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1559
+ }
1560
+ junctionJoinConditions.push(
1561
+ eq(resolveJunctionColumn(aliasedThrough, through.target[i], relationName), foreignColumn)
1562
+ );
1563
+ }
1564
+ return {
1565
+ correlation: correlationConditions.length > 1 ? and(...correlationConditions) : correlationConditions[0],
1566
+ junctionJoin: junctionJoinConditions.length > 1 ? and(...junctionJoinConditions) : junctionJoinConditions[0]
1567
+ };
1568
+ };
1272
1569
  var buildRelationExists = (parentTable, relationName, relEntry, innerFilters, mode, ctx) => {
1273
1570
  const { targetTableName } = relEntry;
1274
1571
  const targetTable = ctx.tables[targetTableName];
1275
1572
  const relation = relEntry.relation ?? relEntry;
1276
- if (!targetTable || !isFilterableRelation(relation)) {
1573
+ if (!targetTable) {
1277
1574
  throw new GraphQLError3(`WHERE ${relationName}: Relation cannot be used as a filter`);
1278
1575
  }
1279
1576
  ctx.aliases ??= { n: 0 };
1280
1577
  const aliases = ctx.aliases;
1281
1578
  const aliasedTarget = aliasedTable(targetTable, `dgql_rel_${aliases.n++}`);
1282
- const joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
1579
+ const throughTable = relation.throughTable;
1580
+ let fromClause;
1581
+ let joinCondition;
1582
+ if (throughTable) {
1583
+ const aliasedThrough = aliasedTable(throughTable, `dgql_rel_${aliases.n++}`);
1584
+ const { correlation, junctionJoin } = buildThroughJoinConditions(
1585
+ parentTable,
1586
+ relation,
1587
+ aliasedThrough,
1588
+ aliasedTarget,
1589
+ relationName
1590
+ );
1591
+ fromClause = sql`${getTableAsAliasSQL(aliasedTarget)} inner join ${getTableAsAliasSQL(aliasedThrough)} on ${junctionJoin}`;
1592
+ joinCondition = correlation;
1593
+ } else {
1594
+ fromClause = getTableAsAliasSQL(aliasedTarget);
1595
+ joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
1596
+ }
1283
1597
  const relationWhere = relation.where ? relationsFilterToSQL(relation.isReversed ? parentTable : aliasedTarget, relation.where) : void 0;
1284
1598
  const inner = innerFilters ? extractFilters(aliasedTarget, targetTableName, innerFilters, { ...ctx, tableKey: targetTableName, aliases }) : void 0;
1285
1599
  if (mode === "every") {
1286
1600
  if (!inner) {
1287
1601
  return void 0;
1288
1602
  }
1289
- return sql`not exists (select 1 from ${getTableAsAliasSQL(aliasedTarget)} where ${and(joinCondition, relationWhere, not(inner))})`;
1603
+ return sql`not exists (select 1 from ${fromClause} where ${and(joinCondition, relationWhere, not(inner))})`;
1290
1604
  }
1291
1605
  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})`;
1606
+ return mode === "none" ? sql`not exists (select 1 from ${fromClause} where ${condition})` : sql`exists (select 1 from ${fromClause} where ${condition})`;
1293
1607
  };
1294
1608
  var extractRelationFilter = (parentTable, relationName, relEntry, value, ctx) => {
1295
1609
  const relation = relEntry.relation ?? relEntry;
1296
1610
  if (is3(relation, One2)) {
1297
1611
  return buildRelationExists(parentTable, relationName, relEntry, value, "some", ctx);
1298
1612
  }
1613
+ const relationMatchModes = ["some", "none", "every"];
1299
1614
  const variants = [];
1300
- for (const mode of ["some", "none", "every"]) {
1301
- const inner = value[mode];
1615
+ for (const [mode, inner] of Object.entries(value)) {
1302
1616
  if (inner === void 0 || inner === null) {
1303
1617
  continue;
1304
1618
  }
1619
+ if (!relationMatchModes.includes(mode)) {
1620
+ throw new GraphQLError3(`WHERE ${relationName}: Unknown relation filter key: ${mode}`);
1621
+ }
1305
1622
  const extracted = buildRelationExists(parentTable, relationName, relEntry, inner, mode, ctx);
1306
1623
  if (extracted) {
1307
1624
  variants.push(extracted);
@@ -1310,26 +1627,8 @@ var extractRelationFilter = (parentTable, relationName, relEntry, value, ctx) =>
1310
1627
  return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
1311
1628
  };
1312
1629
  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
- }
1630
+ const { OR, AND, NOT, ...fieldFilters } = filters;
1631
+ const entries = Object.entries(fieldFilters);
1333
1632
  const columns = getColumns(table);
1334
1633
  const relations = relationCtx?.relationMap[relationCtx.tableKey];
1335
1634
  const variants = [];
@@ -1338,11 +1637,40 @@ var extractFilters = (table, tableName, filters, relationCtx) => {
1338
1637
  continue;
1339
1638
  }
1340
1639
  const column = columns[fieldName];
1341
- const extracted = column ? extractFiltersColumn(column, fieldName, operators) : relations?.[fieldName] && relationCtx ? extractRelationFilter(table, fieldName, relations[fieldName], operators, relationCtx) : void 0;
1640
+ if (!column && !(relations?.[fieldName] && relationCtx)) {
1641
+ throw new GraphQLError3(`WHERE ${tableName}: Unknown filter key: ${fieldName}`);
1642
+ }
1643
+ const extracted = column ? extractFiltersColumn(column, fieldName, operators) : extractRelationFilter(table, fieldName, relations[fieldName], operators, relationCtx);
1342
1644
  if (extracted) {
1343
1645
  variants.push(extracted);
1344
1646
  }
1345
1647
  }
1648
+ if (AND?.length) {
1649
+ for (const variant of AND) {
1650
+ const extracted = extractFilters(table, tableName, variant, relationCtx);
1651
+ if (extracted) {
1652
+ variants.push(extracted);
1653
+ }
1654
+ }
1655
+ }
1656
+ if (NOT) {
1657
+ const extracted = extractFilters(table, tableName, NOT, relationCtx);
1658
+ if (extracted) {
1659
+ variants.push(not(extracted));
1660
+ }
1661
+ }
1662
+ if (OR?.length) {
1663
+ const orVariants = [];
1664
+ for (const variant of OR) {
1665
+ const extracted = extractFilters(table, tableName, variant, relationCtx);
1666
+ if (extracted) {
1667
+ orVariants.push(extracted);
1668
+ }
1669
+ }
1670
+ if (orVariants.length) {
1671
+ variants.push(orVariants.length > 1 ? or(...orVariants) : orVariants[0]);
1672
+ }
1673
+ }
1346
1674
  return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
1347
1675
  };
1348
1676
  var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, originField, typeNameMapper, _isInitial = false, filterCtx) => {
@@ -1384,7 +1712,7 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
1384
1712
  } : void 0;
1385
1713
  const hasPagination = offset != null || limit != null;
1386
1714
  const pkNames = targetPkNames ?? [];
1387
- thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, relationArgs.orderBy) : hasPagination && pkNames.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0;
1715
+ thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, relationArgs.orderBy, relationFilterCtx(filterCtx, targetTableName)) : hasPagination && pkNames.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0;
1388
1716
  thisRecord.offset = offset;
1389
1717
  thisRecord.limit = limit;
1390
1718
  const relWith = relationField ? extractRelationsParamsInner(
@@ -1625,7 +1953,9 @@ var selectDistinctKeys = async (params) => {
1625
1953
  }
1626
1954
  const orderEntries = orderBy ? orderByEntries(orderBy) : [];
1627
1955
  const windowOrder = [
1628
- ...orderEntries.map(([column, direction]) => direction === "asc" ? asc(cols[column]) : desc(cols[column])),
1956
+ ...orderEntries.flatMap(
1957
+ ([column, direction, nulls]) => orderExpressions(cols[column], direction, nulls, cols[column])
1958
+ ),
1629
1959
  ...primaryKeyOrderExprs(table, pkNames)
1630
1960
  ];
1631
1961
  const rowNumber = sql`row_number() over (partition by ${sql.join(partitionCols, sql`, `)} order by ${sql.join(
@@ -1634,7 +1964,9 @@ var selectDistinctKeys = async (params) => {
1634
1964
  )})`.as(DISTINCT_RN);
1635
1965
  const sub = db.select({ ...cols, [DISTINCT_RN]: rowNumber }).from(table).where(where).as("__dgql_distinct");
1636
1966
  const outerOrder = [
1637
- ...orderEntries.map(([column, direction]) => direction === "asc" ? asc(sub[column]) : desc(sub[column])),
1967
+ ...orderEntries.flatMap(
1968
+ ([column, direction, nulls]) => orderExpressions(sub[column], direction, nulls, cols[column])
1969
+ ),
1638
1970
  ...pkNames.filter((name) => sub[name]).map((name) => asc(sub[name]))
1639
1971
  ];
1640
1972
  let query = db.select(Object.fromEntries(pkNames.map((name) => [name, sub[name]]))).from(sub).where(eq(sub[DISTINCT_RN], 1)).orderBy(...outerOrder);
@@ -1733,6 +2065,9 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
1733
2065
  const upsertSingleFieldName = mapped ? `${upsertPrefix}${capitalize(mapped.singular)}` : `${upsertPrefix}${capitalize(tableName)}${suffixes.single}`;
1734
2066
  const updateFieldName = `${prefixes.update}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
1735
2067
  const deleteFieldName = `${prefixes.delete}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
2068
+ const writeSingleSuffix = suffixes.single === "" ? "Single" : suffixes.single;
2069
+ const updateSingleFieldName = `${updateFieldName}${writeSingleSuffix}`;
2070
+ const deleteSingleFieldName = `${deleteFieldName}${writeSingleSuffix}`;
1736
2071
  return {
1737
2072
  typeName,
1738
2073
  listFieldName,
@@ -1744,9 +2079,24 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
1744
2079
  upsertArrayFieldName,
1745
2080
  upsertSingleFieldName,
1746
2081
  updateFieldName,
1747
- deleteFieldName
2082
+ updateSingleFieldName,
2083
+ deleteFieldName,
2084
+ deleteSingleFieldName
1748
2085
  };
1749
2086
  };
2087
+ var extractRequiredFilters = (table, tableName, where, fieldName, relationCtx) => {
2088
+ const filters = where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2089
+ if (!filters) {
2090
+ throw new GraphQLError3(`${fieldName} requires a 'where' argument with at least one filter!`);
2091
+ }
2092
+ return filters;
2093
+ };
2094
+ var assertSingleMatch = async (executor, table, filters, fieldName) => {
2095
+ const matched = await executor.select({ found: sql`1` }).from(table).where(filters).limit(2);
2096
+ if (matched.length > 1) {
2097
+ throw new GraphQLError3(`${fieldName}: 'where' matched more than one row \u2014 nothing was written!`);
2098
+ }
2099
+ };
1750
2100
  var selectArrayArgs = (orderArgs, filterArgs, distinctEnum) => ({
1751
2101
  offset: { type: GraphQLInt2 },
1752
2102
  limit: { type: GraphQLInt2 },
@@ -1805,9 +2155,9 @@ var runRelationalSelect = async (opts) => {
1805
2155
  // drizzle-orm v1 RQB calls orderBy/where with the aliased table proxy — use it
1806
2156
  // directly so column refs match the CTE alias.
1807
2157
  orderBy: distinctKeys ? (aliasedTable2) => [
1808
- ...orderBy ? extractOrderBy(aliasedTable2, orderBy) : [],
2158
+ ...orderBy ? extractOrderBy(aliasedTable2, orderBy, relationFilterCtx(filterCtx, tableName)) : [],
1809
2159
  ...primaryKeyOrderExprs(aliasedTable2, pkNames)
1810
- ] : orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, orderBy) : needsDefaultOrder && pkNames?.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0,
2160
+ ] : orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, orderBy, relationFilterCtx(filterCtx, tableName)) : needsDefaultOrder && pkNames?.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0,
1811
2161
  where: distinctKeys ? { RAW: (aliasedTable2) => primaryKeyRestriction(aliasedTable2, pkNames, distinctKeys) } : where ? {
1812
2162
  RAW: (aliasedTable2) => extractFilters(aliasedTable2, tableName, where, relationFilterCtx(filterCtx, tableName))
1813
2163
  } : void 0,
@@ -1922,7 +2272,7 @@ import {
1922
2272
  } from "drizzle-orm";
1923
2273
  import {
1924
2274
  GraphQLError as GraphQLError4,
1925
- GraphQLFloat as GraphQLFloat2,
2275
+ GraphQLFloat as GraphQLFloat3,
1926
2276
  GraphQLInputObjectType as GraphQLInputObjectType3,
1927
2277
  GraphQLInt as GraphQLInt3,
1928
2278
  GraphQLList as GraphQLList3,
@@ -1980,7 +2330,7 @@ var generateAggregateTypes = (table, tableName, typeName, cacheCtx) => {
1980
2330
  fields[op] = {
1981
2331
  type: new GraphQLObjectType3({
1982
2332
  name: `${typeName}${capitalize(op)}Aggregate`,
1983
- fields: Object.fromEntries(Object.keys(numeric).map((columnName) => [columnName, { type: GraphQLFloat2 }]))
2333
+ fields: Object.fromEntries(Object.keys(numeric).map((columnName) => [columnName, { type: GraphQLFloat3 }]))
1984
2334
  })
1985
2335
  };
1986
2336
  }
@@ -2216,7 +2566,7 @@ var generateGroupByEnum = (table, tableName, typeName) => {
2216
2566
  var aggregateNumberFilter = new GraphQLInputObjectType3({
2217
2567
  name: "AggregateNumberFilter",
2218
2568
  description: "Compares an aggregated value. Several operators in one filter are ANDed together.",
2219
- fields: Object.fromEntries(Object.keys(HAVING_OPS).map((op) => [op, { type: GraphQLFloat2 }]))
2569
+ fields: Object.fromEntries(Object.keys(HAVING_OPS).map((op) => [op, { type: GraphQLFloat3 }]))
2220
2570
  });
2221
2571
  var generateHavingInput = (table, tableName, typeName) => {
2222
2572
  const { numeric, orderable, all } = classifyAggregateColumns(table, tableName);
@@ -2529,13 +2879,13 @@ var generateUpsert = (db, table, baseType, onConflictType, fieldName, single) =>
2529
2879
  args: queryArgs
2530
2880
  };
2531
2881
  };
2532
- var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filterCtx) => {
2882
+ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, single, requireWhere, filterCtx) => {
2533
2883
  const queryArgs = {
2534
2884
  set: {
2535
2885
  type: new GraphQLNonNull4(setArgs)
2536
2886
  },
2537
2887
  where: {
2538
- type: filterArgs
2888
+ type: single || requireWhere ? new GraphQLNonNull4(filterArgs) : filterArgs
2539
2889
  }
2540
2890
  };
2541
2891
  return {
@@ -2547,10 +2897,14 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
2547
2897
  if (!Object.keys(input).length) {
2548
2898
  throw new GraphQLError5("Unable to update with no values specified!");
2549
2899
  }
2900
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
2901
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2550
2902
  const executor = resolveExecutor(db, context);
2903
+ if (single) {
2904
+ await assertSingleMatch(executor, table, filters, fieldName);
2905
+ }
2551
2906
  let query = executor.update(table).set(input);
2552
- if (where) {
2553
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
2907
+ if (filters) {
2554
2908
  query = query.where(filters);
2555
2909
  }
2556
2910
  await query;
@@ -2562,10 +2916,10 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
2562
2916
  args: queryArgs
2563
2917
  };
2564
2918
  };
2565
- var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) => {
2919
+ var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requireWhere, filterCtx) => {
2566
2920
  const queryArgs = {
2567
2921
  where: {
2568
- type: filterArgs
2922
+ type: single || requireWhere ? new GraphQLNonNull4(filterArgs) : filterArgs
2569
2923
  }
2570
2924
  };
2571
2925
  return {
@@ -2573,10 +2927,14 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) =>
2573
2927
  resolver: async (_source, args, context, _info) => {
2574
2928
  try {
2575
2929
  const { where } = args;
2930
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
2931
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2576
2932
  const executor = resolveExecutor(db, context);
2933
+ if (single) {
2934
+ await assertSingleMatch(executor, table, filters, fieldName);
2935
+ }
2577
2936
  let query = executor.delete(table);
2578
- if (where) {
2579
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
2937
+ if (filters) {
2580
2938
  query = query.where(filters);
2581
2939
  }
2582
2940
  await query;
@@ -2665,7 +3023,9 @@ var generateSchemaData = (db, schema, relations, options) => {
2665
3023
  upsertArrayFieldName,
2666
3024
  upsertSingleFieldName,
2667
3025
  updateFieldName,
2668
- deleteFieldName
3026
+ updateSingleFieldName,
3027
+ deleteFieldName,
3028
+ deleteSingleFieldName
2669
3029
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
2670
3030
  const selectArrGenerated = generateSelectArray(
2671
3031
  db,
@@ -2710,9 +3070,41 @@ var generateSchemaData = (db, schema, relations, options) => {
2710
3070
  updateInput,
2711
3071
  tableFilters,
2712
3072
  updateFieldName,
3073
+ false,
3074
+ features.requireWhere,
3075
+ filterCtx
3076
+ ) : void 0;
3077
+ const updateSingleGenerated = features.update ? generateUpdate(
3078
+ db,
3079
+ tableName,
3080
+ schema[tableName],
3081
+ updateInput,
3082
+ tableFilters,
3083
+ updateSingleFieldName,
3084
+ true,
3085
+ features.requireWhere,
3086
+ filterCtx
3087
+ ) : void 0;
3088
+ const deleteGenerated = features.delete ? generateDelete(
3089
+ db,
3090
+ tableName,
3091
+ schema[tableName],
3092
+ tableFilters,
3093
+ deleteFieldName,
3094
+ false,
3095
+ features.requireWhere,
3096
+ filterCtx
3097
+ ) : void 0;
3098
+ const deleteSingleGenerated = features.delete ? generateDelete(
3099
+ db,
3100
+ tableName,
3101
+ schema[tableName],
3102
+ tableFilters,
3103
+ deleteSingleFieldName,
3104
+ true,
3105
+ features.requireWhere,
2713
3106
  filterCtx
2714
3107
  ) : void 0;
2715
- const deleteGenerated = features.delete ? generateDelete(db, tableName, schema[tableName], tableFilters, deleteFieldName, filterCtx) : void 0;
2716
3108
  const aggregateType = features.aggregates ? generateAggregateTypes(schema[tableName], tableName, typeName, cacheCtx) : void 0;
2717
3109
  const aggregateGenerated = features.aggregates ? generateAggregate(
2718
3110
  db,
@@ -2770,7 +3162,9 @@ var generateSchemaData = (db, schema, relations, options) => {
2770
3162
  upsertArrGenerated,
2771
3163
  upsertSingleGenerated,
2772
3164
  updateGenerated,
2773
- deleteGenerated
3165
+ updateSingleGenerated,
3166
+ deleteGenerated,
3167
+ deleteSingleGenerated
2774
3168
  ]) {
2775
3169
  if (generated) {
2776
3170
  mutations[generated.name] = {
@@ -2890,7 +3284,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
2890
3284
  }
2891
3285
  if (orderBy) {
2892
3286
  q = q.orderBy(
2893
- ...extractOrderBy(table, orderBy),
3287
+ ...extractOrderBy(table, orderBy, relationFilterCtx(filterCtx, tableName)),
2894
3288
  ...distinctKeys ? primaryKeyOrderExprs(table, pkNames) : []
2895
3289
  );
2896
3290
  } else if ((distinctKeys || offset != null || limit != null) && pkNames.length) {
@@ -2951,7 +3345,7 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
2951
3345
  q = q.where(extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)));
2952
3346
  }
2953
3347
  if (orderBy) {
2954
- q = q.orderBy(...extractOrderBy(table, orderBy));
3348
+ q = q.orderBy(...extractOrderBy(table, orderBy, relationFilterCtx(filterCtx, tableName)));
2955
3349
  } else if (pkNames.length) {
2956
3350
  q = q.orderBy(...primaryKeyOrderExprs(table, pkNames));
2957
3351
  }
@@ -3111,13 +3505,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
3111
3505
  args: queryArgs
3112
3506
  };
3113
3507
  };
3114
- var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
3508
+ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx) => {
3115
3509
  const queryArgs = {
3116
3510
  set: {
3117
3511
  type: new GraphQLNonNull5(setArgs)
3118
3512
  },
3119
3513
  where: {
3120
- type: filterArgs
3514
+ type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
3121
3515
  }
3122
3516
  };
3123
3517
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -3143,16 +3537,26 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
3143
3537
  if (!Object.keys(input).length) {
3144
3538
  throw new GraphQLError6("Unable to update with no values specified!");
3145
3539
  }
3540
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
3541
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
3146
3542
  const executor = resolveExecutor(db, context);
3543
+ if (single) {
3544
+ await assertSingleMatch(executor, table, filters, fieldName);
3545
+ }
3147
3546
  let query = executor.update(table).set(input);
3148
- if (where) {
3149
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
3547
+ if (filters) {
3150
3548
  query = query.where(filters);
3151
3549
  }
3152
3550
  query = query.returning(columns);
3153
3551
  const result = await query;
3552
+ if (single && result.length > 1) {
3553
+ throw new GraphQLError6(`${fieldName}: 'where' matched more than one row!`);
3554
+ }
3555
+ if (single && !result[0]) {
3556
+ return void 0;
3557
+ }
3154
3558
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
3155
- return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
3559
+ return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
3156
3560
  } catch (e) {
3157
3561
  throw toGraphQLError(e);
3158
3562
  }
@@ -3160,10 +3564,10 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
3160
3564
  args: queryArgs
3161
3565
  };
3162
3566
  };
3163
- var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
3567
+ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
3164
3568
  const queryArgs = {
3165
3569
  where: {
3166
- type: filterArgs
3570
+ type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
3167
3571
  }
3168
3572
  };
3169
3573
  return {
@@ -3179,14 +3583,24 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, fi
3179
3583
  table,
3180
3584
  selectionCtx
3181
3585
  );
3586
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
3587
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
3182
3588
  const executor = resolveExecutor(db, context);
3589
+ if (single) {
3590
+ await assertSingleMatch(executor, table, filters, fieldName);
3591
+ }
3183
3592
  let query = executor.delete(table);
3184
- if (where) {
3185
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
3593
+ if (filters) {
3186
3594
  query = query.where(filters);
3187
3595
  }
3188
3596
  query = query.returning(columns);
3189
3597
  const result = await query;
3598
+ if (single && result.length > 1) {
3599
+ throw new GraphQLError6(`${fieldName}: 'where' matched more than one row!`);
3600
+ }
3601
+ if (single) {
3602
+ return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
3603
+ }
3190
3604
  return remapToGraphQLArrayOutput(result, tableName, table);
3191
3605
  } catch (e) {
3192
3606
  throw toGraphQLError(e);
@@ -3268,7 +3682,9 @@ function generateSchemaData2(db, schema, relations, options) {
3268
3682
  upsertArrayFieldName,
3269
3683
  upsertSingleFieldName,
3270
3684
  updateFieldName,
3271
- deleteFieldName
3685
+ updateSingleFieldName,
3686
+ deleteFieldName,
3687
+ deleteSingleFieldName
3272
3688
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
3273
3689
  const selectArrGenerated = generateSelectArray2(
3274
3690
  db,
@@ -3367,6 +3783,23 @@ function generateSchemaData2(db, schema, relations, options) {
3367
3783
  tableFilters,
3368
3784
  updateFieldName,
3369
3785
  typeName,
3786
+ false,
3787
+ features.requireWhere,
3788
+ typeNameMapper,
3789
+ filterCtx
3790
+ ) : void 0;
3791
+ const updateSingleGenerated = features.update ? generateUpdate2(
3792
+ db,
3793
+ tableName,
3794
+ schema[tableName],
3795
+ tables,
3796
+ eagerRelations,
3797
+ updateInput,
3798
+ tableFilters,
3799
+ updateSingleFieldName,
3800
+ typeName,
3801
+ true,
3802
+ features.requireWhere,
3370
3803
  typeNameMapper,
3371
3804
  filterCtx
3372
3805
  ) : void 0;
@@ -3377,6 +3810,20 @@ function generateSchemaData2(db, schema, relations, options) {
3377
3810
  tableFilters,
3378
3811
  deleteFieldName,
3379
3812
  typeName,
3813
+ false,
3814
+ features.requireWhere,
3815
+ filterCtx,
3816
+ { tableName, relationMap: namedRelations, tables }
3817
+ ) : void 0;
3818
+ const deleteSingleGenerated = features.delete ? generateDelete2(
3819
+ db,
3820
+ tableName,
3821
+ schema[tableName],
3822
+ tableFilters,
3823
+ deleteSingleFieldName,
3824
+ typeName,
3825
+ true,
3826
+ features.requireWhere,
3380
3827
  filterCtx,
3381
3828
  { tableName, relationMap: namedRelations, tables }
3382
3829
  ) : void 0;
@@ -3466,6 +3913,13 @@ function generateSchemaData2(db, schema, relations, options) {
3466
3913
  resolve: updateGenerated.resolver
3467
3914
  };
3468
3915
  }
3916
+ if (updateSingleGenerated) {
3917
+ mutations[updateSingleGenerated.name] = {
3918
+ type: singleTableItemOutput,
3919
+ args: updateSingleGenerated.args,
3920
+ resolve: updateSingleGenerated.resolver
3921
+ };
3922
+ }
3469
3923
  if (deleteGenerated) {
3470
3924
  mutations[deleteGenerated.name] = {
3471
3925
  type: arrTableItemOutput,
@@ -3473,6 +3927,13 @@ function generateSchemaData2(db, schema, relations, options) {
3473
3927
  resolve: deleteGenerated.resolver
3474
3928
  };
3475
3929
  }
3930
+ if (deleteSingleGenerated) {
3931
+ mutations[deleteSingleGenerated.name] = {
3932
+ type: singleTableItemOutput,
3933
+ args: deleteSingleGenerated.args,
3934
+ resolve: deleteSingleGenerated.resolver
3935
+ };
3936
+ }
3476
3937
  const activeInputs = [
3477
3938
  // The insert input types the upsert mutations too, so either feature keeps it.
3478
3939
  ...features.insert || onConflictInput ? [insertInput] : [],
@@ -3743,13 +4204,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
3743
4204
  args: queryArgs
3744
4205
  };
3745
4206
  };
3746
- var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
4207
+ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx) => {
3747
4208
  const queryArgs = {
3748
4209
  set: {
3749
4210
  type: new GraphQLNonNull6(setArgs)
3750
4211
  },
3751
4212
  where: {
3752
- type: filterArgs
4213
+ type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
3753
4214
  }
3754
4215
  };
3755
4216
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -3775,16 +4236,26 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
3775
4236
  if (!Object.keys(input).length) {
3776
4237
  throw new GraphQLError7("Unable to update with no values specified!");
3777
4238
  }
4239
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
4240
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
3778
4241
  const executor = resolveExecutor(db, context);
4242
+ if (single) {
4243
+ await assertSingleMatch(executor, table, filters, fieldName);
4244
+ }
3779
4245
  let query = executor.update(table).set(input);
3780
- if (where) {
3781
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
4246
+ if (filters) {
3782
4247
  query = query.where(filters);
3783
4248
  }
3784
4249
  query = query.returning(columns);
3785
4250
  const result = await query;
4251
+ if (single && result.length > 1) {
4252
+ throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
4253
+ }
4254
+ if (single && !result[0]) {
4255
+ return void 0;
4256
+ }
3786
4257
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
3787
- return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
4258
+ return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
3788
4259
  } catch (e) {
3789
4260
  throw toGraphQLError(e);
3790
4261
  }
@@ -3792,10 +4263,10 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
3792
4263
  args: queryArgs
3793
4264
  };
3794
4265
  };
3795
- var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
4266
+ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
3796
4267
  const queryArgs = {
3797
4268
  where: {
3798
- type: filterArgs
4269
+ type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
3799
4270
  }
3800
4271
  };
3801
4272
  return {
@@ -3811,14 +4282,24 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, fi
3811
4282
  table,
3812
4283
  selectionCtx
3813
4284
  );
4285
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
4286
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
3814
4287
  const executor = resolveExecutor(db, context);
4288
+ if (single) {
4289
+ await assertSingleMatch(executor, table, filters, fieldName);
4290
+ }
3815
4291
  let query = executor.delete(table);
3816
- if (where) {
3817
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
4292
+ if (filters) {
3818
4293
  query = query.where(filters);
3819
4294
  }
3820
4295
  query = query.returning(columns);
3821
4296
  const result = await query;
4297
+ if (single && result.length > 1) {
4298
+ throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
4299
+ }
4300
+ if (single) {
4301
+ return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
4302
+ }
3822
4303
  return remapToGraphQLArrayOutput(result, tableName, table);
3823
4304
  } catch (e) {
3824
4305
  throw toGraphQLError(e);
@@ -3901,7 +4382,9 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3901
4382
  upsertArrayFieldName,
3902
4383
  upsertSingleFieldName,
3903
4384
  updateFieldName,
3904
- deleteFieldName
4385
+ updateSingleFieldName,
4386
+ deleteFieldName,
4387
+ deleteSingleFieldName
3905
4388
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
3906
4389
  const selectArrGenerated = generateSelectArray3(
3907
4390
  db,
@@ -4000,6 +4483,23 @@ var generateSchemaData3 = (db, schema, relations, options) => {
4000
4483
  tableFilters,
4001
4484
  updateFieldName,
4002
4485
  typeName,
4486
+ false,
4487
+ features.requireWhere,
4488
+ typeNameMapper,
4489
+ filterCtx
4490
+ ) : void 0;
4491
+ const updateSingleGenerated = features.update ? generateUpdate3(
4492
+ db,
4493
+ tableName,
4494
+ schema[tableName],
4495
+ tables,
4496
+ eagerRelations,
4497
+ updateInput,
4498
+ tableFilters,
4499
+ updateSingleFieldName,
4500
+ typeName,
4501
+ true,
4502
+ features.requireWhere,
4003
4503
  typeNameMapper,
4004
4504
  filterCtx
4005
4505
  ) : void 0;
@@ -4010,6 +4510,20 @@ var generateSchemaData3 = (db, schema, relations, options) => {
4010
4510
  tableFilters,
4011
4511
  deleteFieldName,
4012
4512
  typeName,
4513
+ false,
4514
+ features.requireWhere,
4515
+ filterCtx,
4516
+ { tableName, relationMap: namedRelations, tables }
4517
+ ) : void 0;
4518
+ const deleteSingleGenerated = features.delete ? generateDelete3(
4519
+ db,
4520
+ tableName,
4521
+ schema[tableName],
4522
+ tableFilters,
4523
+ deleteSingleFieldName,
4524
+ typeName,
4525
+ true,
4526
+ features.requireWhere,
4013
4527
  filterCtx,
4014
4528
  { tableName, relationMap: namedRelations, tables }
4015
4529
  ) : void 0;
@@ -4099,6 +4613,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
4099
4613
  resolve: updateGenerated.resolver
4100
4614
  };
4101
4615
  }
4616
+ if (updateSingleGenerated) {
4617
+ mutations[updateSingleGenerated.name] = {
4618
+ type: singleTableItemOutput,
4619
+ args: updateSingleGenerated.args,
4620
+ resolve: updateSingleGenerated.resolver
4621
+ };
4622
+ }
4102
4623
  if (deleteGenerated) {
4103
4624
  mutations[deleteGenerated.name] = {
4104
4625
  type: arrTableItemOutput,
@@ -4106,6 +4627,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
4106
4627
  resolve: deleteGenerated.resolver
4107
4628
  };
4108
4629
  }
4630
+ if (deleteSingleGenerated) {
4631
+ mutations[deleteSingleGenerated.name] = {
4632
+ type: singleTableItemOutput,
4633
+ args: deleteSingleGenerated.args,
4634
+ resolve: deleteSingleGenerated.resolver
4635
+ };
4636
+ }
4109
4637
  const activeInputs = [
4110
4638
  // The insert input types the upsert mutations too, so either feature keeps it.
4111
4639
  ...features.insert || onConflictInput ? [insertInput] : [],
@@ -4174,7 +4702,8 @@ var buildSchema = (db, config) => {
4174
4702
  insert: config?.features?.insert ?? true,
4175
4703
  update: config?.features?.update ?? true,
4176
4704
  delete: config?.features?.delete ?? true,
4177
- upsert: config?.features?.upsert ?? false
4705
+ upsert: config?.features?.upsert ?? false,
4706
+ requireWhere: config?.features?.requireWhere ?? false
4178
4707
  };
4179
4708
  const complexityConfig = config?.complexity ?? true;
4180
4709
  const complexity = complexityConfig === false ? void 0 : {
@@ -4247,6 +4776,7 @@ export {
4247
4776
  GraphQLBigIntString,
4248
4777
  GraphQLDate,
4249
4778
  GraphQLDateTime,
4779
+ GraphQLDecimalString,
4250
4780
  GraphQLJSON,
4251
4781
  GraphQLUUID,
4252
4782
  buildSchema,