@vantreeseba/drizzle-graphql 5.6.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -40,6 +40,63 @@ type ColumnTypeMapperInfo = {
40
40
  * the built-in detection.
41
41
  */
42
42
  type ColumnTypeMapper = (column: Column, info: ColumnTypeMapperInfo) => ScalarOverride | undefined;
43
+ /** Everything an {@link EnumNameMapper} needs to name — or opt a column out of — a generated enum type. */
44
+ type EnumNameInfo = {
45
+ /**
46
+ * The name the enum type was declared with (`pgEnum('status', …)`), shared by every column
47
+ * that uses it. `undefined` for an inline value list (`text({ enum: [...] })`,
48
+ * `mysqlEnum(...)`), which belongs to the one column that declares it.
49
+ */
50
+ enumName: string | undefined;
51
+ /** The Postgres schema the named enum was declared in, when it declares one. */
52
+ schema: string | undefined;
53
+ /** The table's key in the Drizzle schema object. */
54
+ tableName: string;
55
+ /** The column's property name on the table object. */
56
+ columnName: string;
57
+ /** The enum's values, in declaration order. */
58
+ values: readonly string[];
59
+ };
60
+ /**
61
+ * Names a generated GraphQL enum type. Return `undefined` to keep the default name. See
62
+ * `BuildSchemaConfig.enumNameMapper`.
63
+ */
64
+ type EnumNameMapper = (info: EnumNameInfo) => string | undefined;
65
+ /** Context handed to the documentation and deprecation hooks alongside the column itself. */
66
+ type ColumnDocInfo = {
67
+ /** The table's key in the Drizzle schema object. */
68
+ tableName: string;
69
+ /** The column's property name on the table object. */
70
+ columnName: string;
71
+ };
72
+ /**
73
+ * Supplies the GraphQL `description` for a generated column field. See
74
+ * `BuildSchemaConfig.describeColumn`.
75
+ */
76
+ type ColumnDescriber = (column: Column, info: ColumnDocInfo) => string | undefined;
77
+ /**
78
+ * Supplies the GraphQL `deprecationReason` for a generated column field. See
79
+ * `BuildSchemaConfig.deprecateColumn`.
80
+ */
81
+ type ColumnDeprecator = (column: Column, info: ColumnDocInfo) => string | undefined;
82
+ /** Supplies the GraphQL `description` for a table's object type. See `BuildSchemaConfig.describeTable`. */
83
+ type TableDescriber = (tableName: string) => string | undefined;
84
+ /**
85
+ * Supplies the GraphQL `description` for a relation field. See
86
+ * `BuildSchemaConfig.describeRelation`.
87
+ */
88
+ type RelationDescriber = (tableName: string, relationName: string) => string | undefined;
89
+ /**
90
+ * The documentation hooks a build was configured with, resolved once and threaded through
91
+ * type generation. Every member is optional; a build with no hooks generates fields with no
92
+ * descriptions at all.
93
+ */
94
+ type SchemaDocs = {
95
+ describeColumn?: ColumnDescriber;
96
+ describeTable?: TableDescriber;
97
+ describeRelation?: RelationDescriber;
98
+ deprecateColumn?: ColumnDeprecator;
99
+ };
43
100
 
44
101
  type TableNamedRelations = {
45
102
  relation: Relation;
@@ -175,8 +232,14 @@ declare const drizzleExecutorKey: unique symbol;
175
232
  * 2. When limit/offset args are present, falls back to a direct per-item query.
176
233
  * 3. Otherwise batches all sibling resolver calls within the same GraphQL execution tick
177
234
  * into a single IN-clause query, eliminating N+1 database round-trips.
235
+ *
236
+ * `nullOrdering` is the dialect's native `ORDER BY` placement for `NULL` — the keyset
237
+ * predicate behind a relation's `after` argument has to match it, or rows with a `NULL` in an
238
+ * ordered column would be skipped instead of paged through. It has no sensible default, so
239
+ * each dialect builder states it: `'nulls-largest'` for PostgreSQL, `'nulls-smallest'` for
240
+ * MySQL and SQLite.
178
241
  */
179
- declare const createRelationResolverFactory: (db: any, tables: Record<string, Table>, filterCtx?: RelationFilterBase) => RelationResolverFactory;
242
+ declare const createRelationResolverFactory: (db: any, tables: Record<string, Table>, nullOrdering: NullOrdering, filterCtx?: RelationFilterBase) => RelationResolverFactory;
180
243
  /**
181
244
  * Compiles an `orderBy` argument into ORDER BY expressions, highest priority first.
182
245
  *
@@ -218,6 +281,14 @@ interface RelationFilterContext {
218
281
  */
219
282
  type RelationFilterBase = Pick<RelationFilterContext, 'tables' | 'relationMap'>;
220
283
  declare const extractFilters: <TTable extends Table>(table: TTable, tableName: string, filters: Filters<TTable>, relationCtx?: RelationFilterContext) => SQL | undefined;
284
+ /**
285
+ * Where a dialect's default sort places NULLs relative to non-NULL values:
286
+ * - `nulls-largest` — PostgreSQL: NULLs sort as the largest values (last in ASC, first in DESC).
287
+ * - `nulls-smallest` — MySQL and SQLite: NULLs sort as the smallest values (first in ASC, last
288
+ * in DESC).
289
+ * The keyset predicate has to agree with the dialect's ORDER BY, so each builder passes its own.
290
+ */
291
+ type NullOrdering = 'nulls-largest' | 'nulls-smallest';
221
292
  /**
222
293
  * Default for `config.onError`: keeps drizzle-graphql's own errors, which are written for
223
294
  * the client, and replaces driver/database errors with a generic message. Their text names
@@ -580,6 +651,83 @@ type SchemaFeatures = {
580
651
  * @default false
581
652
  */
582
653
  upsert?: boolean;
654
+ /**
655
+ * Relation fields on `Create<Table>Input` and `Update<Table>Input`, so a parent row and
656
+ * the rows it is related to can be written in one mutation. Off unless asked for: it adds
657
+ * a field per writable relation to every create and update input.
658
+ *
659
+ * ```graphql
660
+ * createPostsSingle(values: {
661
+ * title: "Hello"
662
+ * author: { connect: { id: { eq: "a1" } } }
663
+ * tags: { create: [{ name: "drizzle" }] }
664
+ * }) { id }
665
+ * ```
666
+ *
667
+ * Each relation field offers `create` and `connect`; the update input adds `disconnect`
668
+ * and, for a to-many relation, `set` (replace the whole set). `disconnect` and `set` are
669
+ * generated only when the foreign key is nullable — there is no way to detach a row whose
670
+ * key is NOT NULL — and many-to-many (`.through()`) relations are not written through at
671
+ * all. Nesting is one level deep: the row a nested `create` inserts takes columns only.
672
+ *
673
+ * The whole tree runs in one transaction (a savepoint when the request already carries
674
+ * one), and a column a relation fills in (`authorId`, when `author: { create: … }` is
675
+ * offered) becomes nullable on the create input, since the relation is the other way to
676
+ * supply it.
677
+ *
678
+ * PostgreSQL and SQLite only. MySQL cannot return the rows it just wrote, which is how a
679
+ * nested write learns the parent's key, so `buildSchema` rejects the flag there. On SQLite
680
+ * the driver must be asynchronous (libsql, D1, …): a synchronous one commits before an
681
+ * awaited statement runs, so `buildSchema` rejects the combination outright.
682
+ *
683
+ * @default false
684
+ */
685
+ nestedWrites?: boolean;
686
+ /**
687
+ * Operation inputs on the update `set`, so a column can be changed relative to its current
688
+ * value instead of only replaced.
689
+ *
690
+ * ```graphql
691
+ * updatePostsSingle(where: { id: { eq: "p1" } }, set: { views: { increment: 1 } }) { views }
692
+ * ```
693
+ *
694
+ * Every numeric column's field on `Update<Table>Input` becomes a `<Scalar>FieldUpdate`
695
+ * input carrying `set`, `increment`, `decrement`, `multiply` and `divide`; every array
696
+ * column's becomes a `<Scalar>ListFieldUpdate` carrying `set` and `push`. Exactly one
697
+ * operation per field, checked at resolve time. `set` is the explicit spelling of what the
698
+ * field did before, so `set: { views: 42 }` becomes `set: { views: { set: 42 } }`.
699
+ *
700
+ * The arithmetic happens in the database (`SET views = views + 1`), so a counter no longer
701
+ * needs a read-modify-write round trip and no longer loses concurrent updates. Rounding on
702
+ * an integer column, and division by zero, follow the database's own rules rather than
703
+ * being guarded here. Columns owned by a scalar override keep their plain type — an
704
+ * override owns what the column accepts.
705
+ *
706
+ * Off by default: it changes the type of every numeric and array field on every update
707
+ * input, which no existing document is written against.
708
+ *
709
+ * @default false
710
+ */
711
+ fieldUpdateOperations?: boolean;
712
+ /**
713
+ * `update<Table>Count` / `delete<Table>Count` mutations — the same write as the plural
714
+ * `update<Table>` / `delete<Table>`, returning the number of rows affected instead of the
715
+ * rows themselves.
716
+ *
717
+ * ```graphql
718
+ * deletePostsCount(where: { published: { eq: false } }) # Int!
719
+ * ```
720
+ *
721
+ * A mass update or delete otherwise has to `RETURNING *` every row it touched purely so
722
+ * the caller can count them, which crosses the driver and is serialized through GraphQL
723
+ * for nothing. Each mutation is generated only when its plural counterpart is
724
+ * (`features.update` / `features.delete`), and honours `features.requireWhere`.
725
+ *
726
+ * Off unless asked for, so an existing schema does not grow new mutations on upgrade.
727
+ *
728
+ * @default false
729
+ */
730
+ countMutations?: boolean;
583
731
  /**
584
732
  * Makes `where` non-null on the plural `update<Table>` / `delete<Table>` mutations, and
585
733
  * rejects a `where` that collapses to no filters (e.g. `where: {}`), so a schema can rule
@@ -884,6 +1032,94 @@ type BuildSchemaConfig = {
884
1032
  * ```
885
1033
  */
886
1034
  onError?: (error: unknown) => unknown;
1035
+ /**
1036
+ * Supplies the GraphQL `description` for a column, everywhere that column becomes a field:
1037
+ * the object type, the create/update inputs, the filter input, and the aggregate
1038
+ * `min`/`max`/`group` fields.
1039
+ *
1040
+ * Nothing is generated by default. The library used to emit the column's own type name
1041
+ * ("DateTime", "JSON") as its description, which documented nothing a reader could not see
1042
+ * from the type — that is gone, and this hook is what puts real prose in its place. Drizzle
1043
+ * carries no column-comment metadata to read, so the text has to come from here.
1044
+ *
1045
+ * ```ts
1046
+ * const columnDocs = { Users: { email: 'Primary contact address. Unique, case-insensitive.' } };
1047
+ *
1048
+ * buildSchema(db, {
1049
+ * describeColumn: (_column, { tableName, columnName }) => columnDocs[tableName]?.[columnName],
1050
+ * });
1051
+ * ```
1052
+ *
1053
+ * `tableName` and `columnName` are the Drizzle schema keys. Return `undefined` to leave the
1054
+ * field undocumented.
1055
+ */
1056
+ describeColumn?: ColumnDescriber;
1057
+ /**
1058
+ * Supplies the GraphQL `description` for a table's object type.
1059
+ *
1060
+ * ```ts
1061
+ * buildSchema(db, { describeTable: (tableName) => tableDocs[tableName] });
1062
+ * ```
1063
+ */
1064
+ describeTable?: TableDescriber;
1065
+ /**
1066
+ * Supplies the GraphQL `description` for a relation field on a table's object type.
1067
+ *
1068
+ * ```ts
1069
+ * buildSchema(db, {
1070
+ * describeRelation: (tableName, relationName) =>
1071
+ * tableName === 'Users' && relationName === 'posts' ? 'Posts this user authored.' : undefined,
1072
+ * });
1073
+ * ```
1074
+ *
1075
+ * The generated `<relation>Aggregate` companion fields are not covered — they are derived
1076
+ * fields rather than the relation itself.
1077
+ */
1078
+ describeRelation?: RelationDescriber;
1079
+ /**
1080
+ * Supplies the GraphQL `deprecationReason` for a column, marking it `@deprecated` on the
1081
+ * object type and on the create/update inputs.
1082
+ *
1083
+ * ```ts
1084
+ * buildSchema(db, {
1085
+ * deprecateColumn: (_column, { columnName }) =>
1086
+ * columnName === 'legacyFlag' ? 'Use `status` instead.' : undefined,
1087
+ * });
1088
+ * ```
1089
+ *
1090
+ * A required input field cannot be deprecated — GraphQL rejects the schema, since a client
1091
+ * has no way to stop sending it — so the reason is dropped on non-null input fields and
1092
+ * kept everywhere else. Filter and orderBy fields are never deprecated either: filtering on
1093
+ * a deprecated column is how a caller finds the rows that still use it.
1094
+ */
1095
+ deprecateColumn?: ColumnDeprecator;
1096
+ /**
1097
+ * Names the GraphQL enum types generated for enum columns.
1098
+ *
1099
+ * By default a column declared with a named `pgEnum` gets one shared type named after the
1100
+ * enum (`pgEnum('status', …)` → `StatusEnum`), reused by every column declared with that
1101
+ * same `pgEnum` — the database column is the same type, so a client variable typed
1102
+ * `StatusEnum!` is passable to any of them. A column with an inline value list
1103
+ * (`text({ enum: [...] })`, `mysqlEnum(...)`) keeps a per-column type named for its table
1104
+ * and column (`UsersRoleTextEnum`), because its values are shared with nothing.
1105
+ *
1106
+ * This hook overrides the name either way — for lining the schema up with another schema it
1107
+ * is stitched into, or for opting a specific column back into a type of its own:
1108
+ *
1109
+ * ```ts
1110
+ * buildSchema(db, {
1111
+ * enumNameMapper: (info) => (info.enumName === 'status' ? 'PublicationStatus' : undefined),
1112
+ * });
1113
+ * ```
1114
+ *
1115
+ * Two columns the mapper sends to the same name share one type when their values match —
1116
+ * the way to unify inline enums declared separately that mean the same thing. Sending two
1117
+ * *different* value lists to one name throws at build time rather than producing an
1118
+ * invalid schema.
1119
+ *
1120
+ * Return `undefined` to keep the default name.
1121
+ */
1122
+ enumNameMapper?: EnumNameMapper;
887
1123
  };
888
1124
 
889
1125
  /**
@@ -903,4 +1139,4 @@ declare const GraphQLDecimalString: GraphQLScalarType<string, string>;
903
1139
 
904
1140
  declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
905
1141
 
906
- export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ColumnTypeMapper, type ColumnTypeMapperInfo, type ComplexityConfig, type DeleteResolver, type DeleteSingleResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, GraphQLDecimalString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type ScalarOverride, type ScalarOverridesConfig, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
1142
+ export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ColumnDeprecator, type ColumnDescriber, type ColumnDocInfo, type ColumnTypeMapper, type ColumnTypeMapperInfo, type ComplexityConfig, type DeleteResolver, type DeleteSingleResolver, type EnumNameInfo, type EnumNameMapper, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, GraphQLDecimalString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationDescriber, type RelationResolverFactory, type ScalarOverride, type ScalarOverridesConfig, type SchemaDocs, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableDescriber, type TableNamedRelations, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
package/dist/index.d.ts CHANGED
@@ -40,6 +40,63 @@ type ColumnTypeMapperInfo = {
40
40
  * the built-in detection.
41
41
  */
42
42
  type ColumnTypeMapper = (column: Column, info: ColumnTypeMapperInfo) => ScalarOverride | undefined;
43
+ /** Everything an {@link EnumNameMapper} needs to name — or opt a column out of — a generated enum type. */
44
+ type EnumNameInfo = {
45
+ /**
46
+ * The name the enum type was declared with (`pgEnum('status', …)`), shared by every column
47
+ * that uses it. `undefined` for an inline value list (`text({ enum: [...] })`,
48
+ * `mysqlEnum(...)`), which belongs to the one column that declares it.
49
+ */
50
+ enumName: string | undefined;
51
+ /** The Postgres schema the named enum was declared in, when it declares one. */
52
+ schema: string | undefined;
53
+ /** The table's key in the Drizzle schema object. */
54
+ tableName: string;
55
+ /** The column's property name on the table object. */
56
+ columnName: string;
57
+ /** The enum's values, in declaration order. */
58
+ values: readonly string[];
59
+ };
60
+ /**
61
+ * Names a generated GraphQL enum type. Return `undefined` to keep the default name. See
62
+ * `BuildSchemaConfig.enumNameMapper`.
63
+ */
64
+ type EnumNameMapper = (info: EnumNameInfo) => string | undefined;
65
+ /** Context handed to the documentation and deprecation hooks alongside the column itself. */
66
+ type ColumnDocInfo = {
67
+ /** The table's key in the Drizzle schema object. */
68
+ tableName: string;
69
+ /** The column's property name on the table object. */
70
+ columnName: string;
71
+ };
72
+ /**
73
+ * Supplies the GraphQL `description` for a generated column field. See
74
+ * `BuildSchemaConfig.describeColumn`.
75
+ */
76
+ type ColumnDescriber = (column: Column, info: ColumnDocInfo) => string | undefined;
77
+ /**
78
+ * Supplies the GraphQL `deprecationReason` for a generated column field. See
79
+ * `BuildSchemaConfig.deprecateColumn`.
80
+ */
81
+ type ColumnDeprecator = (column: Column, info: ColumnDocInfo) => string | undefined;
82
+ /** Supplies the GraphQL `description` for a table's object type. See `BuildSchemaConfig.describeTable`. */
83
+ type TableDescriber = (tableName: string) => string | undefined;
84
+ /**
85
+ * Supplies the GraphQL `description` for a relation field. See
86
+ * `BuildSchemaConfig.describeRelation`.
87
+ */
88
+ type RelationDescriber = (tableName: string, relationName: string) => string | undefined;
89
+ /**
90
+ * The documentation hooks a build was configured with, resolved once and threaded through
91
+ * type generation. Every member is optional; a build with no hooks generates fields with no
92
+ * descriptions at all.
93
+ */
94
+ type SchemaDocs = {
95
+ describeColumn?: ColumnDescriber;
96
+ describeTable?: TableDescriber;
97
+ describeRelation?: RelationDescriber;
98
+ deprecateColumn?: ColumnDeprecator;
99
+ };
43
100
 
44
101
  type TableNamedRelations = {
45
102
  relation: Relation;
@@ -175,8 +232,14 @@ declare const drizzleExecutorKey: unique symbol;
175
232
  * 2. When limit/offset args are present, falls back to a direct per-item query.
176
233
  * 3. Otherwise batches all sibling resolver calls within the same GraphQL execution tick
177
234
  * into a single IN-clause query, eliminating N+1 database round-trips.
235
+ *
236
+ * `nullOrdering` is the dialect's native `ORDER BY` placement for `NULL` — the keyset
237
+ * predicate behind a relation's `after` argument has to match it, or rows with a `NULL` in an
238
+ * ordered column would be skipped instead of paged through. It has no sensible default, so
239
+ * each dialect builder states it: `'nulls-largest'` for PostgreSQL, `'nulls-smallest'` for
240
+ * MySQL and SQLite.
178
241
  */
179
- declare const createRelationResolverFactory: (db: any, tables: Record<string, Table>, filterCtx?: RelationFilterBase) => RelationResolverFactory;
242
+ declare const createRelationResolverFactory: (db: any, tables: Record<string, Table>, nullOrdering: NullOrdering, filterCtx?: RelationFilterBase) => RelationResolverFactory;
180
243
  /**
181
244
  * Compiles an `orderBy` argument into ORDER BY expressions, highest priority first.
182
245
  *
@@ -218,6 +281,14 @@ interface RelationFilterContext {
218
281
  */
219
282
  type RelationFilterBase = Pick<RelationFilterContext, 'tables' | 'relationMap'>;
220
283
  declare const extractFilters: <TTable extends Table>(table: TTable, tableName: string, filters: Filters<TTable>, relationCtx?: RelationFilterContext) => SQL | undefined;
284
+ /**
285
+ * Where a dialect's default sort places NULLs relative to non-NULL values:
286
+ * - `nulls-largest` — PostgreSQL: NULLs sort as the largest values (last in ASC, first in DESC).
287
+ * - `nulls-smallest` — MySQL and SQLite: NULLs sort as the smallest values (first in ASC, last
288
+ * in DESC).
289
+ * The keyset predicate has to agree with the dialect's ORDER BY, so each builder passes its own.
290
+ */
291
+ type NullOrdering = 'nulls-largest' | 'nulls-smallest';
221
292
  /**
222
293
  * Default for `config.onError`: keeps drizzle-graphql's own errors, which are written for
223
294
  * the client, and replaces driver/database errors with a generic message. Their text names
@@ -580,6 +651,83 @@ type SchemaFeatures = {
580
651
  * @default false
581
652
  */
582
653
  upsert?: boolean;
654
+ /**
655
+ * Relation fields on `Create<Table>Input` and `Update<Table>Input`, so a parent row and
656
+ * the rows it is related to can be written in one mutation. Off unless asked for: it adds
657
+ * a field per writable relation to every create and update input.
658
+ *
659
+ * ```graphql
660
+ * createPostsSingle(values: {
661
+ * title: "Hello"
662
+ * author: { connect: { id: { eq: "a1" } } }
663
+ * tags: { create: [{ name: "drizzle" }] }
664
+ * }) { id }
665
+ * ```
666
+ *
667
+ * Each relation field offers `create` and `connect`; the update input adds `disconnect`
668
+ * and, for a to-many relation, `set` (replace the whole set). `disconnect` and `set` are
669
+ * generated only when the foreign key is nullable — there is no way to detach a row whose
670
+ * key is NOT NULL — and many-to-many (`.through()`) relations are not written through at
671
+ * all. Nesting is one level deep: the row a nested `create` inserts takes columns only.
672
+ *
673
+ * The whole tree runs in one transaction (a savepoint when the request already carries
674
+ * one), and a column a relation fills in (`authorId`, when `author: { create: … }` is
675
+ * offered) becomes nullable on the create input, since the relation is the other way to
676
+ * supply it.
677
+ *
678
+ * PostgreSQL and SQLite only. MySQL cannot return the rows it just wrote, which is how a
679
+ * nested write learns the parent's key, so `buildSchema` rejects the flag there. On SQLite
680
+ * the driver must be asynchronous (libsql, D1, …): a synchronous one commits before an
681
+ * awaited statement runs, so `buildSchema` rejects the combination outright.
682
+ *
683
+ * @default false
684
+ */
685
+ nestedWrites?: boolean;
686
+ /**
687
+ * Operation inputs on the update `set`, so a column can be changed relative to its current
688
+ * value instead of only replaced.
689
+ *
690
+ * ```graphql
691
+ * updatePostsSingle(where: { id: { eq: "p1" } }, set: { views: { increment: 1 } }) { views }
692
+ * ```
693
+ *
694
+ * Every numeric column's field on `Update<Table>Input` becomes a `<Scalar>FieldUpdate`
695
+ * input carrying `set`, `increment`, `decrement`, `multiply` and `divide`; every array
696
+ * column's becomes a `<Scalar>ListFieldUpdate` carrying `set` and `push`. Exactly one
697
+ * operation per field, checked at resolve time. `set` is the explicit spelling of what the
698
+ * field did before, so `set: { views: 42 }` becomes `set: { views: { set: 42 } }`.
699
+ *
700
+ * The arithmetic happens in the database (`SET views = views + 1`), so a counter no longer
701
+ * needs a read-modify-write round trip and no longer loses concurrent updates. Rounding on
702
+ * an integer column, and division by zero, follow the database's own rules rather than
703
+ * being guarded here. Columns owned by a scalar override keep their plain type — an
704
+ * override owns what the column accepts.
705
+ *
706
+ * Off by default: it changes the type of every numeric and array field on every update
707
+ * input, which no existing document is written against.
708
+ *
709
+ * @default false
710
+ */
711
+ fieldUpdateOperations?: boolean;
712
+ /**
713
+ * `update<Table>Count` / `delete<Table>Count` mutations — the same write as the plural
714
+ * `update<Table>` / `delete<Table>`, returning the number of rows affected instead of the
715
+ * rows themselves.
716
+ *
717
+ * ```graphql
718
+ * deletePostsCount(where: { published: { eq: false } }) # Int!
719
+ * ```
720
+ *
721
+ * A mass update or delete otherwise has to `RETURNING *` every row it touched purely so
722
+ * the caller can count them, which crosses the driver and is serialized through GraphQL
723
+ * for nothing. Each mutation is generated only when its plural counterpart is
724
+ * (`features.update` / `features.delete`), and honours `features.requireWhere`.
725
+ *
726
+ * Off unless asked for, so an existing schema does not grow new mutations on upgrade.
727
+ *
728
+ * @default false
729
+ */
730
+ countMutations?: boolean;
583
731
  /**
584
732
  * Makes `where` non-null on the plural `update<Table>` / `delete<Table>` mutations, and
585
733
  * rejects a `where` that collapses to no filters (e.g. `where: {}`), so a schema can rule
@@ -884,6 +1032,94 @@ type BuildSchemaConfig = {
884
1032
  * ```
885
1033
  */
886
1034
  onError?: (error: unknown) => unknown;
1035
+ /**
1036
+ * Supplies the GraphQL `description` for a column, everywhere that column becomes a field:
1037
+ * the object type, the create/update inputs, the filter input, and the aggregate
1038
+ * `min`/`max`/`group` fields.
1039
+ *
1040
+ * Nothing is generated by default. The library used to emit the column's own type name
1041
+ * ("DateTime", "JSON") as its description, which documented nothing a reader could not see
1042
+ * from the type — that is gone, and this hook is what puts real prose in its place. Drizzle
1043
+ * carries no column-comment metadata to read, so the text has to come from here.
1044
+ *
1045
+ * ```ts
1046
+ * const columnDocs = { Users: { email: 'Primary contact address. Unique, case-insensitive.' } };
1047
+ *
1048
+ * buildSchema(db, {
1049
+ * describeColumn: (_column, { tableName, columnName }) => columnDocs[tableName]?.[columnName],
1050
+ * });
1051
+ * ```
1052
+ *
1053
+ * `tableName` and `columnName` are the Drizzle schema keys. Return `undefined` to leave the
1054
+ * field undocumented.
1055
+ */
1056
+ describeColumn?: ColumnDescriber;
1057
+ /**
1058
+ * Supplies the GraphQL `description` for a table's object type.
1059
+ *
1060
+ * ```ts
1061
+ * buildSchema(db, { describeTable: (tableName) => tableDocs[tableName] });
1062
+ * ```
1063
+ */
1064
+ describeTable?: TableDescriber;
1065
+ /**
1066
+ * Supplies the GraphQL `description` for a relation field on a table's object type.
1067
+ *
1068
+ * ```ts
1069
+ * buildSchema(db, {
1070
+ * describeRelation: (tableName, relationName) =>
1071
+ * tableName === 'Users' && relationName === 'posts' ? 'Posts this user authored.' : undefined,
1072
+ * });
1073
+ * ```
1074
+ *
1075
+ * The generated `<relation>Aggregate` companion fields are not covered — they are derived
1076
+ * fields rather than the relation itself.
1077
+ */
1078
+ describeRelation?: RelationDescriber;
1079
+ /**
1080
+ * Supplies the GraphQL `deprecationReason` for a column, marking it `@deprecated` on the
1081
+ * object type and on the create/update inputs.
1082
+ *
1083
+ * ```ts
1084
+ * buildSchema(db, {
1085
+ * deprecateColumn: (_column, { columnName }) =>
1086
+ * columnName === 'legacyFlag' ? 'Use `status` instead.' : undefined,
1087
+ * });
1088
+ * ```
1089
+ *
1090
+ * A required input field cannot be deprecated — GraphQL rejects the schema, since a client
1091
+ * has no way to stop sending it — so the reason is dropped on non-null input fields and
1092
+ * kept everywhere else. Filter and orderBy fields are never deprecated either: filtering on
1093
+ * a deprecated column is how a caller finds the rows that still use it.
1094
+ */
1095
+ deprecateColumn?: ColumnDeprecator;
1096
+ /**
1097
+ * Names the GraphQL enum types generated for enum columns.
1098
+ *
1099
+ * By default a column declared with a named `pgEnum` gets one shared type named after the
1100
+ * enum (`pgEnum('status', …)` → `StatusEnum`), reused by every column declared with that
1101
+ * same `pgEnum` — the database column is the same type, so a client variable typed
1102
+ * `StatusEnum!` is passable to any of them. A column with an inline value list
1103
+ * (`text({ enum: [...] })`, `mysqlEnum(...)`) keeps a per-column type named for its table
1104
+ * and column (`UsersRoleTextEnum`), because its values are shared with nothing.
1105
+ *
1106
+ * This hook overrides the name either way — for lining the schema up with another schema it
1107
+ * is stitched into, or for opting a specific column back into a type of its own:
1108
+ *
1109
+ * ```ts
1110
+ * buildSchema(db, {
1111
+ * enumNameMapper: (info) => (info.enumName === 'status' ? 'PublicationStatus' : undefined),
1112
+ * });
1113
+ * ```
1114
+ *
1115
+ * Two columns the mapper sends to the same name share one type when their values match —
1116
+ * the way to unify inline enums declared separately that mean the same thing. Sending two
1117
+ * *different* value lists to one name throws at build time rather than producing an
1118
+ * invalid schema.
1119
+ *
1120
+ * Return `undefined` to keep the default name.
1121
+ */
1122
+ enumNameMapper?: EnumNameMapper;
887
1123
  };
888
1124
 
889
1125
  /**
@@ -903,4 +1139,4 @@ declare const GraphQLDecimalString: GraphQLScalarType<string, string>;
903
1139
 
904
1140
  declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
905
1141
 
906
- export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ColumnTypeMapper, type ColumnTypeMapperInfo, type ComplexityConfig, type DeleteResolver, type DeleteSingleResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, GraphQLDecimalString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type ScalarOverride, type ScalarOverridesConfig, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
1142
+ export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ColumnDeprecator, type ColumnDescriber, type ColumnDocInfo, type ColumnTypeMapper, type ColumnTypeMapperInfo, type ComplexityConfig, type DeleteResolver, type DeleteSingleResolver, type EnumNameInfo, type EnumNameMapper, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, GraphQLDecimalString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationDescriber, type RelationResolverFactory, type ScalarOverride, type ScalarOverridesConfig, type SchemaDocs, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableDescriber, type TableNamedRelations, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };