@vantreeseba/drizzle-graphql 2.0.0 → 4.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/README.md +390 -0
- package/dist/README.md +390 -0
- package/dist/index.cjs +1760 -463
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +220 -7
- package/dist/index.d.ts +220 -7
- package/dist/index.js +1712 -401
- package/dist/index.js.map +1 -1
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -2,7 +2,8 @@ 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 { GraphQLFieldResolver, GraphQLResolveInfo, GraphQLSchema, GraphQLInputObjectType, GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType } from 'graphql';
|
|
5
|
+
import { GraphQLFieldResolver, GraphQLResolveInfo, GraphQLSchema, GraphQLInputObjectType, GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType, GraphQLEnumType } from 'graphql';
|
|
6
|
+
export { GraphQLDate, GraphQLDateTime, GraphQLJSON, GraphQLUUID } from 'graphql-scalars';
|
|
6
7
|
|
|
7
8
|
type TableNamedRelations = {
|
|
8
9
|
relation: Relation;
|
|
@@ -89,6 +90,23 @@ type RelationResolverFactory = (params: {
|
|
|
89
90
|
relEntry: TableNamedRelations;
|
|
90
91
|
isOne: boolean;
|
|
91
92
|
}) => GraphQLFieldResolver<any, any> | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Key on the GraphQL context object under which a caller can place a Drizzle transaction
|
|
95
|
+
* (or any other executor: a pooled connection, a logging proxy). Every generated resolver
|
|
96
|
+
* reads it at resolve time and runs its statements there instead of on the database the
|
|
97
|
+
* schema was built from, which is what lets several mutations in one request share a
|
|
98
|
+
* transaction and lets a query see that transaction's uncommitted rows:
|
|
99
|
+
*
|
|
100
|
+
* ```ts
|
|
101
|
+
* await db.transaction(async (tx) => {
|
|
102
|
+
* await graphql({ schema, source, contextValue: { [drizzleExecutorKey]: tx } });
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* Registered with `Symbol.for` so the ESM and CJS builds of this package agree on it when
|
|
107
|
+
* both end up loaded in one process.
|
|
108
|
+
*/
|
|
109
|
+
declare const drizzleExecutorKey: unique symbol;
|
|
92
110
|
/**
|
|
93
111
|
* Creates a RelationResolverFactory that generates field-level resolvers for each relation.
|
|
94
112
|
* Each resolver:
|
|
@@ -97,9 +115,41 @@ type RelationResolverFactory = (params: {
|
|
|
97
115
|
* 3. Otherwise batches all sibling resolver calls within the same GraphQL execution tick
|
|
98
116
|
* into a single IN-clause query, eliminating N+1 database round-trips.
|
|
99
117
|
*/
|
|
100
|
-
declare const createRelationResolverFactory: (db: any, tables: Record<string, Table
|
|
118
|
+
declare const createRelationResolverFactory: (db: any, tables: Record<string, Table>, filterCtx?: RelationFilterBase) => RelationResolverFactory;
|
|
101
119
|
declare const extractOrderBy: <TTable extends Table, TArgs extends OrderByArgs<any> = OrderByArgs<TTable>>(table: TTable, orderArgs: TArgs) => SQL[];
|
|
102
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Everything `extractFilters` needs to turn a relation key in a `where` argument into a
|
|
122
|
+
* correlated subquery. Omitted by callers that don't generate relation filters, in which case
|
|
123
|
+
* relation keys can't appear in the input to begin with.
|
|
124
|
+
*/
|
|
125
|
+
interface RelationFilterContext {
|
|
126
|
+
/** Every table in the schema, keyed by its schema key. */
|
|
127
|
+
tables: Record<string, Table>;
|
|
128
|
+
/** Relations keyed by table schema key, then relation name. */
|
|
129
|
+
relationMap: Record<string, Record<string, TableNamedRelations>>;
|
|
130
|
+
/**
|
|
131
|
+
* Schema key of the table being filtered. Not always the same as the `tableName` label
|
|
132
|
+
* used in error messages (relation `where` callbacks pass the relation name there).
|
|
133
|
+
*/
|
|
134
|
+
tableKey: string;
|
|
135
|
+
/** Shared counter making every subquery alias unique within one extraction. */
|
|
136
|
+
aliases?: {
|
|
137
|
+
n: number;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The build-scoped half of {@link RelationFilterContext}. Created once per generated schema and
|
|
142
|
+
* handed to every resolver, which adds the table it is filtering.
|
|
143
|
+
*/
|
|
144
|
+
type RelationFilterBase = Pick<RelationFilterContext, 'tables' | 'relationMap'>;
|
|
145
|
+
declare const extractFilters: <TTable extends Table>(table: TTable, tableName: string, filters: Filters<TTable>, relationCtx?: RelationFilterContext) => SQL | undefined;
|
|
146
|
+
/**
|
|
147
|
+
* Default for `config.onError`: keeps drizzle-graphql's own errors, which are written for
|
|
148
|
+
* the client, and replaces driver/database errors with a generic message. Their text names
|
|
149
|
+
* tables, columns, constraints and offending values, none of which belongs in a response.
|
|
150
|
+
* The original is preserved on `originalError` for server-side logging.
|
|
151
|
+
*/
|
|
152
|
+
declare const defaultErrorMapper: (error: unknown) => unknown;
|
|
103
153
|
|
|
104
154
|
type Relations<TTable extends string = string, TConfig extends Record<string, Relation> = Record<string, Relation>> = {
|
|
105
155
|
table: {
|
|
@@ -144,6 +194,22 @@ type UpdateArgs<TTable extends Table> = Partial<{
|
|
|
144
194
|
set: GetRemappedTableUpdateDataType<TTable>;
|
|
145
195
|
where?: Filters<TTable>;
|
|
146
196
|
}>;
|
|
197
|
+
/**
|
|
198
|
+
* The `onConflict` argument of the generated upsert mutations.
|
|
199
|
+
*
|
|
200
|
+
* `target` and `where` exist on PostgreSQL and SQLite only: MySQL's
|
|
201
|
+
* `ON DUPLICATE KEY UPDATE` fires on whichever unique key was violated and takes no
|
|
202
|
+
* predicate, so neither field is generated there.
|
|
203
|
+
*/
|
|
204
|
+
type UpsertConflictArgs<TTable extends Table> = {
|
|
205
|
+
action?: 'UPDATE' | 'NOTHING';
|
|
206
|
+
target?: string[];
|
|
207
|
+
update?: string[];
|
|
208
|
+
where?: Filters<TTable>;
|
|
209
|
+
};
|
|
210
|
+
type UpsertArgs<TTable extends Table, isSingle extends boolean> = InsertArgs<TTable, isSingle> & {
|
|
211
|
+
onConflict?: UpsertConflictArgs<TTable>;
|
|
212
|
+
};
|
|
147
213
|
type DeleteArgs<TTable extends Table> = {
|
|
148
214
|
where?: Filters<TTable>;
|
|
149
215
|
};
|
|
@@ -153,9 +219,23 @@ type SelectResolver<TTable extends Table, TTables extends Record<string, Table>,
|
|
|
153
219
|
type SelectSingleResolver<TTable extends Table, TTables extends Record<string, Table>, TRelations extends Record<string, Relation>> = (source: any, args: Partial<QueryArgs<TTable, true>>, context: any, info: GraphQLResolveInfo) => Promise<(keyof TRelations extends infer RelKey ? RelKey extends string ? GetRemappedTableDataType<TTable> & {
|
|
154
220
|
[K in RelKey]: TRelations[K] extends One<string> ? GetRemappedTableDataType<ExtractTableByName<TTables, TRelations[K]['referencedTableName']> extends infer T ? T[keyof T] : never> | null : TRelations[K] extends Many<string> ? Array<GetRemappedTableDataType<ExtractTableByName<TTables, TRelations[K]['referencedTableName']> extends infer T ? T[keyof T] : never>> : never;
|
|
155
221
|
} : GetRemappedTableDataType<TTable> : GetRemappedTableDataType<TTable>) | null>;
|
|
156
|
-
|
|
157
|
-
type
|
|
222
|
+
/** Resolver for `create<Table>Single`: one row in, one row (or `undefined`) out. */
|
|
223
|
+
type InsertResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: Partial<InsertArgs<TTable, true>>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
|
|
224
|
+
/** Resolver for `create<Table>`: an array of rows in, an array of rows out. */
|
|
225
|
+
type InsertArrResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: Partial<InsertArgs<TTable, false>>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? Array<GetRemappedTableDataType<TTable>> : MutationReturnlessResult>;
|
|
158
226
|
type UpdateResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: UpdateArgs<TTable>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
|
|
227
|
+
/** Resolver for `upsert<Table>Single`. */
|
|
228
|
+
type UpsertResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: Partial<UpsertArgs<TTable, true>>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
|
|
229
|
+
/** Resolver for `upsert<Table>`. */
|
|
230
|
+
type UpsertArrResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: Partial<UpsertArgs<TTable, false>>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? Array<GetRemappedTableDataType<TTable>> : MutationReturnlessResult>;
|
|
231
|
+
/**
|
|
232
|
+
* Resolver for a table's generated aggregate query (`<plural>Aggregate`).
|
|
233
|
+
* Returns only the requested aggregations: `count` plus per-column `avg` / `sum`
|
|
234
|
+
* (numeric columns, as Float) and `min` / `max` (orderable columns, as the column's type).
|
|
235
|
+
*/
|
|
236
|
+
type AggregateResolver<TTable extends Table> = (source: any, args: {
|
|
237
|
+
where?: Filters<TTable>;
|
|
238
|
+
}, context: any, info: GraphQLResolveInfo) => Promise<Record<string, any>>;
|
|
159
239
|
type DeleteResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: DeleteArgs<TTable>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
|
|
160
240
|
type QueriesCore<TSchemaTables extends Record<string, Table>, TSchemaRelations extends Record<string, Relations>, TInputs extends Record<string, GraphQLInputObjectType>, TOutputs extends Record<string, GraphQLObjectType>> = {
|
|
161
241
|
[TName in keyof TSchemaTables as TName extends string ? `${Uncapitalize<TName>}` : never]: TName extends string ? {
|
|
@@ -173,6 +253,9 @@ type QueriesCore<TSchemaTables extends Record<string, Table>, TSchemaRelations e
|
|
|
173
253
|
where: {
|
|
174
254
|
type: TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never;
|
|
175
255
|
};
|
|
256
|
+
distinct: {
|
|
257
|
+
type: GraphQLList<GraphQLNonNull<GraphQLEnumType>>;
|
|
258
|
+
};
|
|
176
259
|
};
|
|
177
260
|
resolve: SelectResolver<TSchemaTables[TName], TSchemaTables, ExtractTableRelations<TSchemaTables[TName], TSchemaRelations> extends infer R ? R[keyof R] : never>;
|
|
178
261
|
} : never;
|
|
@@ -192,6 +275,16 @@ type QueriesCore<TSchemaTables extends Record<string, Table>, TSchemaRelations e
|
|
|
192
275
|
};
|
|
193
276
|
resolve: SelectSingleResolver<TSchemaTables[TName], TSchemaTables, ExtractTableRelations<TSchemaTables[TName], TSchemaRelations> extends infer R ? R[keyof R] : never>;
|
|
194
277
|
} : never;
|
|
278
|
+
} & {
|
|
279
|
+
[TName in keyof TSchemaTables as TName extends string ? `${Uncapitalize<TName>}Aggregate` : never]: TName extends string ? {
|
|
280
|
+
type: GraphQLNonNull<TOutputs[`${Capitalize<TName>}Aggregate`] extends GraphQLObjectType ? TOutputs[`${Capitalize<TName>}Aggregate`] : GraphQLObjectType>;
|
|
281
|
+
args: {
|
|
282
|
+
where: {
|
|
283
|
+
type: TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never;
|
|
284
|
+
};
|
|
285
|
+
};
|
|
286
|
+
resolve: AggregateResolver<TSchemaTables[TName]>;
|
|
287
|
+
} : never;
|
|
195
288
|
};
|
|
196
289
|
type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends Record<string, GraphQLInputObjectType>, TOutputs extends Record<string, GraphQLObjectType>, IsReturnless extends boolean> = {
|
|
197
290
|
[TName in keyof TSchemaTables as TName extends string ? `create${Capitalize<TName>}` : never]: TName extends string ? {
|
|
@@ -213,6 +306,32 @@ type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends
|
|
|
213
306
|
};
|
|
214
307
|
resolve: InsertResolver<TSchemaTables[TName], IsReturnless>;
|
|
215
308
|
} : never;
|
|
309
|
+
} & {
|
|
310
|
+
[TName in keyof TSchemaTables as TName extends string ? `upsert${Capitalize<TName>}` : never]?: TName extends string ? {
|
|
311
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[`${Capitalize<TName>}Item`]>>>;
|
|
312
|
+
args: {
|
|
313
|
+
values: {
|
|
314
|
+
type: GraphQLNonNull<GraphQLList<GraphQLNonNull<TInputs[`${Capitalize<TName>}InsertInput`]>>>;
|
|
315
|
+
};
|
|
316
|
+
onConflict: {
|
|
317
|
+
type: GraphQLInputObjectType;
|
|
318
|
+
};
|
|
319
|
+
};
|
|
320
|
+
resolve: UpsertArrResolver<TSchemaTables[TName], IsReturnless>;
|
|
321
|
+
} : never;
|
|
322
|
+
} & {
|
|
323
|
+
[TName in keyof TSchemaTables as TName extends string ? `upsert${Capitalize<TName>}Single` : never]?: TName extends string ? {
|
|
324
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[`${Capitalize<TName>}Item`];
|
|
325
|
+
args: {
|
|
326
|
+
values: {
|
|
327
|
+
type: GraphQLNonNull<TInputs[`${Capitalize<TName>}InsertInput`]>;
|
|
328
|
+
};
|
|
329
|
+
onConflict: {
|
|
330
|
+
type: GraphQLInputObjectType;
|
|
331
|
+
};
|
|
332
|
+
};
|
|
333
|
+
resolve: UpsertResolver<TSchemaTables[TName], IsReturnless>;
|
|
334
|
+
} : never;
|
|
216
335
|
} & {
|
|
217
336
|
[TName in keyof TSchemaTables as TName extends string ? `update${Capitalize<TName>}` : never]: TName extends string ? {
|
|
218
337
|
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[`${Capitalize<TName>}Item`]>>>;
|
|
@@ -248,6 +367,8 @@ type GeneratedInputs<TSchema extends Record<string, Table>> = {
|
|
|
248
367
|
};
|
|
249
368
|
type GeneratedOutputs<TSchema extends Record<string, Table>, IsReturnless extends boolean> = {
|
|
250
369
|
[TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}SelectItem` : never]: GraphQLObjectType;
|
|
370
|
+
} & {
|
|
371
|
+
[TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}Aggregate` : never]: GraphQLObjectType;
|
|
251
372
|
} & (IsReturnless extends true ? {
|
|
252
373
|
MutationReturn: GraphQLObjectType;
|
|
253
374
|
} : {
|
|
@@ -272,6 +393,32 @@ type GeneratedData<TDatabase extends AnyDrizzleDB<any>> = {
|
|
|
272
393
|
schema: GraphQLSchema;
|
|
273
394
|
entities: GeneratedEntities<TDatabase>;
|
|
274
395
|
};
|
|
396
|
+
/**
|
|
397
|
+
* Per-feature switches for what `buildSchema` generates. Every flag defaults to `true`.
|
|
398
|
+
* See {@link BuildSchemaConfig.features}.
|
|
399
|
+
*/
|
|
400
|
+
type SchemaFeatures = {
|
|
401
|
+
/** `<plural>Aggregate` root queries and the aggregate output types. @default true */
|
|
402
|
+
aggregates?: boolean;
|
|
403
|
+
/** `<relation>Aggregate` fields on object types, for to-many relations. @default true */
|
|
404
|
+
relationAggregates?: boolean;
|
|
405
|
+
/** The `distinct` argument on list queries. @default true */
|
|
406
|
+
distinct?: boolean;
|
|
407
|
+
/** `create<Table>` / `create<Table>Single` mutations. @default true */
|
|
408
|
+
insert?: boolean;
|
|
409
|
+
/** `update<Table>` mutations. @default true */
|
|
410
|
+
update?: boolean;
|
|
411
|
+
/** `delete<Table>` mutations. @default true */
|
|
412
|
+
delete?: boolean;
|
|
413
|
+
/**
|
|
414
|
+
* `upsert<Table>` / `upsert<Table>Single` mutations — insert, or update the row that
|
|
415
|
+
* already holds the same unique key. Off unless asked for, so an existing schema does
|
|
416
|
+
* not grow new mutations on upgrade.
|
|
417
|
+
*
|
|
418
|
+
* @default false
|
|
419
|
+
*/
|
|
420
|
+
upsert?: boolean;
|
|
421
|
+
};
|
|
275
422
|
type BuildSchemaConfig = {
|
|
276
423
|
/**
|
|
277
424
|
* Determines whether generated mutations will be passed to returned schema.
|
|
@@ -304,7 +451,7 @@ type BuildSchemaConfig = {
|
|
|
304
451
|
/**
|
|
305
452
|
* Customizes query name prefixes for generated GraphQL operations.
|
|
306
453
|
*
|
|
307
|
-
* @default { insert: 'create', delete: 'delete', update: 'update' }
|
|
454
|
+
* @default { insert: 'create', delete: 'delete', update: 'update', upsert: 'upsert' }
|
|
308
455
|
*/
|
|
309
456
|
prefixes?: {
|
|
310
457
|
/** Prefix for insert mutations (e.g., 'users' -> 'createUsers') */
|
|
@@ -313,6 +460,8 @@ type BuildSchemaConfig = {
|
|
|
313
460
|
delete?: string;
|
|
314
461
|
/** Prefix for update mutations (e.g., 'users' -> 'updateUsers') */
|
|
315
462
|
update?: string;
|
|
463
|
+
/** Prefix for upsert mutations (e.g., 'users' -> 'upsertUsers') */
|
|
464
|
+
upsert?: string;
|
|
316
465
|
};
|
|
317
466
|
/**
|
|
318
467
|
* Customizes query name suffixes for generated GraphQL operations.
|
|
@@ -328,8 +477,40 @@ type BuildSchemaConfig = {
|
|
|
328
477
|
/**
|
|
329
478
|
* When true, insert mutations will use onConflictDoNothing() to silently
|
|
330
479
|
* ignore duplicate key violations. Defaults to false (conflicts throw errors).
|
|
480
|
+
*
|
|
481
|
+
* PostgreSQL and SQLite only — MySQL's insert builder has no equivalent, so the flag is
|
|
482
|
+
* ignored there and conflicts keep throwing.
|
|
483
|
+
*
|
|
484
|
+
* @deprecated Build-wide and unconditional: a request cannot opt out of it, and a
|
|
485
|
+
* swallowed insert returns `null` with no indication why. Turn on `features.upsert` and
|
|
486
|
+
* pass `onConflict: { action: NOTHING }` per request instead. This flag keeps working
|
|
487
|
+
* until the next major.
|
|
331
488
|
*/
|
|
332
489
|
conflictDoNothing?: boolean;
|
|
490
|
+
/**
|
|
491
|
+
* Turns individual generated features off.
|
|
492
|
+
*
|
|
493
|
+
* Every flag defaults to `true` except `upsert`, which is opt-in: a build with no
|
|
494
|
+
* `features` block generates exactly what it generated before this option existed.
|
|
495
|
+
* Turning one off removes both the schema surface it adds and the work behind it.
|
|
496
|
+
*
|
|
497
|
+
* ```ts
|
|
498
|
+
* buildSchema(db, {
|
|
499
|
+
* features: {
|
|
500
|
+
* aggregates: false, // no `<plural>Aggregate` root queries
|
|
501
|
+
* relationAggregates: false, // no `<relation>Aggregate` fields on object types
|
|
502
|
+
* distinct: false, // no `distinct` argument on list queries
|
|
503
|
+
* delete: false, // no delete mutations
|
|
504
|
+
* upsert: true, // opt in to `upsert<Table>` mutations
|
|
505
|
+
* },
|
|
506
|
+
* });
|
|
507
|
+
* ```
|
|
508
|
+
*
|
|
509
|
+
* Turning off every mutation feature omits the `Mutation` type entirely, exactly as
|
|
510
|
+
* `mutations: false` does. Query-side features can all be off — the list and single
|
|
511
|
+
* queries are always generated, so `Query` is never empty.
|
|
512
|
+
*/
|
|
513
|
+
features?: SchemaFeatures;
|
|
333
514
|
/**
|
|
334
515
|
* Optional mapper from table key to singular/plural name pair.
|
|
335
516
|
* When provided for a table, overrides the default (table key) naming for GraphQL type names,
|
|
@@ -377,8 +558,40 @@ type BuildSchemaConfig = {
|
|
|
377
558
|
* @default true
|
|
378
559
|
*/
|
|
379
560
|
eagerLoadRelations?: boolean | ((tableName: string, relationName: string) => boolean);
|
|
561
|
+
/**
|
|
562
|
+
* Called for every error thrown by a generated resolver, before it reaches the client.
|
|
563
|
+
*
|
|
564
|
+
* Return an error to surface that one instead. Return nothing to fall through to the
|
|
565
|
+
* default handling, which makes this a pure logging hook:
|
|
566
|
+
*
|
|
567
|
+
* ```ts
|
|
568
|
+
* buildSchema(db, { onError: (error) => { logger.error(error) } })
|
|
569
|
+
* ```
|
|
570
|
+
*
|
|
571
|
+
* The default passes through errors drizzle-graphql raises itself (bad filter, missing
|
|
572
|
+
* values, invalid date, …) and replaces everything else — driver and database errors —
|
|
573
|
+
* with a generic `Internal server error`, keeping the original on `originalError` so it
|
|
574
|
+
* is still available to server-side logging. Database messages routinely name tables,
|
|
575
|
+
* columns, constraints and the values that violated them, which is not something a
|
|
576
|
+
* public API should hand back.
|
|
577
|
+
*
|
|
578
|
+
* To surface raw database errors instead (useful in development):
|
|
579
|
+
*
|
|
580
|
+
* ```ts
|
|
581
|
+
* buildSchema(db, { onError: (error) => error as Error })
|
|
582
|
+
* ```
|
|
583
|
+
*/
|
|
584
|
+
onError?: (error: unknown) => unknown;
|
|
380
585
|
};
|
|
381
586
|
|
|
587
|
+
/**
|
|
588
|
+
* A 64-bit integer. Always transported as a decimal string, in both directions, so no value
|
|
589
|
+
* is ever silently rounded by JSON's double-precision numbers. `graphql-scalars`' own
|
|
590
|
+
* `GraphQLBigInt` is deliberately not used: it emits numbers for safe integers and strings
|
|
591
|
+
* for everything else, so a client cannot know which it will get.
|
|
592
|
+
*/
|
|
593
|
+
declare const GraphQLBigIntString: GraphQLScalarType<string, string>;
|
|
594
|
+
|
|
382
595
|
declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
|
|
383
596
|
|
|
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 };
|
|
597
|
+
export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type DeleteResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ 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 { GraphQLFieldResolver, GraphQLResolveInfo, GraphQLSchema, GraphQLInputObjectType, GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType } from 'graphql';
|
|
5
|
+
import { GraphQLFieldResolver, GraphQLResolveInfo, GraphQLSchema, GraphQLInputObjectType, GraphQLObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType, GraphQLEnumType } from 'graphql';
|
|
6
|
+
export { GraphQLDate, GraphQLDateTime, GraphQLJSON, GraphQLUUID } from 'graphql-scalars';
|
|
6
7
|
|
|
7
8
|
type TableNamedRelations = {
|
|
8
9
|
relation: Relation;
|
|
@@ -89,6 +90,23 @@ type RelationResolverFactory = (params: {
|
|
|
89
90
|
relEntry: TableNamedRelations;
|
|
90
91
|
isOne: boolean;
|
|
91
92
|
}) => GraphQLFieldResolver<any, any> | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Key on the GraphQL context object under which a caller can place a Drizzle transaction
|
|
95
|
+
* (or any other executor: a pooled connection, a logging proxy). Every generated resolver
|
|
96
|
+
* reads it at resolve time and runs its statements there instead of on the database the
|
|
97
|
+
* schema was built from, which is what lets several mutations in one request share a
|
|
98
|
+
* transaction and lets a query see that transaction's uncommitted rows:
|
|
99
|
+
*
|
|
100
|
+
* ```ts
|
|
101
|
+
* await db.transaction(async (tx) => {
|
|
102
|
+
* await graphql({ schema, source, contextValue: { [drizzleExecutorKey]: tx } });
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* Registered with `Symbol.for` so the ESM and CJS builds of this package agree on it when
|
|
107
|
+
* both end up loaded in one process.
|
|
108
|
+
*/
|
|
109
|
+
declare const drizzleExecutorKey: unique symbol;
|
|
92
110
|
/**
|
|
93
111
|
* Creates a RelationResolverFactory that generates field-level resolvers for each relation.
|
|
94
112
|
* Each resolver:
|
|
@@ -97,9 +115,41 @@ type RelationResolverFactory = (params: {
|
|
|
97
115
|
* 3. Otherwise batches all sibling resolver calls within the same GraphQL execution tick
|
|
98
116
|
* into a single IN-clause query, eliminating N+1 database round-trips.
|
|
99
117
|
*/
|
|
100
|
-
declare const createRelationResolverFactory: (db: any, tables: Record<string, Table
|
|
118
|
+
declare const createRelationResolverFactory: (db: any, tables: Record<string, Table>, filterCtx?: RelationFilterBase) => RelationResolverFactory;
|
|
101
119
|
declare const extractOrderBy: <TTable extends Table, TArgs extends OrderByArgs<any> = OrderByArgs<TTable>>(table: TTable, orderArgs: TArgs) => SQL[];
|
|
102
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Everything `extractFilters` needs to turn a relation key in a `where` argument into a
|
|
122
|
+
* correlated subquery. Omitted by callers that don't generate relation filters, in which case
|
|
123
|
+
* relation keys can't appear in the input to begin with.
|
|
124
|
+
*/
|
|
125
|
+
interface RelationFilterContext {
|
|
126
|
+
/** Every table in the schema, keyed by its schema key. */
|
|
127
|
+
tables: Record<string, Table>;
|
|
128
|
+
/** Relations keyed by table schema key, then relation name. */
|
|
129
|
+
relationMap: Record<string, Record<string, TableNamedRelations>>;
|
|
130
|
+
/**
|
|
131
|
+
* Schema key of the table being filtered. Not always the same as the `tableName` label
|
|
132
|
+
* used in error messages (relation `where` callbacks pass the relation name there).
|
|
133
|
+
*/
|
|
134
|
+
tableKey: string;
|
|
135
|
+
/** Shared counter making every subquery alias unique within one extraction. */
|
|
136
|
+
aliases?: {
|
|
137
|
+
n: number;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The build-scoped half of {@link RelationFilterContext}. Created once per generated schema and
|
|
142
|
+
* handed to every resolver, which adds the table it is filtering.
|
|
143
|
+
*/
|
|
144
|
+
type RelationFilterBase = Pick<RelationFilterContext, 'tables' | 'relationMap'>;
|
|
145
|
+
declare const extractFilters: <TTable extends Table>(table: TTable, tableName: string, filters: Filters<TTable>, relationCtx?: RelationFilterContext) => SQL | undefined;
|
|
146
|
+
/**
|
|
147
|
+
* Default for `config.onError`: keeps drizzle-graphql's own errors, which are written for
|
|
148
|
+
* the client, and replaces driver/database errors with a generic message. Their text names
|
|
149
|
+
* tables, columns, constraints and offending values, none of which belongs in a response.
|
|
150
|
+
* The original is preserved on `originalError` for server-side logging.
|
|
151
|
+
*/
|
|
152
|
+
declare const defaultErrorMapper: (error: unknown) => unknown;
|
|
103
153
|
|
|
104
154
|
type Relations<TTable extends string = string, TConfig extends Record<string, Relation> = Record<string, Relation>> = {
|
|
105
155
|
table: {
|
|
@@ -144,6 +194,22 @@ type UpdateArgs<TTable extends Table> = Partial<{
|
|
|
144
194
|
set: GetRemappedTableUpdateDataType<TTable>;
|
|
145
195
|
where?: Filters<TTable>;
|
|
146
196
|
}>;
|
|
197
|
+
/**
|
|
198
|
+
* The `onConflict` argument of the generated upsert mutations.
|
|
199
|
+
*
|
|
200
|
+
* `target` and `where` exist on PostgreSQL and SQLite only: MySQL's
|
|
201
|
+
* `ON DUPLICATE KEY UPDATE` fires on whichever unique key was violated and takes no
|
|
202
|
+
* predicate, so neither field is generated there.
|
|
203
|
+
*/
|
|
204
|
+
type UpsertConflictArgs<TTable extends Table> = {
|
|
205
|
+
action?: 'UPDATE' | 'NOTHING';
|
|
206
|
+
target?: string[];
|
|
207
|
+
update?: string[];
|
|
208
|
+
where?: Filters<TTable>;
|
|
209
|
+
};
|
|
210
|
+
type UpsertArgs<TTable extends Table, isSingle extends boolean> = InsertArgs<TTable, isSingle> & {
|
|
211
|
+
onConflict?: UpsertConflictArgs<TTable>;
|
|
212
|
+
};
|
|
147
213
|
type DeleteArgs<TTable extends Table> = {
|
|
148
214
|
where?: Filters<TTable>;
|
|
149
215
|
};
|
|
@@ -153,9 +219,23 @@ type SelectResolver<TTable extends Table, TTables extends Record<string, Table>,
|
|
|
153
219
|
type SelectSingleResolver<TTable extends Table, TTables extends Record<string, Table>, TRelations extends Record<string, Relation>> = (source: any, args: Partial<QueryArgs<TTable, true>>, context: any, info: GraphQLResolveInfo) => Promise<(keyof TRelations extends infer RelKey ? RelKey extends string ? GetRemappedTableDataType<TTable> & {
|
|
154
220
|
[K in RelKey]: TRelations[K] extends One<string> ? GetRemappedTableDataType<ExtractTableByName<TTables, TRelations[K]['referencedTableName']> extends infer T ? T[keyof T] : never> | null : TRelations[K] extends Many<string> ? Array<GetRemappedTableDataType<ExtractTableByName<TTables, TRelations[K]['referencedTableName']> extends infer T ? T[keyof T] : never>> : never;
|
|
155
221
|
} : GetRemappedTableDataType<TTable> : GetRemappedTableDataType<TTable>) | null>;
|
|
156
|
-
|
|
157
|
-
type
|
|
222
|
+
/** Resolver for `create<Table>Single`: one row in, one row (or `undefined`) out. */
|
|
223
|
+
type InsertResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: Partial<InsertArgs<TTable, true>>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
|
|
224
|
+
/** Resolver for `create<Table>`: an array of rows in, an array of rows out. */
|
|
225
|
+
type InsertArrResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: Partial<InsertArgs<TTable, false>>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? Array<GetRemappedTableDataType<TTable>> : MutationReturnlessResult>;
|
|
158
226
|
type UpdateResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: UpdateArgs<TTable>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
|
|
227
|
+
/** Resolver for `upsert<Table>Single`. */
|
|
228
|
+
type UpsertResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: Partial<UpsertArgs<TTable, true>>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
|
|
229
|
+
/** Resolver for `upsert<Table>`. */
|
|
230
|
+
type UpsertArrResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: Partial<UpsertArgs<TTable, false>>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? Array<GetRemappedTableDataType<TTable>> : MutationReturnlessResult>;
|
|
231
|
+
/**
|
|
232
|
+
* Resolver for a table's generated aggregate query (`<plural>Aggregate`).
|
|
233
|
+
* Returns only the requested aggregations: `count` plus per-column `avg` / `sum`
|
|
234
|
+
* (numeric columns, as Float) and `min` / `max` (orderable columns, as the column's type).
|
|
235
|
+
*/
|
|
236
|
+
type AggregateResolver<TTable extends Table> = (source: any, args: {
|
|
237
|
+
where?: Filters<TTable>;
|
|
238
|
+
}, context: any, info: GraphQLResolveInfo) => Promise<Record<string, any>>;
|
|
159
239
|
type DeleteResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: DeleteArgs<TTable>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
|
|
160
240
|
type QueriesCore<TSchemaTables extends Record<string, Table>, TSchemaRelations extends Record<string, Relations>, TInputs extends Record<string, GraphQLInputObjectType>, TOutputs extends Record<string, GraphQLObjectType>> = {
|
|
161
241
|
[TName in keyof TSchemaTables as TName extends string ? `${Uncapitalize<TName>}` : never]: TName extends string ? {
|
|
@@ -173,6 +253,9 @@ type QueriesCore<TSchemaTables extends Record<string, Table>, TSchemaRelations e
|
|
|
173
253
|
where: {
|
|
174
254
|
type: TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never;
|
|
175
255
|
};
|
|
256
|
+
distinct: {
|
|
257
|
+
type: GraphQLList<GraphQLNonNull<GraphQLEnumType>>;
|
|
258
|
+
};
|
|
176
259
|
};
|
|
177
260
|
resolve: SelectResolver<TSchemaTables[TName], TSchemaTables, ExtractTableRelations<TSchemaTables[TName], TSchemaRelations> extends infer R ? R[keyof R] : never>;
|
|
178
261
|
} : never;
|
|
@@ -192,6 +275,16 @@ type QueriesCore<TSchemaTables extends Record<string, Table>, TSchemaRelations e
|
|
|
192
275
|
};
|
|
193
276
|
resolve: SelectSingleResolver<TSchemaTables[TName], TSchemaTables, ExtractTableRelations<TSchemaTables[TName], TSchemaRelations> extends infer R ? R[keyof R] : never>;
|
|
194
277
|
} : never;
|
|
278
|
+
} & {
|
|
279
|
+
[TName in keyof TSchemaTables as TName extends string ? `${Uncapitalize<TName>}Aggregate` : never]: TName extends string ? {
|
|
280
|
+
type: GraphQLNonNull<TOutputs[`${Capitalize<TName>}Aggregate`] extends GraphQLObjectType ? TOutputs[`${Capitalize<TName>}Aggregate`] : GraphQLObjectType>;
|
|
281
|
+
args: {
|
|
282
|
+
where: {
|
|
283
|
+
type: TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never;
|
|
284
|
+
};
|
|
285
|
+
};
|
|
286
|
+
resolve: AggregateResolver<TSchemaTables[TName]>;
|
|
287
|
+
} : never;
|
|
195
288
|
};
|
|
196
289
|
type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends Record<string, GraphQLInputObjectType>, TOutputs extends Record<string, GraphQLObjectType>, IsReturnless extends boolean> = {
|
|
197
290
|
[TName in keyof TSchemaTables as TName extends string ? `create${Capitalize<TName>}` : never]: TName extends string ? {
|
|
@@ -213,6 +306,32 @@ type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends
|
|
|
213
306
|
};
|
|
214
307
|
resolve: InsertResolver<TSchemaTables[TName], IsReturnless>;
|
|
215
308
|
} : never;
|
|
309
|
+
} & {
|
|
310
|
+
[TName in keyof TSchemaTables as TName extends string ? `upsert${Capitalize<TName>}` : never]?: TName extends string ? {
|
|
311
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[`${Capitalize<TName>}Item`]>>>;
|
|
312
|
+
args: {
|
|
313
|
+
values: {
|
|
314
|
+
type: GraphQLNonNull<GraphQLList<GraphQLNonNull<TInputs[`${Capitalize<TName>}InsertInput`]>>>;
|
|
315
|
+
};
|
|
316
|
+
onConflict: {
|
|
317
|
+
type: GraphQLInputObjectType;
|
|
318
|
+
};
|
|
319
|
+
};
|
|
320
|
+
resolve: UpsertArrResolver<TSchemaTables[TName], IsReturnless>;
|
|
321
|
+
} : never;
|
|
322
|
+
} & {
|
|
323
|
+
[TName in keyof TSchemaTables as TName extends string ? `upsert${Capitalize<TName>}Single` : never]?: TName extends string ? {
|
|
324
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[`${Capitalize<TName>}Item`];
|
|
325
|
+
args: {
|
|
326
|
+
values: {
|
|
327
|
+
type: GraphQLNonNull<TInputs[`${Capitalize<TName>}InsertInput`]>;
|
|
328
|
+
};
|
|
329
|
+
onConflict: {
|
|
330
|
+
type: GraphQLInputObjectType;
|
|
331
|
+
};
|
|
332
|
+
};
|
|
333
|
+
resolve: UpsertResolver<TSchemaTables[TName], IsReturnless>;
|
|
334
|
+
} : never;
|
|
216
335
|
} & {
|
|
217
336
|
[TName in keyof TSchemaTables as TName extends string ? `update${Capitalize<TName>}` : never]: TName extends string ? {
|
|
218
337
|
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[`${Capitalize<TName>}Item`]>>>;
|
|
@@ -248,6 +367,8 @@ type GeneratedInputs<TSchema extends Record<string, Table>> = {
|
|
|
248
367
|
};
|
|
249
368
|
type GeneratedOutputs<TSchema extends Record<string, Table>, IsReturnless extends boolean> = {
|
|
250
369
|
[TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}SelectItem` : never]: GraphQLObjectType;
|
|
370
|
+
} & {
|
|
371
|
+
[TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}Aggregate` : never]: GraphQLObjectType;
|
|
251
372
|
} & (IsReturnless extends true ? {
|
|
252
373
|
MutationReturn: GraphQLObjectType;
|
|
253
374
|
} : {
|
|
@@ -272,6 +393,32 @@ type GeneratedData<TDatabase extends AnyDrizzleDB<any>> = {
|
|
|
272
393
|
schema: GraphQLSchema;
|
|
273
394
|
entities: GeneratedEntities<TDatabase>;
|
|
274
395
|
};
|
|
396
|
+
/**
|
|
397
|
+
* Per-feature switches for what `buildSchema` generates. Every flag defaults to `true`.
|
|
398
|
+
* See {@link BuildSchemaConfig.features}.
|
|
399
|
+
*/
|
|
400
|
+
type SchemaFeatures = {
|
|
401
|
+
/** `<plural>Aggregate` root queries and the aggregate output types. @default true */
|
|
402
|
+
aggregates?: boolean;
|
|
403
|
+
/** `<relation>Aggregate` fields on object types, for to-many relations. @default true */
|
|
404
|
+
relationAggregates?: boolean;
|
|
405
|
+
/** The `distinct` argument on list queries. @default true */
|
|
406
|
+
distinct?: boolean;
|
|
407
|
+
/** `create<Table>` / `create<Table>Single` mutations. @default true */
|
|
408
|
+
insert?: boolean;
|
|
409
|
+
/** `update<Table>` mutations. @default true */
|
|
410
|
+
update?: boolean;
|
|
411
|
+
/** `delete<Table>` mutations. @default true */
|
|
412
|
+
delete?: boolean;
|
|
413
|
+
/**
|
|
414
|
+
* `upsert<Table>` / `upsert<Table>Single` mutations — insert, or update the row that
|
|
415
|
+
* already holds the same unique key. Off unless asked for, so an existing schema does
|
|
416
|
+
* not grow new mutations on upgrade.
|
|
417
|
+
*
|
|
418
|
+
* @default false
|
|
419
|
+
*/
|
|
420
|
+
upsert?: boolean;
|
|
421
|
+
};
|
|
275
422
|
type BuildSchemaConfig = {
|
|
276
423
|
/**
|
|
277
424
|
* Determines whether generated mutations will be passed to returned schema.
|
|
@@ -304,7 +451,7 @@ type BuildSchemaConfig = {
|
|
|
304
451
|
/**
|
|
305
452
|
* Customizes query name prefixes for generated GraphQL operations.
|
|
306
453
|
*
|
|
307
|
-
* @default { insert: 'create', delete: 'delete', update: 'update' }
|
|
454
|
+
* @default { insert: 'create', delete: 'delete', update: 'update', upsert: 'upsert' }
|
|
308
455
|
*/
|
|
309
456
|
prefixes?: {
|
|
310
457
|
/** Prefix for insert mutations (e.g., 'users' -> 'createUsers') */
|
|
@@ -313,6 +460,8 @@ type BuildSchemaConfig = {
|
|
|
313
460
|
delete?: string;
|
|
314
461
|
/** Prefix for update mutations (e.g., 'users' -> 'updateUsers') */
|
|
315
462
|
update?: string;
|
|
463
|
+
/** Prefix for upsert mutations (e.g., 'users' -> 'upsertUsers') */
|
|
464
|
+
upsert?: string;
|
|
316
465
|
};
|
|
317
466
|
/**
|
|
318
467
|
* Customizes query name suffixes for generated GraphQL operations.
|
|
@@ -328,8 +477,40 @@ type BuildSchemaConfig = {
|
|
|
328
477
|
/**
|
|
329
478
|
* When true, insert mutations will use onConflictDoNothing() to silently
|
|
330
479
|
* ignore duplicate key violations. Defaults to false (conflicts throw errors).
|
|
480
|
+
*
|
|
481
|
+
* PostgreSQL and SQLite only — MySQL's insert builder has no equivalent, so the flag is
|
|
482
|
+
* ignored there and conflicts keep throwing.
|
|
483
|
+
*
|
|
484
|
+
* @deprecated Build-wide and unconditional: a request cannot opt out of it, and a
|
|
485
|
+
* swallowed insert returns `null` with no indication why. Turn on `features.upsert` and
|
|
486
|
+
* pass `onConflict: { action: NOTHING }` per request instead. This flag keeps working
|
|
487
|
+
* until the next major.
|
|
331
488
|
*/
|
|
332
489
|
conflictDoNothing?: boolean;
|
|
490
|
+
/**
|
|
491
|
+
* Turns individual generated features off.
|
|
492
|
+
*
|
|
493
|
+
* Every flag defaults to `true` except `upsert`, which is opt-in: a build with no
|
|
494
|
+
* `features` block generates exactly what it generated before this option existed.
|
|
495
|
+
* Turning one off removes both the schema surface it adds and the work behind it.
|
|
496
|
+
*
|
|
497
|
+
* ```ts
|
|
498
|
+
* buildSchema(db, {
|
|
499
|
+
* features: {
|
|
500
|
+
* aggregates: false, // no `<plural>Aggregate` root queries
|
|
501
|
+
* relationAggregates: false, // no `<relation>Aggregate` fields on object types
|
|
502
|
+
* distinct: false, // no `distinct` argument on list queries
|
|
503
|
+
* delete: false, // no delete mutations
|
|
504
|
+
* upsert: true, // opt in to `upsert<Table>` mutations
|
|
505
|
+
* },
|
|
506
|
+
* });
|
|
507
|
+
* ```
|
|
508
|
+
*
|
|
509
|
+
* Turning off every mutation feature omits the `Mutation` type entirely, exactly as
|
|
510
|
+
* `mutations: false` does. Query-side features can all be off — the list and single
|
|
511
|
+
* queries are always generated, so `Query` is never empty.
|
|
512
|
+
*/
|
|
513
|
+
features?: SchemaFeatures;
|
|
333
514
|
/**
|
|
334
515
|
* Optional mapper from table key to singular/plural name pair.
|
|
335
516
|
* When provided for a table, overrides the default (table key) naming for GraphQL type names,
|
|
@@ -377,8 +558,40 @@ type BuildSchemaConfig = {
|
|
|
377
558
|
* @default true
|
|
378
559
|
*/
|
|
379
560
|
eagerLoadRelations?: boolean | ((tableName: string, relationName: string) => boolean);
|
|
561
|
+
/**
|
|
562
|
+
* Called for every error thrown by a generated resolver, before it reaches the client.
|
|
563
|
+
*
|
|
564
|
+
* Return an error to surface that one instead. Return nothing to fall through to the
|
|
565
|
+
* default handling, which makes this a pure logging hook:
|
|
566
|
+
*
|
|
567
|
+
* ```ts
|
|
568
|
+
* buildSchema(db, { onError: (error) => { logger.error(error) } })
|
|
569
|
+
* ```
|
|
570
|
+
*
|
|
571
|
+
* The default passes through errors drizzle-graphql raises itself (bad filter, missing
|
|
572
|
+
* values, invalid date, …) and replaces everything else — driver and database errors —
|
|
573
|
+
* with a generic `Internal server error`, keeping the original on `originalError` so it
|
|
574
|
+
* is still available to server-side logging. Database messages routinely name tables,
|
|
575
|
+
* columns, constraints and the values that violated them, which is not something a
|
|
576
|
+
* public API should hand back.
|
|
577
|
+
*
|
|
578
|
+
* To surface raw database errors instead (useful in development):
|
|
579
|
+
*
|
|
580
|
+
* ```ts
|
|
581
|
+
* buildSchema(db, { onError: (error) => error as Error })
|
|
582
|
+
* ```
|
|
583
|
+
*/
|
|
584
|
+
onError?: (error: unknown) => unknown;
|
|
380
585
|
};
|
|
381
586
|
|
|
587
|
+
/**
|
|
588
|
+
* A 64-bit integer. Always transported as a decimal string, in both directions, so no value
|
|
589
|
+
* is ever silently rounded by JSON's double-precision numbers. `graphql-scalars`' own
|
|
590
|
+
* `GraphQLBigInt` is deliberately not used: it emits numbers for safe integers and strings
|
|
591
|
+
* for everything else, so a client cannot know which it will get.
|
|
592
|
+
*/
|
|
593
|
+
declare const GraphQLBigIntString: GraphQLScalarType<string, string>;
|
|
594
|
+
|
|
382
595
|
declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
|
|
383
596
|
|
|
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 };
|
|
597
|
+
export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type DeleteResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
|