@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.cjs CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  GraphQLBigIntString: () => GraphQLBigIntString,
34
34
  GraphQLDate: () => import_graphql_scalars.GraphQLDate,
35
35
  GraphQLDateTime: () => import_graphql_scalars.GraphQLDateTime,
36
+ GraphQLDecimalString: () => GraphQLDecimalString,
36
37
  GraphQLJSON: () => import_graphql_scalars.GraphQLJSON,
37
38
  GraphQLUUID: () => import_graphql_scalars.GraphQLUUID,
38
39
  buildSchema: () => buildSchema,
@@ -298,13 +299,6 @@ var remapFromGraphQLArrayInput = (queryInput, table) => {
298
299
  return queryInput;
299
300
  };
300
301
 
301
- // src/util/type-converter/index.ts
302
- var import_drizzle_orm2 = require("drizzle-orm");
303
- var import_mysql_core = require("drizzle-orm/mysql-core");
304
- var import_pg_core = require("drizzle-orm/pg-core");
305
- var import_sqlite_core = require("drizzle-orm/sqlite-core");
306
- var import_graphql3 = require("graphql");
307
-
308
302
  // src/util/scalars/index.ts
309
303
  var import_graphql2 = require("graphql");
310
304
  var import_graphql_scalars = require("graphql-scalars");
@@ -343,8 +337,44 @@ var GraphQLBigIntString = new import_graphql2.GraphQLScalarType({
343
337
  return asDecimalString(ast.value);
344
338
  }
345
339
  });
340
+ var numericStringPattern = /^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/;
341
+ var asNumericString = (value) => {
342
+ if (typeof value === "bigint") {
343
+ return value.toString();
344
+ }
345
+ if (typeof value === "number") {
346
+ if (!Number.isFinite(value)) {
347
+ throw new import_graphql2.GraphQLError(`Decimal cannot represent non-finite value: ${value}`);
348
+ }
349
+ return String(value);
350
+ }
351
+ if (typeof value === "string") {
352
+ if (!numericStringPattern.test(value)) {
353
+ throw new import_graphql2.GraphQLError(`Decimal cannot represent non-numeric value: "${value}"`);
354
+ }
355
+ return value;
356
+ }
357
+ throw new import_graphql2.GraphQLError(`Decimal cannot represent value: ${JSON.stringify(value)}`);
358
+ };
359
+ var GraphQLDecimalString = new import_graphql2.GraphQLScalarType({
360
+ name: "Decimal",
361
+ description: "An arbitrary-precision decimal, transported as a numeric string so that values beyond JavaScript's double-precision range survive the round-trip intact.",
362
+ serialize: asNumericString,
363
+ parseValue: asNumericString,
364
+ parseLiteral: (ast) => {
365
+ if (ast.kind !== import_graphql2.Kind.STRING && ast.kind !== import_graphql2.Kind.INT && ast.kind !== import_graphql2.Kind.FLOAT) {
366
+ throw new import_graphql2.GraphQLError(`Decimal cannot represent a ${ast.kind}`, { nodes: ast });
367
+ }
368
+ return asNumericString(ast.value);
369
+ }
370
+ });
346
371
 
347
372
  // src/util/type-converter/index.ts
373
+ var import_drizzle_orm2 = require("drizzle-orm");
374
+ var import_mysql_core = require("drizzle-orm/mysql-core");
375
+ var import_pg_core = require("drizzle-orm/pg-core");
376
+ var import_sqlite_core = require("drizzle-orm/sqlite-core");
377
+ var import_graphql3 = require("graphql");
348
378
  var allowedNameChars = /^[a-zA-Z0-9_]+$/;
349
379
  var enumMap = /* @__PURE__ */ new WeakMap();
350
380
  var generateEnumCached = (column, columnName, tableName) => {
@@ -381,7 +411,7 @@ var geoXyInputType = new import_graphql3.GraphQLInputObjectType({
381
411
  }
382
412
  });
383
413
  var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
384
- const { type: baseType } = (0, import_drizzle_orm2.extractExtendedColumnType)(column);
414
+ const { type: baseType, constraint } = (0, import_drizzle_orm2.extractExtendedColumnType)(column);
385
415
  switch (baseType) {
386
416
  case "boolean":
387
417
  return { type: import_graphql3.GraphQLBoolean, description: "Boolean" };
@@ -400,6 +430,9 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
400
430
  if (column.enumValues?.length) {
401
431
  return { type: generateEnumCached(column, columnName, tableName) };
402
432
  }
433
+ if (constraint === "numeric" && !column.dimensions) {
434
+ return { type: GraphQLDecimalString, description: "Decimal" };
435
+ }
403
436
  if (column instanceof import_pg_core.PgTimestamp || column instanceof import_pg_core.PgTimestampString) {
404
437
  return { type: import_graphql_scalars.GraphQLDateTime, description: "DateTime" };
405
438
  }
@@ -409,6 +442,15 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
409
442
  if (column instanceof import_pg_core.PgDateString) {
410
443
  return isInput ? { type: import_graphql3.GraphQLString, description: "Date" } : { type: import_graphql_scalars.GraphQLDate, description: "Date" };
411
444
  }
445
+ {
446
+ const dims = column.dimensions;
447
+ if (dims !== void 0 && dims > 0) {
448
+ return {
449
+ type: new import_graphql3.GraphQLList(new import_graphql3.GraphQLNonNull(import_graphql3.GraphQLString)),
450
+ description: "Array<String>"
451
+ };
452
+ }
453
+ }
412
454
  return { type: import_graphql3.GraphQLString, description: "String" };
413
455
  case "bigint":
414
456
  return { type: GraphQLBigIntString, description: "BigInt" };
@@ -559,10 +601,10 @@ var resolveQueryExecutor = (db, context, tableName, buildTimeQueryBase) => {
559
601
  queryBase: buildTimeQueryBase ? executor?.query?.[tableName] ?? buildTimeQueryBase : buildTimeQueryBase
560
602
  };
561
603
  };
562
- var batchedPaginatedRelationQuery = async (db, targetTable, foreignCol, whereCondition, orderByArg, limit, offset, pkNames) => {
604
+ var batchedPaginatedRelationQuery = async (db, targetTable, foreignCol, whereCondition, orderByArg, limit, offset, pkNames, orderCtx) => {
563
605
  const cols = (0, import_drizzle_orm3.getColumns)(targetTable);
564
606
  const orderExprs = [
565
- ...orderByArg ? extractOrderBy(targetTable, orderByArg) : [],
607
+ ...orderByArg ? extractOrderBy(targetTable, orderByArg, orderCtx) : [],
566
608
  ...primaryKeyOrderExprs(targetTable, pkNames)
567
609
  ];
568
610
  const orderClause = orderExprs.length ? import_drizzle_orm3.sql` order by ${import_drizzle_orm3.sql.join(orderExprs, import_drizzle_orm3.sql`, `)}` : import_drizzle_orm3.sql``;
@@ -626,12 +668,13 @@ var createRelationResolverFactory = (db, tables, filterCtx) => ({ tableName, rel
626
668
  orderByArg,
627
669
  limit ?? null,
628
670
  offset ?? null,
629
- targetPkNames
671
+ targetPkNames,
672
+ relationFilterCtx(filterCtx, targetTableName)
630
673
  );
631
674
  } else {
632
675
  let q = executor.select().from(targetTable).where(whereCondition);
633
676
  if (orderByArg) {
634
- q = q.orderBy(...extractOrderBy(targetTable, orderByArg));
677
+ q = q.orderBy(...extractOrderBy(targetTable, orderByArg, relationFilterCtx(filterCtx, targetTableName)));
635
678
  }
636
679
  rows = await q;
637
680
  }
@@ -720,6 +763,20 @@ var extractSelectedColumnsFromTreeSQLFormat = (tree, table, selectionCtx) => {
720
763
  }
721
764
  return Object.fromEntries(selectedColumns);
722
765
  };
766
+ var orderNulls = new import_graphql4.GraphQLEnumType({
767
+ name: "OrderNulls",
768
+ description: "Where NULL values sort relative to non-NULL values",
769
+ values: {
770
+ first: {
771
+ value: "first",
772
+ description: "NULL values sort before all non-NULL values"
773
+ },
774
+ last: {
775
+ value: "last",
776
+ description: "NULL values sort after all non-NULL values"
777
+ }
778
+ }
779
+ });
723
780
  var innerOrder = new import_graphql4.GraphQLInputObjectType({
724
781
  name: "InnerOrder",
725
782
  fields: {
@@ -744,11 +801,15 @@ var innerOrder = new import_graphql4.GraphQLInputObjectType({
744
801
  priority: {
745
802
  type: new import_graphql4.GraphQLNonNull(import_graphql4.GraphQLInt),
746
803
  description: "Priority of current field"
804
+ },
805
+ nulls: {
806
+ type: orderNulls,
807
+ 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)"
747
808
  }
748
809
  }
749
810
  });
750
- var resolveGenericFilterName = (column, columnName, columnGraphQLType) => {
751
- if (columnName === "id" || columnName.endsWith("Id")) {
811
+ var resolveGenericFilterName = (column, columnGraphQLType) => {
812
+ if (columnGraphQLType.type === import_graphql_scalars.GraphQLUUID) {
752
813
  return "Id";
753
814
  }
754
815
  if (columnGraphQLType.type === import_graphql4.GraphQLBoolean) {
@@ -757,27 +818,50 @@ var resolveGenericFilterName = (column, columnName, columnGraphQLType) => {
757
818
  if (columnGraphQLType.type instanceof import_graphql4.GraphQLEnumType) {
758
819
  return columnGraphQLType.type.name;
759
820
  }
821
+ if (columnGraphQLType.type === GraphQLBigIntString) {
822
+ return "BigInt";
823
+ }
824
+ if (columnGraphQLType.type === GraphQLDecimalString) {
825
+ return "Decimal";
826
+ }
760
827
  if (columnGraphQLType.type instanceof import_graphql4.GraphQLList) {
761
828
  const desc2 = columnGraphQLType.description ?? "";
762
- return desc2.includes("Integer") ? "IntArray" : "FloatArray";
829
+ let inner = columnGraphQLType.type.ofType;
830
+ if (inner instanceof import_graphql4.GraphQLNonNull) {
831
+ inner = inner.ofType;
832
+ }
833
+ if (desc2.includes("Integer") || inner === import_graphql4.GraphQLInt) {
834
+ return "IntArray";
835
+ }
836
+ if (desc2.includes("Float") || inner === import_graphql4.GraphQLFloat) {
837
+ return "FloatArray";
838
+ }
839
+ return "StringArray";
763
840
  }
764
841
  const ct = column.columnType ?? "";
765
842
  if (ct === "PgTimestamp" || ct === "PgTimestampString" || ct === "PgDate") {
766
843
  return "DateTime";
767
844
  }
845
+ if (columnGraphQLType.type === import_graphql4.GraphQLInt) {
846
+ return "Int";
847
+ }
848
+ if (columnGraphQLType.type === import_graphql4.GraphQLFloat) {
849
+ return "Float";
850
+ }
768
851
  return "String";
769
852
  };
853
+ var FILTERS_WITHOUT_STRING_OPS = /* @__PURE__ */ new Set(["Id", "Int", "Float", "BigInt", "Decimal"]);
770
854
  var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
771
855
  const columnGraphQLType = drizzleColumnToGraphQLType(column, columnName, tableName, true, false, true);
772
- const genericName = resolveGenericFilterName(column, columnName, columnGraphQLType);
856
+ const genericName = resolveGenericFilterName(column, columnGraphQLType);
773
857
  const cached = cacheCtx.genericFilterCache.get(genericName);
774
858
  if (cached) {
775
- return cached.main;
859
+ return cached;
776
860
  }
777
861
  const colType = columnGraphQLType.type;
778
862
  const colDesc = columnGraphQLType.description;
779
863
  const colArr = new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(colType));
780
- const isId = genericName === "Id";
864
+ const omitStringOps = FILTERS_WITHOUT_STRING_OPS.has(genericName);
781
865
  const baseFields = {
782
866
  eq: { type: colType, description: colDesc },
783
867
  ne: { type: colType, description: colDesc },
@@ -785,31 +869,60 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
785
869
  lte: { type: colType, description: colDesc },
786
870
  gt: { type: colType, description: colDesc },
787
871
  gte: { type: colType, description: colDesc },
788
- ...isId ? {} : {
872
+ ...omitStringOps ? {} : {
789
873
  like: { type: import_graphql4.GraphQLString },
790
874
  notLike: { type: import_graphql4.GraphQLString },
791
875
  ilike: { type: import_graphql4.GraphQLString },
792
- notIlike: { type: import_graphql4.GraphQLString }
876
+ notIlike: { type: import_graphql4.GraphQLString },
877
+ startsWith: {
878
+ type: import_graphql4.GraphQLString,
879
+ description: "Matches values starting with the given string. `%`, `_` and `\\` are matched literally."
880
+ },
881
+ endsWith: {
882
+ type: import_graphql4.GraphQLString,
883
+ description: "Matches values ending with the given string. `%`, `_` and `\\` are matched literally."
884
+ },
885
+ contains: {
886
+ type: import_graphql4.GraphQLString,
887
+ description: "Matches values containing the given string. `%`, `_` and `\\` are matched literally."
888
+ },
889
+ iStartsWith: {
890
+ type: import_graphql4.GraphQLString,
891
+ description: "Case-insensitive `startsWith`."
892
+ },
893
+ iEndsWith: {
894
+ type: import_graphql4.GraphQLString,
895
+ description: "Case-insensitive `endsWith`."
896
+ },
897
+ iContains: {
898
+ type: import_graphql4.GraphQLString,
899
+ description: "Case-insensitive `contains`."
900
+ }
793
901
  },
794
902
  inArray: { type: colArr, description: `Array<${colDesc}>` },
795
903
  notInArray: { type: colArr, description: `Array<${colDesc}>` },
796
904
  isNull: { type: import_graphql4.GraphQLBoolean },
797
905
  isNotNull: { type: import_graphql4.GraphQLBoolean }
798
906
  };
799
- const orType = new import_graphql4.GraphQLInputObjectType({
800
- name: `${genericName}FilterOr`,
801
- fields: { ...baseFields }
802
- });
803
907
  const mainType = new import_graphql4.GraphQLInputObjectType({
804
908
  name: `${genericName}Filter`,
805
- fields: {
909
+ fields: () => ({
806
910
  ...baseFields,
807
911
  OR: {
808
- type: new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(orType))
912
+ type: new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(mainType)),
913
+ description: "At least one branch matches; ANDed with any sibling operators"
914
+ },
915
+ AND: {
916
+ type: new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(mainType)),
917
+ description: "Every branch matches"
918
+ },
919
+ NOT: {
920
+ type: mainType,
921
+ description: "Negates the nested operators"
809
922
  }
810
- }
923
+ })
811
924
  });
812
- cacheCtx.genericFilterCache.set(genericName, { main: mainType, or: orType });
925
+ cacheCtx.genericFilterCache.set(genericName, mainType);
813
926
  return mainType;
814
927
  };
815
928
  var orderMap = /* @__PURE__ */ new WeakMap();
@@ -863,19 +976,53 @@ var generateTableSelectTypeFieldsCached = (table, tableName) => {
863
976
  fieldMap.set(table, remapped);
864
977
  return remapped;
865
978
  };
866
- var generateTableOrderTypeCached = (table, tableName, typeNameMapper, cacheCtx) => {
979
+ var isFilterableRelation = (relation) => !relation.through;
980
+ var generateRelationOrderFields = (tableName, cacheCtx, typeNameMapper, columnFields, relationMap, tables) => {
981
+ const relations = relationMap?.[tableName];
982
+ if (!relations || !tables) {
983
+ return {};
984
+ }
985
+ const fields = {};
986
+ for (const [relationName, relEntry] of Object.entries(relations)) {
987
+ if (relationName in columnFields) {
988
+ continue;
989
+ }
990
+ const targetTable = tables[relEntry.targetTableName];
991
+ const relation = relEntry.relation ?? relEntry;
992
+ if (!targetTable || !(0, import_drizzle_orm3.is)(relation, import_drizzle_orm3.One) || !isFilterableRelation(relation)) {
993
+ continue;
994
+ }
995
+ fields[relationName] = {
996
+ type: generateTableOrderTypeCached(
997
+ targetTable,
998
+ relEntry.targetTableName,
999
+ typeNameMapper,
1000
+ cacheCtx,
1001
+ relationMap,
1002
+ tables
1003
+ ),
1004
+ description: `Order by columns of the related ${relationName} row`
1005
+ };
1006
+ }
1007
+ return fields;
1008
+ };
1009
+ var generateTableOrderTypeCached = (table, tableName, typeNameMapper, cacheCtx, relationMap, tables) => {
867
1010
  if (cacheCtx.orderTypeCache.has(table)) {
868
1011
  return cacheCtx.orderTypeCache.get(table);
869
1012
  }
870
- const orderColumns = generateTableOrderCached(table);
871
1013
  const order = new import_graphql4.GraphQLInputObjectType({
872
1014
  name: `${resolveTypeName(tableName, typeNameMapper)}OrderBy`,
873
- fields: orderColumns
1015
+ fields: () => {
1016
+ const orderColumns = generateTableOrderCached(table);
1017
+ return {
1018
+ ...orderColumns,
1019
+ ...generateRelationOrderFields(tableName, cacheCtx, typeNameMapper, orderColumns, relationMap, tables)
1020
+ };
1021
+ }
874
1022
  });
875
1023
  cacheCtx.orderTypeCache.set(table, order);
876
1024
  return order;
877
1025
  };
878
- var isFilterableRelation = (relation) => !relation.through;
879
1026
  var generateListRelationFilterCached = (targetTable, targetTableName, cacheCtx, typeNameMapper, relationMap, tables) => {
880
1027
  const cached = cacheCtx.listRelationFilterCache.get(targetTableName);
881
1028
  if (cached) {
@@ -914,7 +1061,7 @@ var generateRelationFilterFields = (tableName, cacheCtx, typeNameMapper, columnF
914
1061
  }
915
1062
  const targetTable = tables[relEntry.targetTableName];
916
1063
  const relation = relEntry.relation ?? relEntry;
917
- if (!targetTable || !isFilterableRelation(relation)) {
1064
+ if (!targetTable) {
918
1065
  continue;
919
1066
  }
920
1067
  fields[relationName] = (0, import_drizzle_orm3.is)(relation, import_drizzle_orm3.One) ? {
@@ -951,16 +1098,21 @@ var generateTableFilterTypeCached = (table, tableName, cacheCtx, typeNameMapper,
951
1098
  ...generateRelationFilterFields(tableName, cacheCtx, typeNameMapper, filterColumns, relationMap, tables)
952
1099
  };
953
1100
  };
954
- const orFilters = new import_graphql4.GraphQLInputObjectType({
955
- name: `${resolveTypeName(tableName, typeNameMapper)}FiltersOr`,
956
- fields: buildFields
957
- });
958
1101
  const filters = new import_graphql4.GraphQLInputObjectType({
959
1102
  name: `${resolveTypeName(tableName, typeNameMapper)}Filters`,
960
1103
  fields: () => ({
961
1104
  ...buildFields(),
962
1105
  OR: {
963
- type: new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(orFilters))
1106
+ type: new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(filters)),
1107
+ description: "At least one branch matches; ANDed with any sibling fields"
1108
+ },
1109
+ AND: {
1110
+ type: new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(filters)),
1111
+ description: "Every branch matches"
1112
+ },
1113
+ NOT: {
1114
+ type: filters,
1115
+ description: "Negates the nested filters"
964
1116
  }
965
1117
  })
966
1118
  });
@@ -969,7 +1121,7 @@ var generateTableFilterTypeCached = (table, tableName, cacheCtx, typeNameMapper,
969
1121
  };
970
1122
  var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromRelationName, withOrder, relationsDepthLimit, cacheCtx, typeNameMapper, usedTables = /* @__PURE__ */ new Set(), resolverFactory, currentDepth = 0, relationAggregateFactory) => {
971
1123
  const table = tables[tableName];
972
- const order = withOrder ? generateTableOrderTypeCached(table, tableName, typeNameMapper, cacheCtx) : void 0;
1124
+ const order = withOrder ? generateTableOrderTypeCached(table, tableName, typeNameMapper, cacheCtx, relationMap, tables) : void 0;
973
1125
  const filters = generateTableFilterTypeCached(table, tableName, cacheCtx, typeNameMapper, relationMap, tables);
974
1126
  const tableFields = generateTableSelectTypeFieldsCached(table, tableName);
975
1127
  const relationsForTable = relationMap[tableName];
@@ -1055,10 +1207,11 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1055
1207
  }
1056
1208
  const resolve = resolverFactory?.({ tableName, relationName, relEntry, isOne });
1057
1209
  if (isOne) {
1210
+ const isRequired = relation.optional === false;
1058
1211
  rawRelationFields.push([
1059
1212
  relationName,
1060
1213
  {
1061
- type: relType,
1214
+ type: isRequired ? new import_graphql4.GraphQLNonNull(relType) : relType,
1062
1215
  args: {
1063
1216
  where: { type: relSelectData.filters }
1064
1217
  },
@@ -1196,28 +1349,95 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
1196
1349
  outputs
1197
1350
  };
1198
1351
  };
1199
- 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]);
1200
- var extractOrderBy = (table, orderArgs) => orderByEntries(orderArgs).map(
1201
- ([column, direction]) => direction === "asc" ? (0, import_drizzle_orm3.asc)((0, import_drizzle_orm3.getColumns)(table)[column]) : (0, import_drizzle_orm3.desc)((0, import_drizzle_orm3.getColumns)(table)[column])
1202
- );
1203
- var extractFiltersColumn = (column, columnName, operators) => {
1204
- if (!operators.OR?.length) {
1205
- delete operators.OR;
1352
+ var orderByEntries = (orderArgs) => Object.entries(orderArgs).sort((a, b) => (b[1]?.priority ?? 0) - (a[1]?.priority ?? 0)).filter(([, config]) => config).map(([column, config]) => {
1353
+ if (typeof config === "object" && config.direction === void 0) {
1354
+ throw new import_graphql4.GraphQLError(`ORDER BY ${column}: ordering through a relation is not supported in this query`);
1355
+ }
1356
+ return [column, config.direction, config.nulls ?? void 0];
1357
+ });
1358
+ var orderExpressions = (expr, direction, nulls, dialectColumn) => {
1359
+ const directed = direction === "asc" ? (0, import_drizzle_orm3.asc)(expr) : (0, import_drizzle_orm3.desc)(expr);
1360
+ if (!nulls) {
1361
+ return [directed];
1362
+ }
1363
+ const isMySql = (dialectColumn.columnType ?? "").startsWith("MySql");
1364
+ if (isMySql) {
1365
+ const nullsKey = nulls === "first" ? (0, import_drizzle_orm3.desc)(import_drizzle_orm3.sql`(${expr} is null)`) : (0, import_drizzle_orm3.asc)(import_drizzle_orm3.sql`(${expr} is null)`);
1366
+ return [nullsKey, directed];
1206
1367
  }
1207
- const entries = Object.entries(operators);
1208
- if (operators.OR) {
1209
- if (entries.length > 1) {
1210
- throw new import_graphql4.GraphQLError(`WHERE ${columnName}: Cannot specify both fields and 'OR' in column operators!`);
1368
+ return [nulls === "first" ? import_drizzle_orm3.sql`${directed} nulls first` : import_drizzle_orm3.sql`${directed} nulls last`];
1369
+ };
1370
+ var extendRelationOrderChain = (parentTable, relationName, relEntry, ctx, chain) => {
1371
+ const targetTable = ctx.tables[relEntry.targetTableName];
1372
+ const relation = relEntry.relation ?? relEntry;
1373
+ if (!targetTable || !(0, import_drizzle_orm3.is)(relation, import_drizzle_orm3.One) || !isFilterableRelation(relation)) {
1374
+ throw new import_graphql4.GraphQLError(`ORDER BY ${relationName}: Relation cannot be used for ordering`);
1375
+ }
1376
+ ctx.aliases ??= { n: 0 };
1377
+ const aliasedTarget = (0, import_drizzle_orm3.aliasedTable)(targetTable, `dgql_ord_${ctx.aliases.n++}`);
1378
+ const joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
1379
+ const relationWhere = relation.where ? (0, import_drizzle_orm3.relationsFilterToSQL)(relation.isReversed ? parentTable : aliasedTarget, relation.where) : void 0;
1380
+ return {
1381
+ fromParts: [...chain?.fromParts ?? [], (0, import_drizzle_orm3.getTableAsAliasSQL)(aliasedTarget)],
1382
+ conditions: [
1383
+ ...chain?.conditions ?? [],
1384
+ ...joinCondition ? [joinCondition] : [],
1385
+ ...relationWhere ? [relationWhere] : []
1386
+ ],
1387
+ table: aliasedTarget
1388
+ };
1389
+ };
1390
+ var collectOrderEntries = (table, tableKey, orderArgs, ctx, chain, out) => {
1391
+ const columns = (0, import_drizzle_orm3.getColumns)(table);
1392
+ const relations = ctx?.relationMap[tableKey];
1393
+ for (const [key, config] of Object.entries(orderArgs)) {
1394
+ if (config === null || config === void 0) {
1395
+ continue;
1211
1396
  }
1212
- const variants2 = [];
1213
- for (const variant of operators.OR) {
1214
- const extracted = extractFiltersColumn(column, columnName, variant);
1215
- if (extracted) {
1216
- variants2.push(extracted);
1217
- }
1397
+ const column = columns[key];
1398
+ if (column) {
1399
+ out.push({
1400
+ expression: chain ? import_drizzle_orm3.sql`(select ${column} from ${import_drizzle_orm3.sql.join(chain.fromParts, import_drizzle_orm3.sql`, `)} where ${(0, import_drizzle_orm3.and)(...chain.conditions)})` : column,
1401
+ column,
1402
+ direction: config.direction,
1403
+ nulls: config.nulls ?? void 0,
1404
+ priority: config.priority ?? 0
1405
+ });
1406
+ continue;
1407
+ }
1408
+ const relEntry = relations?.[key];
1409
+ if (!relEntry || !ctx) {
1410
+ throw new import_graphql4.GraphQLError(`ORDER BY ${key}: Unknown column or relation`);
1218
1411
  }
1219
- return variants2.length ? variants2.length > 1 ? (0, import_drizzle_orm3.or)(...variants2) : variants2[0] : void 0;
1412
+ const nextChain = extendRelationOrderChain(chain?.table ?? table, key, relEntry, ctx, chain);
1413
+ collectOrderEntries(nextChain.table, relEntry.targetTableName, config, ctx, nextChain, out);
1220
1414
  }
1415
+ };
1416
+ var extractOrderBy = (table, orderArgs, ctx) => {
1417
+ const entries = [];
1418
+ collectOrderEntries(table, ctx?.tableKey ?? "", orderArgs, ctx, void 0, entries);
1419
+ return entries.sort((a, b) => b.priority - a.priority).flatMap((entry) => orderExpressions(entry.expression, entry.direction, entry.nulls, entry.column));
1420
+ };
1421
+ var LIKE_ESCAPE_CHAR = "\\";
1422
+ var escapeLikeValue = (value) => value.replace(/[\\%_]/g, (char) => `\\${char}`);
1423
+ var safeLikeOps = {
1424
+ startsWith: { buildPattern: (value) => `${escapeLikeValue(value)}%`, insensitive: false },
1425
+ endsWith: { buildPattern: (value) => `%${escapeLikeValue(value)}`, insensitive: false },
1426
+ contains: { buildPattern: (value) => `%${escapeLikeValue(value)}%`, insensitive: false },
1427
+ iStartsWith: { buildPattern: (value) => `${escapeLikeValue(value)}%`, insensitive: true },
1428
+ iEndsWith: { buildPattern: (value) => `%${escapeLikeValue(value)}`, insensitive: true },
1429
+ iContains: { buildPattern: (value) => `%${escapeLikeValue(value)}%`, insensitive: true }
1430
+ };
1431
+ var safeLikeCondition = (column, pattern, insensitive) => {
1432
+ if (!insensitive) {
1433
+ return import_drizzle_orm3.sql`${column} like ${pattern} escape ${LIKE_ESCAPE_CHAR}`;
1434
+ }
1435
+ const isPg = (column.columnType ?? "").startsWith("Pg");
1436
+ return isPg ? import_drizzle_orm3.sql`${column} ilike ${pattern} escape ${LIKE_ESCAPE_CHAR}` : import_drizzle_orm3.sql`lower(${column}) like ${pattern.toLowerCase()} escape ${LIKE_ESCAPE_CHAR}`;
1437
+ };
1438
+ var extractFiltersColumn = (column, columnName, operators) => {
1439
+ const { OR, AND, NOT, ...restOperators } = operators;
1440
+ const entries = Object.entries(restOperators);
1221
1441
  const singleValueOps = { eq: import_drizzle_orm3.eq, ne: import_drizzle_orm3.ne, gt: import_drizzle_orm3.gt, gte: import_drizzle_orm3.gte, lt: import_drizzle_orm3.lt, lte: import_drizzle_orm3.lte };
1222
1442
  const stringValueOps = { like: import_drizzle_orm3.like, notLike: import_drizzle_orm3.notLike, ilike: import_drizzle_orm3.ilike, notIlike: import_drizzle_orm3.notIlike };
1223
1443
  const arrayValueOps = { inArray: import_drizzle_orm3.inArray, notInArray: import_drizzle_orm3.notInArray };
@@ -1232,6 +1452,9 @@ var extractFiltersColumn = (column, columnName, operators) => {
1232
1452
  variants.push(singleValueOps[operatorName](column, singleValue));
1233
1453
  } else if (operatorName in stringValueOps) {
1234
1454
  variants.push(stringValueOps[operatorName](column, operatorValue));
1455
+ } else if (operatorName in safeLikeOps) {
1456
+ const { buildPattern, insensitive } = safeLikeOps[operatorName];
1457
+ variants.push(safeLikeCondition(column, buildPattern(operatorValue), insensitive));
1235
1458
  } else if (operatorName in arrayValueOps) {
1236
1459
  if (!operatorValue.length) {
1237
1460
  throw new import_graphql4.GraphQLError(`WHERE ${columnName}: Unable to use operator ${operatorName} with an empty array!`);
@@ -1240,6 +1463,34 @@ var extractFiltersColumn = (column, columnName, operators) => {
1240
1463
  variants.push(arrayValueOps[operatorName](column, arrayValue));
1241
1464
  } else if (operatorName in nullableOps) {
1242
1465
  variants.push(nullableOps[operatorName](column));
1466
+ } else {
1467
+ throw new import_graphql4.GraphQLError(`WHERE ${columnName}: Unknown operator: ${operatorName}`);
1468
+ }
1469
+ }
1470
+ if (AND?.length) {
1471
+ for (const variant of AND) {
1472
+ const extracted = extractFiltersColumn(column, columnName, variant);
1473
+ if (extracted) {
1474
+ variants.push(extracted);
1475
+ }
1476
+ }
1477
+ }
1478
+ if (NOT) {
1479
+ const extracted = extractFiltersColumn(column, columnName, NOT);
1480
+ if (extracted) {
1481
+ variants.push((0, import_drizzle_orm3.not)(extracted));
1482
+ }
1483
+ }
1484
+ if (OR?.length) {
1485
+ const orVariants = [];
1486
+ for (const variant of OR) {
1487
+ const extracted = extractFiltersColumn(column, columnName, variant);
1488
+ if (extracted) {
1489
+ orVariants.push(extracted);
1490
+ }
1491
+ }
1492
+ if (orVariants.length) {
1493
+ variants.push(orVariants.length > 1 ? (0, import_drizzle_orm3.or)(...orVariants) : orVariants[0]);
1243
1494
  }
1244
1495
  }
1245
1496
  return variants.length ? variants.length > 1 ? (0, import_drizzle_orm3.and)(...variants) : variants[0] : void 0;
@@ -1264,39 +1515,105 @@ var buildRelationJoinCondition = (parentTable, relation, aliasedTarget, relation
1264
1515
  }
1265
1516
  return conditions.length > 1 ? (0, import_drizzle_orm3.and)(...conditions) : conditions[0];
1266
1517
  };
1518
+ var resolveJunctionColumn = (aliasedThrough, junctionRef, relationName) => {
1519
+ const throughColumns = (0, import_drizzle_orm3.getColumns)(aliasedThrough);
1520
+ const key = junctionRef?._?.key;
1521
+ const byKey = key ? throughColumns[key] : void 0;
1522
+ if (byKey) {
1523
+ return byKey;
1524
+ }
1525
+ const columnName = junctionRef?._?.column?.name;
1526
+ const byName = columnName ? Object.values(throughColumns).find((c) => c.name === columnName) : void 0;
1527
+ if (!byName) {
1528
+ throw new import_graphql4.GraphQLError(`WHERE ${relationName}: Relation cannot be used as a filter`);
1529
+ }
1530
+ return byName;
1531
+ };
1532
+ var buildThroughJoinConditions = (parentTable, relation, aliasedThrough, aliasedTarget, relationName) => {
1533
+ const sourceColumns = relation.sourceColumns;
1534
+ const targetColumns = relation.targetColumns;
1535
+ const through = relation.through;
1536
+ if (!sourceColumns?.length || !targetColumns?.length || through?.source.length !== sourceColumns.length || through.target.length !== targetColumns.length) {
1537
+ throw new import_graphql4.GraphQLError(`WHERE ${relationName}: Relation cannot be used as a filter`);
1538
+ }
1539
+ const parentColumns = Object.values((0, import_drizzle_orm3.getColumns)(parentTable));
1540
+ const targetTableColumns = Object.values((0, import_drizzle_orm3.getColumns)(aliasedTarget));
1541
+ const correlationConditions = [];
1542
+ for (let i = 0; i < sourceColumns.length; i++) {
1543
+ const localColumn = parentColumns.find((c) => c.name === sourceColumns[i].name);
1544
+ if (!localColumn) {
1545
+ throw new import_graphql4.GraphQLError(`WHERE ${relationName}: Relation cannot be used as a filter`);
1546
+ }
1547
+ correlationConditions.push((0, import_drizzle_orm3.eq)(localColumn, resolveJunctionColumn(aliasedThrough, through.source[i], relationName)));
1548
+ }
1549
+ const junctionJoinConditions = [];
1550
+ for (let i = 0; i < targetColumns.length; i++) {
1551
+ const foreignColumn = targetTableColumns.find((c) => c.name === targetColumns[i].name);
1552
+ if (!foreignColumn) {
1553
+ throw new import_graphql4.GraphQLError(`WHERE ${relationName}: Relation cannot be used as a filter`);
1554
+ }
1555
+ junctionJoinConditions.push(
1556
+ (0, import_drizzle_orm3.eq)(resolveJunctionColumn(aliasedThrough, through.target[i], relationName), foreignColumn)
1557
+ );
1558
+ }
1559
+ return {
1560
+ correlation: correlationConditions.length > 1 ? (0, import_drizzle_orm3.and)(...correlationConditions) : correlationConditions[0],
1561
+ junctionJoin: junctionJoinConditions.length > 1 ? (0, import_drizzle_orm3.and)(...junctionJoinConditions) : junctionJoinConditions[0]
1562
+ };
1563
+ };
1267
1564
  var buildRelationExists = (parentTable, relationName, relEntry, innerFilters, mode, ctx) => {
1268
1565
  const { targetTableName } = relEntry;
1269
1566
  const targetTable = ctx.tables[targetTableName];
1270
1567
  const relation = relEntry.relation ?? relEntry;
1271
- if (!targetTable || !isFilterableRelation(relation)) {
1568
+ if (!targetTable) {
1272
1569
  throw new import_graphql4.GraphQLError(`WHERE ${relationName}: Relation cannot be used as a filter`);
1273
1570
  }
1274
1571
  ctx.aliases ??= { n: 0 };
1275
1572
  const aliases = ctx.aliases;
1276
1573
  const aliasedTarget = (0, import_drizzle_orm3.aliasedTable)(targetTable, `dgql_rel_${aliases.n++}`);
1277
- const joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
1574
+ const throughTable = relation.throughTable;
1575
+ let fromClause;
1576
+ let joinCondition;
1577
+ if (throughTable) {
1578
+ const aliasedThrough = (0, import_drizzle_orm3.aliasedTable)(throughTable, `dgql_rel_${aliases.n++}`);
1579
+ const { correlation, junctionJoin } = buildThroughJoinConditions(
1580
+ parentTable,
1581
+ relation,
1582
+ aliasedThrough,
1583
+ aliasedTarget,
1584
+ relationName
1585
+ );
1586
+ fromClause = import_drizzle_orm3.sql`${(0, import_drizzle_orm3.getTableAsAliasSQL)(aliasedTarget)} inner join ${(0, import_drizzle_orm3.getTableAsAliasSQL)(aliasedThrough)} on ${junctionJoin}`;
1587
+ joinCondition = correlation;
1588
+ } else {
1589
+ fromClause = (0, import_drizzle_orm3.getTableAsAliasSQL)(aliasedTarget);
1590
+ joinCondition = buildRelationJoinCondition(parentTable, relation, aliasedTarget, relationName);
1591
+ }
1278
1592
  const relationWhere = relation.where ? (0, import_drizzle_orm3.relationsFilterToSQL)(relation.isReversed ? parentTable : aliasedTarget, relation.where) : void 0;
1279
1593
  const inner = innerFilters ? extractFilters(aliasedTarget, targetTableName, innerFilters, { ...ctx, tableKey: targetTableName, aliases }) : void 0;
1280
1594
  if (mode === "every") {
1281
1595
  if (!inner) {
1282
1596
  return void 0;
1283
1597
  }
1284
- return import_drizzle_orm3.sql`not exists (select 1 from ${(0, import_drizzle_orm3.getTableAsAliasSQL)(aliasedTarget)} where ${(0, import_drizzle_orm3.and)(joinCondition, relationWhere, (0, import_drizzle_orm3.not)(inner))})`;
1598
+ return import_drizzle_orm3.sql`not exists (select 1 from ${fromClause} where ${(0, import_drizzle_orm3.and)(joinCondition, relationWhere, (0, import_drizzle_orm3.not)(inner))})`;
1285
1599
  }
1286
1600
  const condition = (0, import_drizzle_orm3.and)(joinCondition, relationWhere, inner);
1287
- return mode === "none" ? import_drizzle_orm3.sql`not exists (select 1 from ${(0, import_drizzle_orm3.getTableAsAliasSQL)(aliasedTarget)} where ${condition})` : import_drizzle_orm3.sql`exists (select 1 from ${(0, import_drizzle_orm3.getTableAsAliasSQL)(aliasedTarget)} where ${condition})`;
1601
+ return mode === "none" ? import_drizzle_orm3.sql`not exists (select 1 from ${fromClause} where ${condition})` : import_drizzle_orm3.sql`exists (select 1 from ${fromClause} where ${condition})`;
1288
1602
  };
1289
1603
  var extractRelationFilter = (parentTable, relationName, relEntry, value, ctx) => {
1290
1604
  const relation = relEntry.relation ?? relEntry;
1291
1605
  if ((0, import_drizzle_orm3.is)(relation, import_drizzle_orm3.One)) {
1292
1606
  return buildRelationExists(parentTable, relationName, relEntry, value, "some", ctx);
1293
1607
  }
1608
+ const relationMatchModes = ["some", "none", "every"];
1294
1609
  const variants = [];
1295
- for (const mode of ["some", "none", "every"]) {
1296
- const inner = value[mode];
1610
+ for (const [mode, inner] of Object.entries(value)) {
1297
1611
  if (inner === void 0 || inner === null) {
1298
1612
  continue;
1299
1613
  }
1614
+ if (!relationMatchModes.includes(mode)) {
1615
+ throw new import_graphql4.GraphQLError(`WHERE ${relationName}: Unknown relation filter key: ${mode}`);
1616
+ }
1300
1617
  const extracted = buildRelationExists(parentTable, relationName, relEntry, inner, mode, ctx);
1301
1618
  if (extracted) {
1302
1619
  variants.push(extracted);
@@ -1305,26 +1622,8 @@ var extractRelationFilter = (parentTable, relationName, relEntry, value, ctx) =>
1305
1622
  return variants.length ? variants.length > 1 ? (0, import_drizzle_orm3.and)(...variants) : variants[0] : void 0;
1306
1623
  };
1307
1624
  var extractFilters = (table, tableName, filters, relationCtx) => {
1308
- if (!filters.OR?.length) {
1309
- delete filters.OR;
1310
- }
1311
- const entries = Object.entries(filters);
1312
- if (!entries.length) {
1313
- return;
1314
- }
1315
- if (filters.OR) {
1316
- if (entries.length > 1) {
1317
- throw new import_graphql4.GraphQLError(`WHERE ${tableName}: Cannot specify both fields and 'OR' in table filters!`);
1318
- }
1319
- const variants2 = [];
1320
- for (const variant of filters.OR) {
1321
- const extracted = extractFilters(table, tableName, variant, relationCtx);
1322
- if (extracted) {
1323
- variants2.push(extracted);
1324
- }
1325
- }
1326
- return variants2.length ? variants2.length > 1 ? (0, import_drizzle_orm3.or)(...variants2) : variants2[0] : void 0;
1327
- }
1625
+ const { OR, AND, NOT, ...fieldFilters } = filters;
1626
+ const entries = Object.entries(fieldFilters);
1328
1627
  const columns = (0, import_drizzle_orm3.getColumns)(table);
1329
1628
  const relations = relationCtx?.relationMap[relationCtx.tableKey];
1330
1629
  const variants = [];
@@ -1333,11 +1632,40 @@ var extractFilters = (table, tableName, filters, relationCtx) => {
1333
1632
  continue;
1334
1633
  }
1335
1634
  const column = columns[fieldName];
1336
- const extracted = column ? extractFiltersColumn(column, fieldName, operators) : relations?.[fieldName] && relationCtx ? extractRelationFilter(table, fieldName, relations[fieldName], operators, relationCtx) : void 0;
1635
+ if (!column && !(relations?.[fieldName] && relationCtx)) {
1636
+ throw new import_graphql4.GraphQLError(`WHERE ${tableName}: Unknown filter key: ${fieldName}`);
1637
+ }
1638
+ const extracted = column ? extractFiltersColumn(column, fieldName, operators) : extractRelationFilter(table, fieldName, relations[fieldName], operators, relationCtx);
1337
1639
  if (extracted) {
1338
1640
  variants.push(extracted);
1339
1641
  }
1340
1642
  }
1643
+ if (AND?.length) {
1644
+ for (const variant of AND) {
1645
+ const extracted = extractFilters(table, tableName, variant, relationCtx);
1646
+ if (extracted) {
1647
+ variants.push(extracted);
1648
+ }
1649
+ }
1650
+ }
1651
+ if (NOT) {
1652
+ const extracted = extractFilters(table, tableName, NOT, relationCtx);
1653
+ if (extracted) {
1654
+ variants.push((0, import_drizzle_orm3.not)(extracted));
1655
+ }
1656
+ }
1657
+ if (OR?.length) {
1658
+ const orVariants = [];
1659
+ for (const variant of OR) {
1660
+ const extracted = extractFilters(table, tableName, variant, relationCtx);
1661
+ if (extracted) {
1662
+ orVariants.push(extracted);
1663
+ }
1664
+ }
1665
+ if (orVariants.length) {
1666
+ variants.push(orVariants.length > 1 ? (0, import_drizzle_orm3.or)(...orVariants) : orVariants[0]);
1667
+ }
1668
+ }
1341
1669
  return variants.length ? variants.length > 1 ? (0, import_drizzle_orm3.and)(...variants) : variants[0] : void 0;
1342
1670
  };
1343
1671
  var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, originField, typeNameMapper, _isInitial = false, filterCtx) => {
@@ -1379,7 +1707,7 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
1379
1707
  } : void 0;
1380
1708
  const hasPagination = offset != null || limit != null;
1381
1709
  const pkNames = targetPkNames ?? [];
1382
- thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, relationArgs.orderBy) : hasPagination && pkNames.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0;
1710
+ thisRecord.orderBy = relationArgs?.orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, relationArgs.orderBy, relationFilterCtx(filterCtx, targetTableName)) : hasPagination && pkNames.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0;
1383
1711
  thisRecord.offset = offset;
1384
1712
  thisRecord.limit = limit;
1385
1713
  const relWith = relationField ? extractRelationsParamsInner(
@@ -1620,7 +1948,9 @@ var selectDistinctKeys = async (params) => {
1620
1948
  }
1621
1949
  const orderEntries = orderBy ? orderByEntries(orderBy) : [];
1622
1950
  const windowOrder = [
1623
- ...orderEntries.map(([column, direction]) => direction === "asc" ? (0, import_drizzle_orm3.asc)(cols[column]) : (0, import_drizzle_orm3.desc)(cols[column])),
1951
+ ...orderEntries.flatMap(
1952
+ ([column, direction, nulls]) => orderExpressions(cols[column], direction, nulls, cols[column])
1953
+ ),
1624
1954
  ...primaryKeyOrderExprs(table, pkNames)
1625
1955
  ];
1626
1956
  const rowNumber = import_drizzle_orm3.sql`row_number() over (partition by ${import_drizzle_orm3.sql.join(partitionCols, import_drizzle_orm3.sql`, `)} order by ${import_drizzle_orm3.sql.join(
@@ -1629,7 +1959,9 @@ var selectDistinctKeys = async (params) => {
1629
1959
  )})`.as(DISTINCT_RN);
1630
1960
  const sub = db.select({ ...cols, [DISTINCT_RN]: rowNumber }).from(table).where(where).as("__dgql_distinct");
1631
1961
  const outerOrder = [
1632
- ...orderEntries.map(([column, direction]) => direction === "asc" ? (0, import_drizzle_orm3.asc)(sub[column]) : (0, import_drizzle_orm3.desc)(sub[column])),
1962
+ ...orderEntries.flatMap(
1963
+ ([column, direction, nulls]) => orderExpressions(sub[column], direction, nulls, cols[column])
1964
+ ),
1633
1965
  ...pkNames.filter((name) => sub[name]).map((name) => (0, import_drizzle_orm3.asc)(sub[name]))
1634
1966
  ];
1635
1967
  let query = db.select(Object.fromEntries(pkNames.map((name) => [name, sub[name]]))).from(sub).where((0, import_drizzle_orm3.eq)(sub[DISTINCT_RN], 1)).orderBy(...outerOrder);
@@ -1728,6 +2060,9 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
1728
2060
  const upsertSingleFieldName = mapped ? `${upsertPrefix}${capitalize(mapped.singular)}` : `${upsertPrefix}${capitalize(tableName)}${suffixes.single}`;
1729
2061
  const updateFieldName = `${prefixes.update}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
1730
2062
  const deleteFieldName = `${prefixes.delete}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
2063
+ const writeSingleSuffix = suffixes.single === "" ? "Single" : suffixes.single;
2064
+ const updateSingleFieldName = `${updateFieldName}${writeSingleSuffix}`;
2065
+ const deleteSingleFieldName = `${deleteFieldName}${writeSingleSuffix}`;
1731
2066
  return {
1732
2067
  typeName,
1733
2068
  listFieldName,
@@ -1739,9 +2074,24 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
1739
2074
  upsertArrayFieldName,
1740
2075
  upsertSingleFieldName,
1741
2076
  updateFieldName,
1742
- deleteFieldName
2077
+ updateSingleFieldName,
2078
+ deleteFieldName,
2079
+ deleteSingleFieldName
1743
2080
  };
1744
2081
  };
2082
+ var extractRequiredFilters = (table, tableName, where, fieldName, relationCtx) => {
2083
+ const filters = where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2084
+ if (!filters) {
2085
+ throw new import_graphql4.GraphQLError(`${fieldName} requires a 'where' argument with at least one filter!`);
2086
+ }
2087
+ return filters;
2088
+ };
2089
+ var assertSingleMatch = async (executor, table, filters, fieldName) => {
2090
+ const matched = await executor.select({ found: import_drizzle_orm3.sql`1` }).from(table).where(filters).limit(2);
2091
+ if (matched.length > 1) {
2092
+ throw new import_graphql4.GraphQLError(`${fieldName}: 'where' matched more than one row \u2014 nothing was written!`);
2093
+ }
2094
+ };
1745
2095
  var selectArrayArgs = (orderArgs, filterArgs, distinctEnum) => ({
1746
2096
  offset: { type: import_graphql4.GraphQLInt },
1747
2097
  limit: { type: import_graphql4.GraphQLInt },
@@ -1800,9 +2150,9 @@ var runRelationalSelect = async (opts) => {
1800
2150
  // drizzle-orm v1 RQB calls orderBy/where with the aliased table proxy — use it
1801
2151
  // directly so column refs match the CTE alias.
1802
2152
  orderBy: distinctKeys ? (aliasedTable2) => [
1803
- ...orderBy ? extractOrderBy(aliasedTable2, orderBy) : [],
2153
+ ...orderBy ? extractOrderBy(aliasedTable2, orderBy, relationFilterCtx(filterCtx, tableName)) : [],
1804
2154
  ...primaryKeyOrderExprs(aliasedTable2, pkNames)
1805
- ] : orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, orderBy) : needsDefaultOrder && pkNames?.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0,
2155
+ ] : orderBy ? (aliasedTable2) => extractOrderBy(aliasedTable2, orderBy, relationFilterCtx(filterCtx, tableName)) : needsDefaultOrder && pkNames?.length ? (aliasedTable2) => primaryKeyOrderExprs(aliasedTable2, pkNames) : void 0,
1806
2156
  where: distinctKeys ? { RAW: (aliasedTable2) => primaryKeyRestriction(aliasedTable2, pkNames, distinctKeys) } : where ? {
1807
2157
  RAW: (aliasedTable2) => extractFilters(aliasedTable2, tableName, where, relationFilterCtx(filterCtx, tableName))
1808
2158
  } : void 0,
@@ -2493,13 +2843,13 @@ var generateUpsert = (db, table, baseType, onConflictType, fieldName, single) =>
2493
2843
  args: queryArgs
2494
2844
  };
2495
2845
  };
2496
- var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filterCtx) => {
2846
+ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, single, requireWhere, filterCtx) => {
2497
2847
  const queryArgs = {
2498
2848
  set: {
2499
2849
  type: new import_graphql6.GraphQLNonNull(setArgs)
2500
2850
  },
2501
2851
  where: {
2502
- type: filterArgs
2852
+ type: single || requireWhere ? new import_graphql6.GraphQLNonNull(filterArgs) : filterArgs
2503
2853
  }
2504
2854
  };
2505
2855
  return {
@@ -2511,10 +2861,14 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
2511
2861
  if (!Object.keys(input).length) {
2512
2862
  throw new import_graphql6.GraphQLError("Unable to update with no values specified!");
2513
2863
  }
2864
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
2865
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2514
2866
  const executor = resolveExecutor(db, context);
2867
+ if (single) {
2868
+ await assertSingleMatch(executor, table, filters, fieldName);
2869
+ }
2515
2870
  let query = executor.update(table).set(input);
2516
- if (where) {
2517
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
2871
+ if (filters) {
2518
2872
  query = query.where(filters);
2519
2873
  }
2520
2874
  await query;
@@ -2526,10 +2880,10 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
2526
2880
  args: queryArgs
2527
2881
  };
2528
2882
  };
2529
- var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) => {
2883
+ var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requireWhere, filterCtx) => {
2530
2884
  const queryArgs = {
2531
2885
  where: {
2532
- type: filterArgs
2886
+ type: single || requireWhere ? new import_graphql6.GraphQLNonNull(filterArgs) : filterArgs
2533
2887
  }
2534
2888
  };
2535
2889
  return {
@@ -2537,10 +2891,14 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) =>
2537
2891
  resolver: async (_source, args, context, _info) => {
2538
2892
  try {
2539
2893
  const { where } = args;
2894
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
2895
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2540
2896
  const executor = resolveExecutor(db, context);
2897
+ if (single) {
2898
+ await assertSingleMatch(executor, table, filters, fieldName);
2899
+ }
2541
2900
  let query = executor.delete(table);
2542
- if (where) {
2543
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
2901
+ if (filters) {
2544
2902
  query = query.where(filters);
2545
2903
  }
2546
2904
  await query;
@@ -2629,7 +2987,9 @@ var generateSchemaData = (db, schema, relations, options) => {
2629
2987
  upsertArrayFieldName,
2630
2988
  upsertSingleFieldName,
2631
2989
  updateFieldName,
2632
- deleteFieldName
2990
+ updateSingleFieldName,
2991
+ deleteFieldName,
2992
+ deleteSingleFieldName
2633
2993
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
2634
2994
  const selectArrGenerated = generateSelectArray(
2635
2995
  db,
@@ -2674,9 +3034,41 @@ var generateSchemaData = (db, schema, relations, options) => {
2674
3034
  updateInput,
2675
3035
  tableFilters,
2676
3036
  updateFieldName,
3037
+ false,
3038
+ features.requireWhere,
3039
+ filterCtx
3040
+ ) : void 0;
3041
+ const updateSingleGenerated = features.update ? generateUpdate(
3042
+ db,
3043
+ tableName,
3044
+ schema[tableName],
3045
+ updateInput,
3046
+ tableFilters,
3047
+ updateSingleFieldName,
3048
+ true,
3049
+ features.requireWhere,
3050
+ filterCtx
3051
+ ) : void 0;
3052
+ const deleteGenerated = features.delete ? generateDelete(
3053
+ db,
3054
+ tableName,
3055
+ schema[tableName],
3056
+ tableFilters,
3057
+ deleteFieldName,
3058
+ false,
3059
+ features.requireWhere,
3060
+ filterCtx
3061
+ ) : void 0;
3062
+ const deleteSingleGenerated = features.delete ? generateDelete(
3063
+ db,
3064
+ tableName,
3065
+ schema[tableName],
3066
+ tableFilters,
3067
+ deleteSingleFieldName,
3068
+ true,
3069
+ features.requireWhere,
2677
3070
  filterCtx
2678
3071
  ) : void 0;
2679
- const deleteGenerated = features.delete ? generateDelete(db, tableName, schema[tableName], tableFilters, deleteFieldName, filterCtx) : void 0;
2680
3072
  const aggregateType = features.aggregates ? generateAggregateTypes(schema[tableName], tableName, typeName, cacheCtx) : void 0;
2681
3073
  const aggregateGenerated = features.aggregates ? generateAggregate(
2682
3074
  db,
@@ -2734,7 +3126,9 @@ var generateSchemaData = (db, schema, relations, options) => {
2734
3126
  upsertArrGenerated,
2735
3127
  upsertSingleGenerated,
2736
3128
  updateGenerated,
2737
- deleteGenerated
3129
+ updateSingleGenerated,
3130
+ deleteGenerated,
3131
+ deleteSingleGenerated
2738
3132
  ]) {
2739
3133
  if (generated) {
2740
3134
  mutations[generated.name] = {
@@ -2850,7 +3244,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
2850
3244
  }
2851
3245
  if (orderBy) {
2852
3246
  q = q.orderBy(
2853
- ...extractOrderBy(table, orderBy),
3247
+ ...extractOrderBy(table, orderBy, relationFilterCtx(filterCtx, tableName)),
2854
3248
  ...distinctKeys ? primaryKeyOrderExprs(table, pkNames) : []
2855
3249
  );
2856
3250
  } else if ((distinctKeys || offset != null || limit != null) && pkNames.length) {
@@ -2911,7 +3305,7 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
2911
3305
  q = q.where(extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)));
2912
3306
  }
2913
3307
  if (orderBy) {
2914
- q = q.orderBy(...extractOrderBy(table, orderBy));
3308
+ q = q.orderBy(...extractOrderBy(table, orderBy, relationFilterCtx(filterCtx, tableName)));
2915
3309
  } else if (pkNames.length) {
2916
3310
  q = q.orderBy(...primaryKeyOrderExprs(table, pkNames));
2917
3311
  }
@@ -3071,13 +3465,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
3071
3465
  args: queryArgs
3072
3466
  };
3073
3467
  };
3074
- var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
3468
+ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx) => {
3075
3469
  const queryArgs = {
3076
3470
  set: {
3077
3471
  type: new import_graphql7.GraphQLNonNull(setArgs)
3078
3472
  },
3079
3473
  where: {
3080
- type: filterArgs
3474
+ type: single || requireWhere ? new import_graphql7.GraphQLNonNull(filterArgs) : filterArgs
3081
3475
  }
3082
3476
  };
3083
3477
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -3103,16 +3497,26 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
3103
3497
  if (!Object.keys(input).length) {
3104
3498
  throw new import_graphql7.GraphQLError("Unable to update with no values specified!");
3105
3499
  }
3500
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
3501
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
3106
3502
  const executor = resolveExecutor(db, context);
3503
+ if (single) {
3504
+ await assertSingleMatch(executor, table, filters, fieldName);
3505
+ }
3107
3506
  let query = executor.update(table).set(input);
3108
- if (where) {
3109
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
3507
+ if (filters) {
3110
3508
  query = query.where(filters);
3111
3509
  }
3112
3510
  query = query.returning(columns);
3113
3511
  const result = await query;
3512
+ if (single && result.length > 1) {
3513
+ throw new import_graphql7.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
3514
+ }
3515
+ if (single && !result[0]) {
3516
+ return void 0;
3517
+ }
3114
3518
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
3115
- return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
3519
+ return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
3116
3520
  } catch (e) {
3117
3521
  throw toGraphQLError(e);
3118
3522
  }
@@ -3120,10 +3524,10 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
3120
3524
  args: queryArgs
3121
3525
  };
3122
3526
  };
3123
- var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
3527
+ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
3124
3528
  const queryArgs = {
3125
3529
  where: {
3126
- type: filterArgs
3530
+ type: single || requireWhere ? new import_graphql7.GraphQLNonNull(filterArgs) : filterArgs
3127
3531
  }
3128
3532
  };
3129
3533
  return {
@@ -3139,14 +3543,24 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, fi
3139
3543
  table,
3140
3544
  selectionCtx
3141
3545
  );
3546
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
3547
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
3142
3548
  const executor = resolveExecutor(db, context);
3549
+ if (single) {
3550
+ await assertSingleMatch(executor, table, filters, fieldName);
3551
+ }
3143
3552
  let query = executor.delete(table);
3144
- if (where) {
3145
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
3553
+ if (filters) {
3146
3554
  query = query.where(filters);
3147
3555
  }
3148
3556
  query = query.returning(columns);
3149
3557
  const result = await query;
3558
+ if (single && result.length > 1) {
3559
+ throw new import_graphql7.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
3560
+ }
3561
+ if (single) {
3562
+ return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
3563
+ }
3150
3564
  return remapToGraphQLArrayOutput(result, tableName, table);
3151
3565
  } catch (e) {
3152
3566
  throw toGraphQLError(e);
@@ -3228,7 +3642,9 @@ function generateSchemaData2(db, schema, relations, options) {
3228
3642
  upsertArrayFieldName,
3229
3643
  upsertSingleFieldName,
3230
3644
  updateFieldName,
3231
- deleteFieldName
3645
+ updateSingleFieldName,
3646
+ deleteFieldName,
3647
+ deleteSingleFieldName
3232
3648
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
3233
3649
  const selectArrGenerated = generateSelectArray2(
3234
3650
  db,
@@ -3327,6 +3743,23 @@ function generateSchemaData2(db, schema, relations, options) {
3327
3743
  tableFilters,
3328
3744
  updateFieldName,
3329
3745
  typeName,
3746
+ false,
3747
+ features.requireWhere,
3748
+ typeNameMapper,
3749
+ filterCtx
3750
+ ) : void 0;
3751
+ const updateSingleGenerated = features.update ? generateUpdate2(
3752
+ db,
3753
+ tableName,
3754
+ schema[tableName],
3755
+ tables,
3756
+ eagerRelations,
3757
+ updateInput,
3758
+ tableFilters,
3759
+ updateSingleFieldName,
3760
+ typeName,
3761
+ true,
3762
+ features.requireWhere,
3330
3763
  typeNameMapper,
3331
3764
  filterCtx
3332
3765
  ) : void 0;
@@ -3337,6 +3770,20 @@ function generateSchemaData2(db, schema, relations, options) {
3337
3770
  tableFilters,
3338
3771
  deleteFieldName,
3339
3772
  typeName,
3773
+ false,
3774
+ features.requireWhere,
3775
+ filterCtx,
3776
+ { tableName, relationMap: namedRelations, tables }
3777
+ ) : void 0;
3778
+ const deleteSingleGenerated = features.delete ? generateDelete2(
3779
+ db,
3780
+ tableName,
3781
+ schema[tableName],
3782
+ tableFilters,
3783
+ deleteSingleFieldName,
3784
+ typeName,
3785
+ true,
3786
+ features.requireWhere,
3340
3787
  filterCtx,
3341
3788
  { tableName, relationMap: namedRelations, tables }
3342
3789
  ) : void 0;
@@ -3426,6 +3873,13 @@ function generateSchemaData2(db, schema, relations, options) {
3426
3873
  resolve: updateGenerated.resolver
3427
3874
  };
3428
3875
  }
3876
+ if (updateSingleGenerated) {
3877
+ mutations[updateSingleGenerated.name] = {
3878
+ type: singleTableItemOutput,
3879
+ args: updateSingleGenerated.args,
3880
+ resolve: updateSingleGenerated.resolver
3881
+ };
3882
+ }
3429
3883
  if (deleteGenerated) {
3430
3884
  mutations[deleteGenerated.name] = {
3431
3885
  type: arrTableItemOutput,
@@ -3433,6 +3887,13 @@ function generateSchemaData2(db, schema, relations, options) {
3433
3887
  resolve: deleteGenerated.resolver
3434
3888
  };
3435
3889
  }
3890
+ if (deleteSingleGenerated) {
3891
+ mutations[deleteSingleGenerated.name] = {
3892
+ type: singleTableItemOutput,
3893
+ args: deleteSingleGenerated.args,
3894
+ resolve: deleteSingleGenerated.resolver
3895
+ };
3896
+ }
3436
3897
  const activeInputs = [
3437
3898
  // The insert input types the upsert mutations too, so either feature keeps it.
3438
3899
  ...features.insert || onConflictInput ? [insertInput] : [],
@@ -3699,13 +4160,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
3699
4160
  args: queryArgs
3700
4161
  };
3701
4162
  };
3702
- var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx) => {
4163
+ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx) => {
3703
4164
  const queryArgs = {
3704
4165
  set: {
3705
4166
  type: new import_graphql8.GraphQLNonNull(setArgs)
3706
4167
  },
3707
4168
  where: {
3708
- type: filterArgs
4169
+ type: single || requireWhere ? new import_graphql8.GraphQLNonNull(filterArgs) : filterArgs
3709
4170
  }
3710
4171
  };
3711
4172
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -3731,16 +4192,26 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
3731
4192
  if (!Object.keys(input).length) {
3732
4193
  throw new import_graphql8.GraphQLError("Unable to update with no values specified!");
3733
4194
  }
4195
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
4196
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
3734
4197
  const executor = resolveExecutor(db, context);
4198
+ if (single) {
4199
+ await assertSingleMatch(executor, table, filters, fieldName);
4200
+ }
3735
4201
  let query = executor.update(table).set(input);
3736
- if (where) {
3737
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
4202
+ if (filters) {
3738
4203
  query = query.where(filters);
3739
4204
  }
3740
4205
  query = query.returning(columns);
3741
4206
  const result = await query;
4207
+ if (single && result.length > 1) {
4208
+ throw new import_graphql8.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
4209
+ }
4210
+ if (single && !result[0]) {
4211
+ return void 0;
4212
+ }
3742
4213
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
3743
- return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
4214
+ return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
3744
4215
  } catch (e) {
3745
4216
  throw toGraphQLError(e);
3746
4217
  }
@@ -3748,10 +4219,10 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
3748
4219
  args: queryArgs
3749
4220
  };
3750
4221
  };
3751
- var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, filterCtx, selectionCtx) => {
4222
+ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
3752
4223
  const queryArgs = {
3753
4224
  where: {
3754
- type: filterArgs
4225
+ type: single || requireWhere ? new import_graphql8.GraphQLNonNull(filterArgs) : filterArgs
3755
4226
  }
3756
4227
  };
3757
4228
  return {
@@ -3767,14 +4238,24 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, fi
3767
4238
  table,
3768
4239
  selectionCtx
3769
4240
  );
4241
+ const relationCtx = relationFilterCtx(filterCtx, tableName);
4242
+ const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
3770
4243
  const executor = resolveExecutor(db, context);
4244
+ if (single) {
4245
+ await assertSingleMatch(executor, table, filters, fieldName);
4246
+ }
3771
4247
  let query = executor.delete(table);
3772
- if (where) {
3773
- const filters = extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName));
4248
+ if (filters) {
3774
4249
  query = query.where(filters);
3775
4250
  }
3776
4251
  query = query.returning(columns);
3777
4252
  const result = await query;
4253
+ if (single && result.length > 1) {
4254
+ throw new import_graphql8.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
4255
+ }
4256
+ if (single) {
4257
+ return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
4258
+ }
3778
4259
  return remapToGraphQLArrayOutput(result, tableName, table);
3779
4260
  } catch (e) {
3780
4261
  throw toGraphQLError(e);
@@ -3857,7 +4338,9 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3857
4338
  upsertArrayFieldName,
3858
4339
  upsertSingleFieldName,
3859
4340
  updateFieldName,
3860
- deleteFieldName
4341
+ updateSingleFieldName,
4342
+ deleteFieldName,
4343
+ deleteSingleFieldName
3861
4344
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
3862
4345
  const selectArrGenerated = generateSelectArray3(
3863
4346
  db,
@@ -3956,6 +4439,23 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3956
4439
  tableFilters,
3957
4440
  updateFieldName,
3958
4441
  typeName,
4442
+ false,
4443
+ features.requireWhere,
4444
+ typeNameMapper,
4445
+ filterCtx
4446
+ ) : void 0;
4447
+ const updateSingleGenerated = features.update ? generateUpdate3(
4448
+ db,
4449
+ tableName,
4450
+ schema[tableName],
4451
+ tables,
4452
+ eagerRelations,
4453
+ updateInput,
4454
+ tableFilters,
4455
+ updateSingleFieldName,
4456
+ typeName,
4457
+ true,
4458
+ features.requireWhere,
3959
4459
  typeNameMapper,
3960
4460
  filterCtx
3961
4461
  ) : void 0;
@@ -3966,6 +4466,20 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3966
4466
  tableFilters,
3967
4467
  deleteFieldName,
3968
4468
  typeName,
4469
+ false,
4470
+ features.requireWhere,
4471
+ filterCtx,
4472
+ { tableName, relationMap: namedRelations, tables }
4473
+ ) : void 0;
4474
+ const deleteSingleGenerated = features.delete ? generateDelete3(
4475
+ db,
4476
+ tableName,
4477
+ schema[tableName],
4478
+ tableFilters,
4479
+ deleteSingleFieldName,
4480
+ typeName,
4481
+ true,
4482
+ features.requireWhere,
3969
4483
  filterCtx,
3970
4484
  { tableName, relationMap: namedRelations, tables }
3971
4485
  ) : void 0;
@@ -4055,6 +4569,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
4055
4569
  resolve: updateGenerated.resolver
4056
4570
  };
4057
4571
  }
4572
+ if (updateSingleGenerated) {
4573
+ mutations[updateSingleGenerated.name] = {
4574
+ type: singleTableItemOutput,
4575
+ args: updateSingleGenerated.args,
4576
+ resolve: updateSingleGenerated.resolver
4577
+ };
4578
+ }
4058
4579
  if (deleteGenerated) {
4059
4580
  mutations[deleteGenerated.name] = {
4060
4581
  type: arrTableItemOutput,
@@ -4062,6 +4583,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
4062
4583
  resolve: deleteGenerated.resolver
4063
4584
  };
4064
4585
  }
4586
+ if (deleteSingleGenerated) {
4587
+ mutations[deleteSingleGenerated.name] = {
4588
+ type: singleTableItemOutput,
4589
+ args: deleteSingleGenerated.args,
4590
+ resolve: deleteSingleGenerated.resolver
4591
+ };
4592
+ }
4065
4593
  const activeInputs = [
4066
4594
  // The insert input types the upsert mutations too, so either feature keeps it.
4067
4595
  ...features.insert || onConflictInput ? [insertInput] : [],
@@ -4130,7 +4658,8 @@ var buildSchema = (db, config) => {
4130
4658
  insert: config?.features?.insert ?? true,
4131
4659
  update: config?.features?.update ?? true,
4132
4660
  delete: config?.features?.delete ?? true,
4133
- upsert: config?.features?.upsert ?? false
4661
+ upsert: config?.features?.upsert ?? false,
4662
+ requireWhere: config?.features?.requireWhere ?? false
4134
4663
  };
4135
4664
  const complexityConfig = config?.complexity ?? true;
4136
4665
  const complexity = complexityConfig === false ? void 0 : {
@@ -4204,6 +4733,7 @@ var buildSchema = (db, config) => {
4204
4733
  GraphQLBigIntString,
4205
4734
  GraphQLDate,
4206
4735
  GraphQLDateTime,
4736
+ GraphQLDecimalString,
4207
4737
  GraphQLJSON,
4208
4738
  GraphQLUUID,
4209
4739
  buildSchema,