@vantreeseba/drizzle-graphql 1.0.3 → 2.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
@@ -1,9 +1,19 @@
1
- import { Table, Column, SQL, Relation, One, Many } from 'drizzle-orm';
1
+ import { Table, Column, Relation, SQL, One, Many } from 'drizzle-orm';
2
2
  import { MySqlDatabase } from 'drizzle-orm/mysql-core';
3
3
  import { PgAsyncDatabase } from 'drizzle-orm/pg-core';
4
4
  import { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';
5
- import { GraphQLResolveInfo, GraphQLSchema, GraphQLInputObjectType, GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType } from 'graphql';
5
+ import { GraphQLFieldResolver, GraphQLResolveInfo, GraphQLSchema, GraphQLInputObjectType, GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType } from 'graphql';
6
6
 
7
+ type TableNamedRelations = {
8
+ relation: Relation;
9
+ targetTableName: string;
10
+ /**
11
+ * Property names of the target table's primary key, resolved at build time (composite
12
+ * keys included, via the dialect's getTableConfig). Used to default paginated relations
13
+ * to a deterministic PK order. Empty when the target has no detectable primary key.
14
+ */
15
+ targetPkNames?: readonly string[];
16
+ };
7
17
  type ColTypeIsNull<TColumn extends Column, TColType> = TColumn['_']['notNull'] extends true ? TColType : TColType | null;
8
18
  type ColTypeIsNullOrUndefinedWithDefault<TColumn extends Column, TColType> = TColumn['_']['notNull'] extends true ? TColumn['_']['hasDefault'] extends true ? TColType | null | undefined : TColumn['defaultFn'] extends undefined ? TColType : TColType | null | undefined : TColType | null | undefined;
9
19
  type GetColumnGqlDataType<TColumn extends Column> = TColumn['dataType'] extends 'boolean' ? ColTypeIsNull<TColumn, boolean> : TColumn['dataType'] extends 'json' ? TColumn['_']['columnType'] extends 'PgGeometryObject' ? ColTypeIsNull<TColumn, {
@@ -62,6 +72,32 @@ type OrderByArgs<TTable extends Table> = {
62
72
  };
63
73
  };
64
74
 
75
+ /**
76
+ * Extracts the join column info from a drizzle-orm v1 Relation object.
77
+ * Returns the JS property name of the local column on the parent table and the
78
+ * Column object for the foreign column on the target table, or undefined if the
79
+ * relation internals are not accessible.
80
+ */
81
+ declare const extractRelationJoinColumns: (relEntry: TableNamedRelations, parentTable: Table, targetTable: Table) => {
82
+ localColPropName: string;
83
+ foreignCol: Column;
84
+ foreignColPropName: string;
85
+ } | undefined;
86
+ type RelationResolverFactory = (params: {
87
+ tableName: string;
88
+ relationName: string;
89
+ relEntry: TableNamedRelations;
90
+ isOne: boolean;
91
+ }) => GraphQLFieldResolver<any, any> | undefined;
92
+ /**
93
+ * Creates a RelationResolverFactory that generates field-level resolvers for each relation.
94
+ * Each resolver:
95
+ * 1. Returns pre-fetched data if the parent resolver already included it (eager path, zero cost).
96
+ * 2. When limit/offset args are present, falls back to a direct per-item query.
97
+ * 3. Otherwise batches all sibling resolver calls within the same GraphQL execution tick
98
+ * into a single IN-clause query, eliminating N+1 database round-trips.
99
+ */
100
+ declare const createRelationResolverFactory: (db: any, tables: Record<string, Table>) => RelationResolverFactory;
65
101
  declare const extractOrderBy: <TTable extends Table, TArgs extends OrderByArgs<any> = OrderByArgs<TTable>>(table: TTable, orderArgs: TArgs) => SQL[];
66
102
  declare const extractFilters: <TTable extends Table>(table: TTable, tableName: string, filters: Filters<TTable>) => SQL | undefined;
67
103
 
@@ -158,7 +194,7 @@ type QueriesCore<TSchemaTables extends Record<string, Table>, TSchemaRelations e
158
194
  } : never;
159
195
  };
160
196
  type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends Record<string, GraphQLInputObjectType>, TOutputs extends Record<string, GraphQLObjectType>, IsReturnless extends boolean> = {
161
- [TName in keyof TSchemaTables as TName extends string ? `insertInto${Capitalize<TName>}` : never]: TName extends string ? {
197
+ [TName in keyof TSchemaTables as TName extends string ? `create${Capitalize<TName>}` : never]: TName extends string ? {
162
198
  type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[`${Capitalize<TName>}Item`]>>>;
163
199
  args: {
164
200
  values: {
@@ -168,7 +204,7 @@ type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends
168
204
  resolve: InsertArrResolver<TSchemaTables[TName], IsReturnless>;
169
205
  } : never;
170
206
  } & {
171
- [TName in keyof TSchemaTables as TName extends string ? `insertInto${Capitalize<TName>}Single` : never]: TName extends string ? {
207
+ [TName in keyof TSchemaTables as TName extends string ? `create${Capitalize<TName>}Single` : never]: TName extends string ? {
172
208
  type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[`${Capitalize<TName>}Item`];
173
209
  args: {
174
210
  values: {
@@ -191,7 +227,7 @@ type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends
191
227
  resolve: UpdateResolver<TSchemaTables[TName], IsReturnless>;
192
228
  } : never;
193
229
  } & {
194
- [TName in keyof TSchemaTables as TName extends string ? `deleteFrom${Capitalize<TName>}` : never]: TName extends string ? {
230
+ [TName in keyof TSchemaTables as TName extends string ? `delete${Capitalize<TName>}` : never]: TName extends string ? {
195
231
  type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[`${Capitalize<TName>}Item`]>>>;
196
232
  args: {
197
233
  where: {
@@ -222,6 +258,15 @@ type GeneratedEntities<TDatabase extends AnyDrizzleDB<TSchema>, TSchema extends
222
258
  mutations: MutationsCore<TSchemaTables, TInputs, TOutputs, TDatabase extends MySqlDatabase<any, any, any, any> ? true : false>;
223
259
  inputs: TInputs;
224
260
  types: TOutputs;
261
+ /**
262
+ * Field-level resolvers for each relation on each table.
263
+ * Each resolver handles both the eager path (data pre-fetched by the parent query)
264
+ * and the lazy path (data fetched on demand with N+1 protection via request-scoped batching).
265
+ * Keyed as `fieldResolvers[tableSchemaKey][relationName]`.
266
+ */
267
+ fieldResolvers: {
268
+ [TName in keyof TSchemaTables as TName extends string ? TName : never]?: Record<string, (source: any, args: any, context: any, info: GraphQLResolveInfo) => Promise<any>>;
269
+ };
225
270
  };
226
271
  type GeneratedData<TDatabase extends AnyDrizzleDB<any>> = {
227
272
  schema: GraphQLSchema;
@@ -237,26 +282,34 @@ type BuildSchemaConfig = {
237
282
  */
238
283
  mutations?: boolean;
239
284
  /**
240
- * Limits depth of generated relation fields on queries.
285
+ * Limits depth of relation-field generation.
241
286
  *
242
- * Expects non-negative integer or undefined.
287
+ * Expects a non-negative integer or `undefined`.
243
288
  *
244
- * Set value to `undefined` to not limit relation depth.
289
+ * `undefined` (default) no limit; all relations are generated recursively
290
+ * until a cycle is detected.
245
291
  *
246
- * Set value to `0` to omit relations altogether.
292
+ * `0` no relation fields are generated on any type. Useful for a flat,
293
+ * columns-only schema.
247
294
  *
248
- * Value is treated as if set to `undefined` by default.
295
+ * `N > 0` each table's own direct relations are still generated (every
296
+ * table's root type is processed at depth 0, which is always < N). The
297
+ * depth limit controls how deep the generation RECURSES when traversing
298
+ * related types; because all types share a single instance via the type
299
+ * cache, setting N > 0 currently behaves the same as `undefined` for the
300
+ * final schema shape. The principal useful values are `0` (no relations)
301
+ * and `undefined` (unlimited).
249
302
  */
250
303
  relationsDepthLimit?: number;
251
304
  /**
252
305
  * Customizes query name prefixes for generated GraphQL operations.
253
306
  *
254
- * @default { list: '', single: 'Single' }
307
+ * @default { insert: 'create', delete: 'delete', update: 'update' }
255
308
  */
256
309
  prefixes?: {
257
- /** Prefix for insert mutations (e.g., 'users' -> 'insertIntoUsers') */
310
+ /** Prefix for insert mutations (e.g., 'users' -> 'createUsers') */
258
311
  insert?: string;
259
- /** Prefix for delete mutations (e.g., 'users' -> 'deleteFromUsers') */
312
+ /** Prefix for delete mutations (e.g., 'users' -> 'deleteUsers') */
260
313
  delete?: string;
261
314
  /** Prefix for update mutations (e.g., 'users' -> 'updateUsers') */
262
315
  update?: string;
@@ -278,14 +331,54 @@ type BuildSchemaConfig = {
278
331
  */
279
332
  conflictDoNothing?: boolean;
280
333
  /**
281
- * When true, all generated GraphQL object type names will use the singular form
282
- * of the table name (e.g. `users` table `User` type instead of `Users`).
334
+ * Optional mapper from table key to singular/plural name pair.
335
+ * When provided for a table, overrides the default (table key) naming for GraphQL type names,
336
+ * query field names, and mutation field names.
337
+ * Return `undefined` for tables that should use the default naming.
338
+ *
339
+ * Example: `(name) => name === 'users' ? { singular: 'user', plural: 'users' } : undefined`
340
+ * produces type `User`, queries `users` / `user`, mutations `createUsers` / `createUser` for
341
+ * the `users` table, and leaves other tables with their default names.
342
+ */
343
+ typeNameMapper?: (tableName: string) => {
344
+ singular: string;
345
+ plural: string;
346
+ } | undefined;
347
+ /**
348
+ * Controls whether a relation is eagerly pre-fetched via Drizzle's `with:` clause
349
+ * when its parent is loaded through a generated query or mutation.
350
+ *
351
+ * `true` (default) — every selected relation is eager-loaded in the parent's query.
352
+ *
353
+ * `false` — no relation is ever eager-loaded; all relations resolve lazily through
354
+ * their (request-batched) field resolvers.
355
+ *
356
+ * `(tableName, relationName) => boolean` — decide per relation. Return `false` to
357
+ * exclude that relation from `with:` (and from the mutation eager re-fetch).
358
+ *
359
+ * Opting a relation out does NOT remove its field resolver — it still resolves
360
+ * lazily via the request-scoped batch loader. This is the hook for overriding a
361
+ * relation's resolver (e.g. via `@graphql-tools/schema`'s `addResolversToSchema`)
362
+ * without the eager `with:` query also fetching it from the database:
363
+ *
364
+ * ```ts
365
+ * const { schema } = buildSchema(db, {
366
+ * eagerLoadRelations: (t, r) => !(t === 'Users' && r === 'posts'),
367
+ * });
368
+ * const finalSchema = addResolversToSchema({
369
+ * schema,
370
+ * resolvers: { Users: { posts: (parent) => myLoader.load(parent.id) } },
371
+ * });
372
+ * ```
373
+ *
374
+ * Table and relation names are the Drizzle schema keys (e.g. `Users`, `posts`),
375
+ * matching the keys of `entities.fieldResolvers`.
283
376
  *
284
- * Defaults to false.
377
+ * @default true
285
378
  */
286
- singularTypes?: boolean;
379
+ eagerLoadRelations?: boolean | ((tableName: string, relationName: string) => boolean);
287
380
  };
288
381
 
289
382
  declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
290
383
 
291
- export { type AnyDrizzleDB, type BuildSchemaConfig, type DeleteResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type SelectResolver, type SelectSingleResolver, type UpdateResolver, buildSchema, extractFilters, extractOrderBy };
384
+ export { type AnyDrizzleDB, type BuildSchemaConfig, type DeleteResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateResolver, buildSchema, createRelationResolverFactory, extractFilters, extractOrderBy, extractRelationJoinColumns };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,19 @@
1
- import { Table, Column, SQL, Relation, One, Many } from 'drizzle-orm';
1
+ import { Table, Column, Relation, SQL, One, Many } from 'drizzle-orm';
2
2
  import { MySqlDatabase } from 'drizzle-orm/mysql-core';
3
3
  import { PgAsyncDatabase } from 'drizzle-orm/pg-core';
4
4
  import { BaseSQLiteDatabase } from 'drizzle-orm/sqlite-core';
5
- import { GraphQLResolveInfo, GraphQLSchema, GraphQLInputObjectType, GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType } from 'graphql';
5
+ import { GraphQLFieldResolver, GraphQLResolveInfo, GraphQLSchema, GraphQLInputObjectType, GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType } from 'graphql';
6
6
 
7
+ type TableNamedRelations = {
8
+ relation: Relation;
9
+ targetTableName: string;
10
+ /**
11
+ * Property names of the target table's primary key, resolved at build time (composite
12
+ * keys included, via the dialect's getTableConfig). Used to default paginated relations
13
+ * to a deterministic PK order. Empty when the target has no detectable primary key.
14
+ */
15
+ targetPkNames?: readonly string[];
16
+ };
7
17
  type ColTypeIsNull<TColumn extends Column, TColType> = TColumn['_']['notNull'] extends true ? TColType : TColType | null;
8
18
  type ColTypeIsNullOrUndefinedWithDefault<TColumn extends Column, TColType> = TColumn['_']['notNull'] extends true ? TColumn['_']['hasDefault'] extends true ? TColType | null | undefined : TColumn['defaultFn'] extends undefined ? TColType : TColType | null | undefined : TColType | null | undefined;
9
19
  type GetColumnGqlDataType<TColumn extends Column> = TColumn['dataType'] extends 'boolean' ? ColTypeIsNull<TColumn, boolean> : TColumn['dataType'] extends 'json' ? TColumn['_']['columnType'] extends 'PgGeometryObject' ? ColTypeIsNull<TColumn, {
@@ -62,6 +72,32 @@ type OrderByArgs<TTable extends Table> = {
62
72
  };
63
73
  };
64
74
 
75
+ /**
76
+ * Extracts the join column info from a drizzle-orm v1 Relation object.
77
+ * Returns the JS property name of the local column on the parent table and the
78
+ * Column object for the foreign column on the target table, or undefined if the
79
+ * relation internals are not accessible.
80
+ */
81
+ declare const extractRelationJoinColumns: (relEntry: TableNamedRelations, parentTable: Table, targetTable: Table) => {
82
+ localColPropName: string;
83
+ foreignCol: Column;
84
+ foreignColPropName: string;
85
+ } | undefined;
86
+ type RelationResolverFactory = (params: {
87
+ tableName: string;
88
+ relationName: string;
89
+ relEntry: TableNamedRelations;
90
+ isOne: boolean;
91
+ }) => GraphQLFieldResolver<any, any> | undefined;
92
+ /**
93
+ * Creates a RelationResolverFactory that generates field-level resolvers for each relation.
94
+ * Each resolver:
95
+ * 1. Returns pre-fetched data if the parent resolver already included it (eager path, zero cost).
96
+ * 2. When limit/offset args are present, falls back to a direct per-item query.
97
+ * 3. Otherwise batches all sibling resolver calls within the same GraphQL execution tick
98
+ * into a single IN-clause query, eliminating N+1 database round-trips.
99
+ */
100
+ declare const createRelationResolverFactory: (db: any, tables: Record<string, Table>) => RelationResolverFactory;
65
101
  declare const extractOrderBy: <TTable extends Table, TArgs extends OrderByArgs<any> = OrderByArgs<TTable>>(table: TTable, orderArgs: TArgs) => SQL[];
66
102
  declare const extractFilters: <TTable extends Table>(table: TTable, tableName: string, filters: Filters<TTable>) => SQL | undefined;
67
103
 
@@ -158,7 +194,7 @@ type QueriesCore<TSchemaTables extends Record<string, Table>, TSchemaRelations e
158
194
  } : never;
159
195
  };
160
196
  type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends Record<string, GraphQLInputObjectType>, TOutputs extends Record<string, GraphQLObjectType>, IsReturnless extends boolean> = {
161
- [TName in keyof TSchemaTables as TName extends string ? `insertInto${Capitalize<TName>}` : never]: TName extends string ? {
197
+ [TName in keyof TSchemaTables as TName extends string ? `create${Capitalize<TName>}` : never]: TName extends string ? {
162
198
  type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[`${Capitalize<TName>}Item`]>>>;
163
199
  args: {
164
200
  values: {
@@ -168,7 +204,7 @@ type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends
168
204
  resolve: InsertArrResolver<TSchemaTables[TName], IsReturnless>;
169
205
  } : never;
170
206
  } & {
171
- [TName in keyof TSchemaTables as TName extends string ? `insertInto${Capitalize<TName>}Single` : never]: TName extends string ? {
207
+ [TName in keyof TSchemaTables as TName extends string ? `create${Capitalize<TName>}Single` : never]: TName extends string ? {
172
208
  type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[`${Capitalize<TName>}Item`];
173
209
  args: {
174
210
  values: {
@@ -191,7 +227,7 @@ type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends
191
227
  resolve: UpdateResolver<TSchemaTables[TName], IsReturnless>;
192
228
  } : never;
193
229
  } & {
194
- [TName in keyof TSchemaTables as TName extends string ? `deleteFrom${Capitalize<TName>}` : never]: TName extends string ? {
230
+ [TName in keyof TSchemaTables as TName extends string ? `delete${Capitalize<TName>}` : never]: TName extends string ? {
195
231
  type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[`${Capitalize<TName>}Item`]>>>;
196
232
  args: {
197
233
  where: {
@@ -222,6 +258,15 @@ type GeneratedEntities<TDatabase extends AnyDrizzleDB<TSchema>, TSchema extends
222
258
  mutations: MutationsCore<TSchemaTables, TInputs, TOutputs, TDatabase extends MySqlDatabase<any, any, any, any> ? true : false>;
223
259
  inputs: TInputs;
224
260
  types: TOutputs;
261
+ /**
262
+ * Field-level resolvers for each relation on each table.
263
+ * Each resolver handles both the eager path (data pre-fetched by the parent query)
264
+ * and the lazy path (data fetched on demand with N+1 protection via request-scoped batching).
265
+ * Keyed as `fieldResolvers[tableSchemaKey][relationName]`.
266
+ */
267
+ fieldResolvers: {
268
+ [TName in keyof TSchemaTables as TName extends string ? TName : never]?: Record<string, (source: any, args: any, context: any, info: GraphQLResolveInfo) => Promise<any>>;
269
+ };
225
270
  };
226
271
  type GeneratedData<TDatabase extends AnyDrizzleDB<any>> = {
227
272
  schema: GraphQLSchema;
@@ -237,26 +282,34 @@ type BuildSchemaConfig = {
237
282
  */
238
283
  mutations?: boolean;
239
284
  /**
240
- * Limits depth of generated relation fields on queries.
285
+ * Limits depth of relation-field generation.
241
286
  *
242
- * Expects non-negative integer or undefined.
287
+ * Expects a non-negative integer or `undefined`.
243
288
  *
244
- * Set value to `undefined` to not limit relation depth.
289
+ * `undefined` (default) no limit; all relations are generated recursively
290
+ * until a cycle is detected.
245
291
  *
246
- * Set value to `0` to omit relations altogether.
292
+ * `0` no relation fields are generated on any type. Useful for a flat,
293
+ * columns-only schema.
247
294
  *
248
- * Value is treated as if set to `undefined` by default.
295
+ * `N > 0` each table's own direct relations are still generated (every
296
+ * table's root type is processed at depth 0, which is always < N). The
297
+ * depth limit controls how deep the generation RECURSES when traversing
298
+ * related types; because all types share a single instance via the type
299
+ * cache, setting N > 0 currently behaves the same as `undefined` for the
300
+ * final schema shape. The principal useful values are `0` (no relations)
301
+ * and `undefined` (unlimited).
249
302
  */
250
303
  relationsDepthLimit?: number;
251
304
  /**
252
305
  * Customizes query name prefixes for generated GraphQL operations.
253
306
  *
254
- * @default { list: '', single: 'Single' }
307
+ * @default { insert: 'create', delete: 'delete', update: 'update' }
255
308
  */
256
309
  prefixes?: {
257
- /** Prefix for insert mutations (e.g., 'users' -> 'insertIntoUsers') */
310
+ /** Prefix for insert mutations (e.g., 'users' -> 'createUsers') */
258
311
  insert?: string;
259
- /** Prefix for delete mutations (e.g., 'users' -> 'deleteFromUsers') */
312
+ /** Prefix for delete mutations (e.g., 'users' -> 'deleteUsers') */
260
313
  delete?: string;
261
314
  /** Prefix for update mutations (e.g., 'users' -> 'updateUsers') */
262
315
  update?: string;
@@ -278,14 +331,54 @@ type BuildSchemaConfig = {
278
331
  */
279
332
  conflictDoNothing?: boolean;
280
333
  /**
281
- * When true, all generated GraphQL object type names will use the singular form
282
- * of the table name (e.g. `users` table `User` type instead of `Users`).
334
+ * Optional mapper from table key to singular/plural name pair.
335
+ * When provided for a table, overrides the default (table key) naming for GraphQL type names,
336
+ * query field names, and mutation field names.
337
+ * Return `undefined` for tables that should use the default naming.
338
+ *
339
+ * Example: `(name) => name === 'users' ? { singular: 'user', plural: 'users' } : undefined`
340
+ * produces type `User`, queries `users` / `user`, mutations `createUsers` / `createUser` for
341
+ * the `users` table, and leaves other tables with their default names.
342
+ */
343
+ typeNameMapper?: (tableName: string) => {
344
+ singular: string;
345
+ plural: string;
346
+ } | undefined;
347
+ /**
348
+ * Controls whether a relation is eagerly pre-fetched via Drizzle's `with:` clause
349
+ * when its parent is loaded through a generated query or mutation.
350
+ *
351
+ * `true` (default) — every selected relation is eager-loaded in the parent's query.
352
+ *
353
+ * `false` — no relation is ever eager-loaded; all relations resolve lazily through
354
+ * their (request-batched) field resolvers.
355
+ *
356
+ * `(tableName, relationName) => boolean` — decide per relation. Return `false` to
357
+ * exclude that relation from `with:` (and from the mutation eager re-fetch).
358
+ *
359
+ * Opting a relation out does NOT remove its field resolver — it still resolves
360
+ * lazily via the request-scoped batch loader. This is the hook for overriding a
361
+ * relation's resolver (e.g. via `@graphql-tools/schema`'s `addResolversToSchema`)
362
+ * without the eager `with:` query also fetching it from the database:
363
+ *
364
+ * ```ts
365
+ * const { schema } = buildSchema(db, {
366
+ * eagerLoadRelations: (t, r) => !(t === 'Users' && r === 'posts'),
367
+ * });
368
+ * const finalSchema = addResolversToSchema({
369
+ * schema,
370
+ * resolvers: { Users: { posts: (parent) => myLoader.load(parent.id) } },
371
+ * });
372
+ * ```
373
+ *
374
+ * Table and relation names are the Drizzle schema keys (e.g. `Users`, `posts`),
375
+ * matching the keys of `entities.fieldResolvers`.
283
376
  *
284
- * Defaults to false.
377
+ * @default true
285
378
  */
286
- singularTypes?: boolean;
379
+ eagerLoadRelations?: boolean | ((tableName: string, relationName: string) => boolean);
287
380
  };
288
381
 
289
382
  declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
290
383
 
291
- export { type AnyDrizzleDB, type BuildSchemaConfig, type DeleteResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type SelectResolver, type SelectSingleResolver, type UpdateResolver, buildSchema, extractFilters, extractOrderBy };
384
+ export { type AnyDrizzleDB, type BuildSchemaConfig, type DeleteResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateResolver, buildSchema, createRelationResolverFactory, extractFilters, extractOrderBy, extractRelationJoinColumns };