@vantreeseba/drizzle-graphql 9.1.0 → 10.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 +13 -0
- package/dist/index.cjs +7591 -7879
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1539 -1535
- package/dist/index.d.ts +1539 -1535
- package/dist/index.js +7553 -7946
- package/dist/index.js.map +1 -1
- package/package.json +10 -11
- package/dist/README.md +0 -2216
- package/dist/package.json +0 -108
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { Column,
|
|
2
|
-
import { MySqlAsyncDatabase } from
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { Column, Many, One, Relation, SQL, Table, TablesRelationalConfig } from "drizzle-orm";
|
|
2
|
+
import { MySqlAsyncDatabase } from "drizzle-orm/mysql-core";
|
|
3
|
+
import "drizzle-orm/mysql-core/query-builders/query";
|
|
4
|
+
import { PgAsyncDatabase } from "drizzle-orm/pg-core";
|
|
5
|
+
import "drizzle-orm/pg-core/query-builders/query";
|
|
6
|
+
import { SQLiteAsyncDatabase } from "drizzle-orm/sqlite-core";
|
|
7
|
+
import "drizzle-orm/sqlite-core/query-builders/query";
|
|
8
|
+
import { ASTNode, GraphQLEnumType, GraphQLError, GraphQLFieldResolver, GraphQLInputObjectType, GraphQLInputType, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLOutputType, GraphQLResolveInfo, GraphQLScalarType, GraphQLSchema } from "graphql";
|
|
9
|
+
import { GraphQLDate, GraphQLDateTime, GraphQLJSON, GraphQLUUID } from "graphql-scalars";
|
|
10
|
+
//#region src/util/extensions.d.ts
|
|
9
11
|
/**
|
|
10
12
|
* The identity a generated field publishes about itself, under `extensions.drizzle`.
|
|
11
13
|
*
|
|
@@ -27,48 +29,48 @@ type DrizzleFieldOperation = 'select' | 'insert' | 'update' | 'updateMany' | 'up
|
|
|
27
29
|
type DrizzleTargetArg = 'where' | 'values' | 'updates';
|
|
28
30
|
/** `extensions.drizzle` on a generated field. */
|
|
29
31
|
type DrizzleFieldExtension = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
32
|
+
/** The Drizzle schema key of the table the field reads or writes. */
|
|
33
|
+
table: string;
|
|
34
|
+
kind: Exclude<DrizzleFieldKind, 'type'>;
|
|
35
|
+
operation: DrizzleFieldOperation;
|
|
36
|
+
/** Whether the field resolves to one row (or one aggregate) rather than a list. */
|
|
37
|
+
single: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Which argument names the rows: `where` for select/update/delete/aggregate, `values`
|
|
40
|
+
* for insert and upsert, `updates` for the batch update's per-entry `{ where, set }`.
|
|
41
|
+
* Absent when the field takes no such argument.
|
|
42
|
+
*/
|
|
43
|
+
targetArg?: DrizzleTargetArg;
|
|
44
|
+
/**
|
|
45
|
+
* Primary-key property names of `table`, in schema order. Empty when the table declares
|
|
46
|
+
* no primary key. Carried here so {@link identifyRows} works from the field alone.
|
|
47
|
+
*/
|
|
48
|
+
primaryKey: readonly string[];
|
|
49
|
+
/**
|
|
50
|
+
* For `operation: 'delete'` on a soft-deleting table that opted into `hardDelete`: the
|
|
51
|
+
* field takes a `hard` argument that issues a real `DELETE` rather than writing the marker.
|
|
52
|
+
* Absent everywhere else, so a wrapper can gate purging without parsing arguments.
|
|
53
|
+
*/
|
|
54
|
+
hardDelete?: boolean;
|
|
55
|
+
/** For `kind: 'relation'` and `operation: 'relationAggregate'`: the relation's name. */
|
|
56
|
+
relation?: string;
|
|
57
|
+
/** For `kind: 'relation'` and `operation: 'relationAggregate'`: the table it hangs off. */
|
|
58
|
+
parentTable?: string;
|
|
57
59
|
};
|
|
58
60
|
/** `extensions.drizzle` on a generated object type. */
|
|
59
61
|
type DrizzleTypeExtension = {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
/** The Drizzle schema key this type was generated from. */
|
|
63
|
+
table: string;
|
|
64
|
+
kind: 'type';
|
|
65
|
+
/** Primary-key property names of `table`, in schema order. Empty when there is none. */
|
|
66
|
+
primaryKey: readonly string[];
|
|
65
67
|
};
|
|
66
68
|
type DrizzleExtension = DrizzleFieldExtension | DrizzleTypeExtension;
|
|
67
69
|
/** Anything carrying GraphQL `extensions` — a field config, a field, or a named type. */
|
|
68
70
|
type WithExtensions = {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
extensions?: {
|
|
72
|
+
drizzle?: unknown;
|
|
73
|
+
} | null;
|
|
72
74
|
} | null | undefined;
|
|
73
75
|
/**
|
|
74
76
|
* Reads the `drizzle` extension off a field or type, typed. Returns `undefined` for
|
|
@@ -80,22 +82,22 @@ declare const drizzleExtension: (target: WithExtensions) => DrizzleExtension | u
|
|
|
80
82
|
declare const isDrizzleFieldExtension: (value: DrizzleExtension | undefined) => value is DrizzleFieldExtension;
|
|
81
83
|
/** The rows a field's arguments name. */
|
|
82
84
|
type IdentifiedRows = {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
85
|
+
/** The Drizzle schema key of the table being read or written. */
|
|
86
|
+
table: string;
|
|
87
|
+
/** Primary-key property names, in schema order. */
|
|
88
|
+
primaryKey: readonly string[];
|
|
89
|
+
/** One entry per identified row: the primary-key values, keyed by property name. */
|
|
90
|
+
rows: Record<string, unknown>[];
|
|
91
|
+
/**
|
|
92
|
+
* Whether `rows` is exactly the set the operation affects.
|
|
93
|
+
*
|
|
94
|
+
* `false` means the arguments do not pin the rows down — an insert whose key the
|
|
95
|
+
* database generates, a `where` that filters on something other than the primary key,
|
|
96
|
+
* a plural update with no filter at all, or a table with no primary key. `rows` is then
|
|
97
|
+
* a best-effort subset-free superset: every entry in it is a row the key values name,
|
|
98
|
+
* but other filters may narrow the real set further, and it may be empty.
|
|
99
|
+
*/
|
|
100
|
+
complete: boolean;
|
|
99
101
|
};
|
|
100
102
|
/**
|
|
101
103
|
* The rows a generated field's arguments are about, as primary-key values.
|
|
@@ -115,53 +117,56 @@ type IdentifiedRows = {
|
|
|
115
117
|
* `complete` before treating `rows` as the affected set — see {@link IdentifiedRows}.
|
|
116
118
|
*/
|
|
117
119
|
declare const identifyRows: (field: WithExtensions, args: Record<string, unknown> | undefined) => IdentifiedRows | undefined;
|
|
118
|
-
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/util/builders/common/errors.d.ts
|
|
119
122
|
/**
|
|
120
123
|
* The classification of an error drizzle-graphql raised itself, published as
|
|
121
124
|
* `extensions.code`. A consumer maps these onto its own vocabulary; the prose is written for
|
|
122
125
|
* a client to read and may be reworded in any release, so it is not something to match on.
|
|
123
126
|
*/
|
|
124
|
-
type DrizzleErrorCode =
|
|
127
|
+
type DrizzleErrorCode =
|
|
125
128
|
/** A `Single` write's `where` matched more than one row, so nothing was written. */
|
|
126
|
-
'DRIZZLE_MULTI_ROW_MATCH'
|
|
129
|
+
'DRIZZLE_MULTI_ROW_MATCH' |
|
|
127
130
|
/** A write that refuses to run unbounded was given no `where`, or one matching every row. */
|
|
128
|
-
|
|
131
|
+
'DRIZZLE_WHERE_REQUIRED' |
|
|
129
132
|
/** The requested `limit` is above the maximum the field's limit policy allows. */
|
|
130
|
-
|
|
133
|
+
'DRIZZLE_LIMIT_EXCEEDED' |
|
|
131
134
|
/** A write's `values` / `set` carried nothing to write. */
|
|
132
|
-
|
|
135
|
+
'DRIZZLE_NO_VALUES' |
|
|
133
136
|
/** An insert reported no row back, so there is nothing to return or attach. */
|
|
134
|
-
|
|
137
|
+
'DRIZZLE_NO_ROW_RETURNED' |
|
|
135
138
|
/** The driver reported no row count for a returnless write. */
|
|
136
|
-
|
|
139
|
+
'DRIZZLE_ROW_COUNT_UNAVAILABLE' |
|
|
137
140
|
/** A nested write was passed to a field that cannot run one. */
|
|
138
|
-
|
|
141
|
+
'DRIZZLE_NESTED_WRITES_UNSUPPORTED' |
|
|
139
142
|
/** A nested `create` / `connect` / `disconnect` / `set` operand was not usable. */
|
|
140
|
-
|
|
143
|
+
'DRIZZLE_NESTED_WRITE_INVALID' |
|
|
141
144
|
/** A `groupBy` named no column, or one that cannot be grouped by. */
|
|
142
|
-
|
|
145
|
+
'DRIZZLE_INVALID_GROUP_BY' |
|
|
143
146
|
/** An `after` cursor did not decode, or was issued for a different ordering. */
|
|
144
|
-
|
|
147
|
+
'DRIZZLE_INVALID_CURSOR' |
|
|
145
148
|
/** A `where` key was not a filter of the table, or a relation was used as one. */
|
|
146
|
-
|
|
149
|
+
'DRIZZLE_INVALID_FILTER' |
|
|
147
150
|
/** A column's update operations input held none, or more than one. */
|
|
148
|
-
|
|
151
|
+
'DRIZZLE_INVALID_UPDATE_OPERATION' |
|
|
149
152
|
/** A configured `scope` hook returned something that is not a predicate. */
|
|
150
|
-
|
|
153
|
+
'DRIZZLE_INVALID_SCOPE' |
|
|
151
154
|
/** An `orderBy` named something that cannot be ordered by in this query. */
|
|
152
|
-
|
|
155
|
+
'DRIZZLE_INVALID_ORDER_BY' |
|
|
153
156
|
/** `distinct` was asked for where it cannot be applied. */
|
|
154
|
-
|
|
157
|
+
'DRIZZLE_INVALID_DISTINCT' |
|
|
155
158
|
/** An `onConflict` named a target or update column the upsert cannot use. */
|
|
156
|
-
|
|
159
|
+
'DRIZZLE_INVALID_ON_CONFLICT' |
|
|
157
160
|
/** A written value could not be converted to what its column stores. */
|
|
158
|
-
|
|
161
|
+
'DRIZZLE_INVALID_INPUT_VALUE' |
|
|
162
|
+
/** An update's `set` gave a column that cannot hold null an explicit null. */
|
|
163
|
+
'DRIZZLE_NOT_NULL' |
|
|
159
164
|
/** A write's input named a key that is not a column of the table. */
|
|
160
|
-
|
|
165
|
+
'DRIZZLE_UNKNOWN_COLUMN' |
|
|
161
166
|
/** A stored value could not be represented by the scalar that transports it. */
|
|
162
|
-
|
|
167
|
+
'DRIZZLE_UNREPRESENTABLE_VALUE' |
|
|
163
168
|
/** The request's shared mutation transaction was rolled back, so this field never ran. */
|
|
164
|
-
|
|
169
|
+
'DRIZZLE_TRANSACTION_ABORTED';
|
|
165
170
|
/**
|
|
166
171
|
* What an error was about, published as `extensions.drizzle` beside the code — the runtime
|
|
167
172
|
* half of the `extensions.drizzle` markers a generated field carries.
|
|
@@ -172,13 +177,13 @@ type DrizzleErrorCode =
|
|
|
172
177
|
* of. The name the client asked for is already in the error's `path`.
|
|
173
178
|
*/
|
|
174
179
|
type DrizzleErrorContext = {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
/** The Drizzle schema key of the table the field reads or writes. */
|
|
181
|
+
table?: string;
|
|
182
|
+
operation?: DrizzleFieldOperation;
|
|
183
|
+
/** The generated field's own name, pre-rename. */
|
|
184
|
+
field?: string;
|
|
185
|
+
/** For a relation field: the relation's name. */
|
|
186
|
+
relation?: string;
|
|
182
187
|
};
|
|
183
188
|
/**
|
|
184
189
|
* A `GraphQLError` carrying its context as data. The message says what went wrong, in prose
|
|
@@ -186,9 +191,9 @@ type DrizzleErrorContext = {
|
|
|
186
191
|
* table, operation and generated field it came from.
|
|
187
192
|
*/
|
|
188
193
|
declare const drizzleError: (message: string, { code, nodes, ...context }: DrizzleErrorContext & {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
194
|
+
code: DrizzleErrorCode;
|
|
195
|
+
/** The AST the error is about, where the throw site has one — it becomes the `locations`. */
|
|
196
|
+
nodes?: ASTNode | readonly ASTNode[];
|
|
192
197
|
}) => GraphQLError;
|
|
193
198
|
/**
|
|
194
199
|
* Default for `config.onError`: keeps drizzle-graphql's own errors, which are written for
|
|
@@ -197,12 +202,13 @@ declare const drizzleError: (message: string, { code, nodes, ...context }: Drizz
|
|
|
197
202
|
* The original is preserved on `originalError` for server-side logging.
|
|
198
203
|
*/
|
|
199
204
|
declare const defaultErrorMapper: (error: unknown) => unknown;
|
|
200
|
-
|
|
205
|
+
//#endregion
|
|
206
|
+
//#region src/util/builders/common/limits.d.ts
|
|
201
207
|
/** {@link BuildSchemaConfig.limits} resolved for one table. `undefined` means no policy. */
|
|
202
208
|
type ResolvedLimitPolicy = {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
209
|
+
defaultLimit: number | undefined;
|
|
210
|
+
maxLimit: number | undefined;
|
|
211
|
+
clampToMax: boolean;
|
|
206
212
|
};
|
|
207
213
|
/**
|
|
208
214
|
* Looks up the limit policy for a table by its Drizzle schema key. Built once per schema by
|
|
@@ -216,15 +222,16 @@ type LimitPolicyFor = (tableName: string) => ResolvedLimitPolicy | undefined;
|
|
|
216
222
|
* returns.
|
|
217
223
|
*/
|
|
218
224
|
type DefaultOrderByFor = (tableName: string) => Record<string, any> | undefined;
|
|
219
|
-
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region src/util/type-converter/types.d.ts
|
|
220
227
|
/**
|
|
221
228
|
* A scalar override for one column. A bare scalar applies to both directions; the object form
|
|
222
229
|
* lets output (object type, aggregate min/max) and input (create/update inputs, filter operands)
|
|
223
230
|
* use different scalars — or override only one side, leaving the other on built-in detection.
|
|
224
231
|
*/
|
|
225
232
|
type ScalarOverride = GraphQLScalarType | {
|
|
226
|
-
|
|
227
|
-
|
|
233
|
+
output?: GraphQLScalarType;
|
|
234
|
+
input?: GraphQLScalarType;
|
|
228
235
|
};
|
|
229
236
|
/**
|
|
230
237
|
* Declarative per-table, per-column scalar overrides. Keys are the Drizzle schema keys —
|
|
@@ -233,18 +240,18 @@ type ScalarOverride = GraphQLScalarType | {
|
|
|
233
240
|
type ScalarOverridesConfig = Record<string, Record<string, ScalarOverride>>;
|
|
234
241
|
/** Context handed to {@link ColumnTypeMapper} alongside the column itself. */
|
|
235
242
|
type ColumnTypeMapperInfo = {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
243
|
+
/** The table's key in the Drizzle schema object. */
|
|
244
|
+
tableName: string;
|
|
245
|
+
/** The column's property name on the table object. */
|
|
246
|
+
columnName: string;
|
|
247
|
+
/**
|
|
248
|
+
* The GraphQL type built-in detection would use for output positions (without nullability
|
|
249
|
+
* wrapping). `undefined` when detection has no mapping for the column's data type — the
|
|
250
|
+
* mapper is then the only way to give the column a type.
|
|
251
|
+
*/
|
|
252
|
+
defaultType: GraphQLOutputType | undefined;
|
|
253
|
+
/** The input-position counterpart of `defaultType`. */
|
|
254
|
+
defaultInputType: GraphQLInputType | undefined;
|
|
248
255
|
};
|
|
249
256
|
/**
|
|
250
257
|
* Rule-based scalar mapping, called once per column at build time. Return a scalar (or
|
|
@@ -254,20 +261,20 @@ type ColumnTypeMapperInfo = {
|
|
|
254
261
|
type ColumnTypeMapper = (column: Column, info: ColumnTypeMapperInfo) => ScalarOverride | undefined;
|
|
255
262
|
/** Everything an {@link EnumNameMapper} needs to name — or opt a column out of — a generated enum type. */
|
|
256
263
|
type EnumNameInfo = {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
264
|
+
/**
|
|
265
|
+
* The name the enum type was declared with (`pgEnum('status', …)`), shared by every column
|
|
266
|
+
* that uses it. `undefined` for an inline value list (`text({ enum: [...] })`,
|
|
267
|
+
* `mysqlEnum(...)`), which belongs to the one column that declares it.
|
|
268
|
+
*/
|
|
269
|
+
enumName: string | undefined;
|
|
270
|
+
/** The Postgres schema the named enum was declared in, when it declares one. */
|
|
271
|
+
schema: string | undefined;
|
|
272
|
+
/** The table's key in the Drizzle schema object. */
|
|
273
|
+
tableName: string;
|
|
274
|
+
/** The column's property name on the table object. */
|
|
275
|
+
columnName: string;
|
|
276
|
+
/** The enum's values, in declaration order. */
|
|
277
|
+
values: readonly string[];
|
|
271
278
|
};
|
|
272
279
|
/**
|
|
273
280
|
* Names a generated GraphQL enum type. Return `undefined` to keep the default name. See
|
|
@@ -276,10 +283,10 @@ type EnumNameInfo = {
|
|
|
276
283
|
type EnumNameMapper = (info: EnumNameInfo) => string | undefined;
|
|
277
284
|
/** Context handed to the documentation and deprecation hooks alongside the column itself. */
|
|
278
285
|
type ColumnDocInfo = {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
286
|
+
/** The table's key in the Drizzle schema object. */
|
|
287
|
+
tableName: string;
|
|
288
|
+
/** The column's property name on the table object. */
|
|
289
|
+
columnName: string;
|
|
283
290
|
};
|
|
284
291
|
/**
|
|
285
292
|
* Supplies the GraphQL `description` for a generated column field. See
|
|
@@ -304,117 +311,109 @@ type RelationDescriber = (tableName: string, relationName: string) => string | u
|
|
|
304
311
|
* descriptions at all.
|
|
305
312
|
*/
|
|
306
313
|
type SchemaDocs = {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
314
|
+
describeColumn?: ColumnDescriber;
|
|
315
|
+
describeTable?: TableDescriber;
|
|
316
|
+
describeRelation?: RelationDescriber;
|
|
317
|
+
deprecateColumn?: ColumnDeprecator;
|
|
311
318
|
};
|
|
312
|
-
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region src/util/builders/types.d.ts
|
|
313
321
|
type TableNamedRelations = {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
+
relation: Relation;
|
|
323
|
+
targetTableName: string;
|
|
324
|
+
/**
|
|
325
|
+
* Property names of the target table's primary key, resolved at build time (composite
|
|
326
|
+
* keys included, via the dialect's getTableConfig). Used to default paginated relations
|
|
327
|
+
* to a deterministic PK order. Empty when the target has no detectable primary key.
|
|
328
|
+
*/
|
|
329
|
+
targetPkNames?: readonly string[];
|
|
322
330
|
};
|
|
323
331
|
type ColTypeIsNull<TColumn extends Column, TColType> = TColumn['_']['notNull'] extends true ? TColType : TColType | null;
|
|
324
332
|
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;
|
|
325
333
|
type GetColumnGqlDataType<TColumn extends Column> = TColumn['dataType'] extends 'boolean' ? ColTypeIsNull<TColumn, boolean> : TColumn['dataType'] extends 'json' ? TColumn['columnType'] extends 'PgGeometryObject' ? ColTypeIsNull<TColumn, {
|
|
326
|
-
|
|
327
|
-
|
|
334
|
+
x: number;
|
|
335
|
+
y: number;
|
|
328
336
|
}> : ColTypeIsNull<TColumn, string> : TColumn['dataType'] extends 'date' | 'string' | 'bigint' ? TColumn['enumValues'] extends [string, ...string[]] ? ColTypeIsNull<TColumn, TColumn['enumValues'][number]> : ColTypeIsNull<TColumn, string> : TColumn['dataType'] extends 'number' ? ColTypeIsNull<TColumn, number> : TColumn['dataType'] extends 'buffer' ? ColTypeIsNull<TColumn, number[]> : TColumn['dataType'] extends 'array' ? TColumn['columnType'] extends 'PgVector' ? ColTypeIsNull<TColumn, number[]> : TColumn['columnType'] extends 'PgGeometry' ? ColTypeIsNullOrUndefinedWithDefault<TColumn, [number, number]> : ColTypeIsNull<TColumn, Array<GetColumnGqlDataType<TColumn extends {
|
|
329
|
-
|
|
330
|
-
} ? TColumn['baseColumn'] : never> extends infer InnerColType ? InnerColType extends null | undefined ? never : InnerColType : never>> : never;
|
|
337
|
+
baseColumn: Column;
|
|
338
|
+
} ? TColumn['baseColumn'] : never> extends (infer InnerColType) ? InnerColType extends null | undefined ? never : InnerColType : never>> : never;
|
|
331
339
|
type GetColumnGqlInsertDataType<TColumn extends Column> = TColumn['dataType'] extends 'boolean' ? ColTypeIsNullOrUndefinedWithDefault<TColumn, boolean> : TColumn['dataType'] extends 'json' ? TColumn['columnType'] extends 'PgGeometryObject' ? ColTypeIsNullOrUndefinedWithDefault<TColumn, {
|
|
332
|
-
|
|
333
|
-
|
|
340
|
+
x: number;
|
|
341
|
+
y: number;
|
|
334
342
|
}> : ColTypeIsNullOrUndefinedWithDefault<TColumn, string> : TColumn['dataType'] extends 'date' | 'string' | 'bigint' ? TColumn['enumValues'] extends [string, ...string[]] ? ColTypeIsNullOrUndefinedWithDefault<TColumn, TColumn['enumValues'][number]> : ColTypeIsNullOrUndefinedWithDefault<TColumn, string> : TColumn['dataType'] extends 'number' ? ColTypeIsNullOrUndefinedWithDefault<TColumn, number> : TColumn['dataType'] extends 'buffer' ? ColTypeIsNullOrUndefinedWithDefault<TColumn, number[]> : TColumn['dataType'] extends 'array' ? TColumn['columnType'] extends 'PgVector' ? ColTypeIsNullOrUndefinedWithDefault<TColumn, number[]> : TColumn['columnType'] extends 'PgGeometry' ? ColTypeIsNullOrUndefinedWithDefault<TColumn, [number, number]> : ColTypeIsNullOrUndefinedWithDefault<TColumn, Array<GetColumnGqlDataType<TColumn extends {
|
|
335
|
-
|
|
336
|
-
} ? TColumn['baseColumn'] : never> extends infer InnerColType ? InnerColType extends null | undefined ? never : InnerColType : never>> : never;
|
|
343
|
+
baseColumn: Column;
|
|
344
|
+
} ? TColumn['baseColumn'] : never> extends (infer InnerColType) ? InnerColType extends null | undefined ? never : InnerColType : never>> : never;
|
|
337
345
|
type GetColumnGqlUpdateDataType<TColumn extends Column> = TColumn['dataType'] extends 'boolean' ? boolean | null | undefined : TColumn['dataType'] extends 'json' ? TColumn['columnType'] extends 'PgGeometryObject' ? {
|
|
338
|
-
|
|
339
|
-
|
|
346
|
+
x: number;
|
|
347
|
+
y: number;
|
|
340
348
|
} | null | undefined : string | null | undefined : TColumn['dataType'] extends 'date' | 'string' | 'bigint' ? TColumn['enumValues'] extends [string, ...string[]] ? TColumn['enumValues'][number] | null | undefined : string | null | undefined : TColumn['dataType'] extends 'number' ? number | null | undefined : TColumn['dataType'] extends 'buffer' ? number[] | null | undefined : TColumn['dataType'] extends 'array' ? TColumn['columnType'] extends 'PgVector' ? number[] | null | undefined : TColumn['columnType'] extends 'PgGeometry' ? [number, number] | null | undefined : Array<GetColumnGqlDataType<TColumn extends {
|
|
341
|
-
|
|
342
|
-
} ? TColumn['baseColumn'] : never> extends infer InnerColType ? InnerColType extends null | undefined ? never : InnerColType : never> | null | undefined : never;
|
|
343
|
-
type GetRemappedTableDataType<TTable extends Table, TColumns extends TTable['_']['columns'] = TTable['_']['columns']> = {
|
|
344
|
-
|
|
345
|
-
};
|
|
346
|
-
type GetRemappedTableInsertDataType<TTable extends Table> = {
|
|
347
|
-
[K in keyof TTable['_']['columns']]: GetColumnGqlInsertDataType<TTable['_']['columns'][K]>;
|
|
348
|
-
};
|
|
349
|
-
type GetRemappedTableUpdateDataType<TTable extends Table> = {
|
|
350
|
-
[K in keyof TTable['_']['columns']]: GetColumnGqlUpdateDataType<TTable['_']['columns'][K]>;
|
|
351
|
-
};
|
|
349
|
+
baseColumn: Column;
|
|
350
|
+
} ? TColumn['baseColumn'] : never> extends (infer InnerColType) ? InnerColType extends null | undefined ? never : InnerColType : never> | null | undefined : never;
|
|
351
|
+
type GetRemappedTableDataType<TTable extends Table, TColumns extends TTable['_']['columns'] = TTable['_']['columns']> = { [K in keyof TColumns]: GetColumnGqlDataType<TColumns[K]>; };
|
|
352
|
+
type GetRemappedTableInsertDataType<TTable extends Table> = { [K in keyof TTable['_']['columns']]: GetColumnGqlInsertDataType<TTable['_']['columns'][K]>; };
|
|
353
|
+
type GetRemappedTableUpdateDataType<TTable extends Table> = { [K in keyof TTable['_']['columns']]: GetColumnGqlUpdateDataType<TTable['_']['columns'][K]>; };
|
|
352
354
|
type FilterColumnOperatorsCore<TColumn extends Column, TColType = GetColumnGqlDataType<TColumn>> = Partial<{
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}>;
|
|
392
|
-
type FiltersCore<TTable extends Table> = Partial<{
|
|
393
|
-
[Column in keyof TTable['_']['columns']]: FilterColumnOperatorsCore<TTable['_']['columns'][Column]>;
|
|
355
|
+
eq: TColType;
|
|
356
|
+
ne: TColType;
|
|
357
|
+
lt: TColType;
|
|
358
|
+
lte: TColType;
|
|
359
|
+
gt: TColType;
|
|
360
|
+
gte: TColType;
|
|
361
|
+
like: string;
|
|
362
|
+
notLike: string;
|
|
363
|
+
ilike: string;
|
|
364
|
+
notIlike: string;
|
|
365
|
+
startsWith: string;
|
|
366
|
+
endsWith: string;
|
|
367
|
+
/**
|
|
368
|
+
* String columns: safe substring match (`%`, `_` and `\` matched literally).
|
|
369
|
+
* JSON columns: structural containment (Postgres `@>` / MySQL JSON_CONTAINS).
|
|
370
|
+
*/
|
|
371
|
+
contains: string | TColType;
|
|
372
|
+
iStartsWith: string;
|
|
373
|
+
iEndsWith: string;
|
|
374
|
+
iContains: string;
|
|
375
|
+
inArray: Array<TColType>;
|
|
376
|
+
notInArray: Array<TColType>;
|
|
377
|
+
/** Array columns only: the array contains this element. */
|
|
378
|
+
has: TColType extends Array<infer TElement> ? TElement : never;
|
|
379
|
+
/** Array columns only: the array overlaps these elements (`&&`). */
|
|
380
|
+
hasSome: TColType extends Array<infer TElement> ? Array<TElement> : never;
|
|
381
|
+
/** Array columns only: the array contains all of these elements (`@>`). */
|
|
382
|
+
hasEvery: TColType extends Array<infer TElement> ? Array<TElement> : never;
|
|
383
|
+
/** Array columns only: when true, matches arrays with no elements. */
|
|
384
|
+
isEmpty: boolean;
|
|
385
|
+
isNull: boolean;
|
|
386
|
+
isNotNull: boolean;
|
|
387
|
+
/**
|
|
388
|
+
* String columns: compares every operator in this object case-insensitively
|
|
389
|
+
* (`lower(column)` against `lower(operand)`). Applies to the operators beside it only —
|
|
390
|
+
* a nested `AND`/`OR`/`NOT` branch sets its own.
|
|
391
|
+
*/
|
|
392
|
+
insensitive: boolean;
|
|
394
393
|
}>;
|
|
394
|
+
type FiltersCore<TTable extends Table> = Partial<{ [Column in keyof TTable['_']['columns']]: FilterColumnOperatorsCore<TTable['_']['columns'][Column]>; }>;
|
|
395
395
|
type Filters<TTable extends Table, TFilterType = FiltersCore<TTable>> = TFilterType & {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
};
|
|
400
|
-
type OrderByArgs<TTable extends Table> = {
|
|
401
|
-
[Key in keyof TTable['_']['columns']]?: {
|
|
402
|
-
direction: 'asc' | 'desc';
|
|
403
|
-
priority: number;
|
|
404
|
-
/**
|
|
405
|
-
* Where NULL values sort. Native NULLS FIRST/LAST on PostgreSQL and SQLite;
|
|
406
|
-
* emulated with an extra `IS NULL` sort key on MySQL.
|
|
407
|
-
*/
|
|
408
|
-
nulls?: 'first' | 'last';
|
|
409
|
-
/**
|
|
410
|
-
* Sort by the column's position in the `inArray` list the same request's `where` gives
|
|
411
|
-
* it, rather than by the column's own value. Requires that `inArray` filter; cannot be
|
|
412
|
-
* combined with `after` or `distinct`.
|
|
413
|
-
*/
|
|
414
|
-
matchFilterOrder?: boolean;
|
|
415
|
-
};
|
|
396
|
+
OR?: Filters<TTable, TFilterType>[];
|
|
397
|
+
AND?: Filters<TTable, TFilterType>[];
|
|
398
|
+
NOT?: Filters<TTable, TFilterType>;
|
|
416
399
|
};
|
|
417
|
-
|
|
400
|
+
type OrderByArgs<TTable extends Table> = { [Key in keyof TTable['_']['columns']]?: {
|
|
401
|
+
direction: 'asc' | 'desc';
|
|
402
|
+
priority: number;
|
|
403
|
+
/**
|
|
404
|
+
* Where NULL values sort. Native NULLS FIRST/LAST on PostgreSQL and SQLite;
|
|
405
|
+
* emulated with an extra `IS NULL` sort key on MySQL.
|
|
406
|
+
*/
|
|
407
|
+
nulls?: 'first' | 'last';
|
|
408
|
+
/**
|
|
409
|
+
* Sort by the column's position in the `inArray` list the same request's `where` gives
|
|
410
|
+
* it, rather than by the column's own value. Requires that `inArray` filter; cannot be
|
|
411
|
+
* combined with `after` or `distinct`.
|
|
412
|
+
*/
|
|
413
|
+
matchFilterOrder?: boolean;
|
|
414
|
+
}; };
|
|
415
|
+
//#endregion
|
|
416
|
+
//#region src/util/builders/common/type-names.d.ts
|
|
418
417
|
/**
|
|
419
418
|
* What a generated type is, so a name mapper can answer for one kind without matching on the
|
|
420
419
|
* spelling of the default name.
|
|
@@ -435,18 +434,18 @@ type OrderByArgs<TTable extends Table> = {
|
|
|
435
434
|
type GeneratedTypeKind = 'object' | 'filter' | 'listRelationFilter' | 'orderBy' | 'createInput' | 'updateInput' | 'updateManyInput' | 'nestedWriteInput' | 'fieldUpdateInput' | 'aggregate' | 'having' | 'groupBy' | 'groupKeys' | 'onConflict' | 'uniqueKey' | 'columnEnum' | 'columnFilter' | 'shared';
|
|
436
435
|
/** What a name mapper is told about the type it is being asked to name. */
|
|
437
436
|
interface GeneratedTypeInfo {
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
437
|
+
/** Which kind of generated type this is. */
|
|
438
|
+
kind: GeneratedTypeKind;
|
|
439
|
+
/** The name the library would use, before any prefix or suffix. */
|
|
440
|
+
defaultName: string;
|
|
441
|
+
/** The table key the type belongs to, where it belongs to one. */
|
|
442
|
+
table?: string;
|
|
443
|
+
/**
|
|
444
|
+
* The narrower thing the type is for, where the kind alone does not say: the aggregate
|
|
445
|
+
* operation (`sum`, `avg`, …), the relation a nested-write input is for, the scalar a
|
|
446
|
+
* column filter covers, the columns of a unique key.
|
|
447
|
+
*/
|
|
448
|
+
operation?: string;
|
|
450
449
|
}
|
|
451
450
|
/**
|
|
452
451
|
* Renames a generated type. Return `undefined` — or the same name — to keep the default,
|
|
@@ -454,41 +453,44 @@ interface GeneratedTypeInfo {
|
|
|
454
453
|
* build's prefix or suffix.
|
|
455
454
|
*/
|
|
456
455
|
type DerivedTypeNameMapper = (info: GeneratedTypeInfo) => string | undefined;
|
|
457
|
-
|
|
456
|
+
//#endregion
|
|
457
|
+
//#region src/util/builders/common/naming.d.ts
|
|
458
458
|
/** Optional mapper from table key to singular/plural name pair. Return undefined to use default naming for a table. */
|
|
459
459
|
type TypeNameMapper = (tableName: string) => {
|
|
460
|
-
|
|
461
|
-
|
|
460
|
+
singular: string;
|
|
461
|
+
plural: string;
|
|
462
462
|
} | undefined;
|
|
463
|
-
|
|
463
|
+
//#endregion
|
|
464
|
+
//#region src/util/builders/common/unique-keys.d.ts
|
|
464
465
|
/** A table's unique-key `where` fields: field name → the constraint's member property names. */
|
|
465
466
|
type UniqueKeyMap = Record<string, readonly string[]>;
|
|
466
|
-
|
|
467
|
+
//#endregion
|
|
468
|
+
//#region src/util/builders/common/relation-filters.d.ts
|
|
467
469
|
/**
|
|
468
470
|
* Everything `extractFilters` needs to turn a relation key in a `where` argument into a
|
|
469
471
|
* correlated subquery. Omitted by callers that don't generate relation filters, in which case
|
|
470
472
|
* relation keys can't appear in the input to begin with.
|
|
471
473
|
*/
|
|
472
474
|
interface RelationFilterContext {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
475
|
+
/** Every table in the schema, keyed by its schema key. */
|
|
476
|
+
tables: Record<string, Table>;
|
|
477
|
+
/** Relations keyed by table schema key, then relation name. */
|
|
478
|
+
relationMap: Record<string, Record<string, TableNamedRelations>>;
|
|
479
|
+
/**
|
|
480
|
+
* Schema key of the table being filtered. Not always the same as the `tableName` label
|
|
481
|
+
* used in error messages (relation `where` callbacks pass the relation name there).
|
|
482
|
+
*/
|
|
483
|
+
tableKey: string;
|
|
484
|
+
/** Shared counter making every subquery alias unique within one extraction. */
|
|
485
|
+
aliases?: {
|
|
486
|
+
n: number;
|
|
487
|
+
};
|
|
488
|
+
/**
|
|
489
|
+
* The compound-unique-key `where` fields of each table, keyed by table schema key. Only
|
|
490
|
+
* populated when `features.uniqueKeyFilters` generated them — a key field the build did not
|
|
491
|
+
* generate is an unknown filter key like any other.
|
|
492
|
+
*/
|
|
493
|
+
uniqueKeys?: Record<string, UniqueKeyMap>;
|
|
492
494
|
}
|
|
493
495
|
/**
|
|
494
496
|
* The build-scoped half of {@link RelationFilterContext}. Created once per generated schema and
|
|
@@ -496,45 +498,47 @@ interface RelationFilterContext {
|
|
|
496
498
|
*/
|
|
497
499
|
type RelationFilterBase = Pick<RelationFilterContext, 'tables' | 'relationMap' | 'uniqueKeys'>;
|
|
498
500
|
declare const extractFilters: <TTable extends Table>(table: TTable, tableName: string, filters: Filters<TTable>, relationCtx?: RelationFilterContext) => SQL | undefined;
|
|
499
|
-
|
|
501
|
+
//#endregion
|
|
502
|
+
//#region src/util/builders/common/write-hooks.d.ts
|
|
500
503
|
/** The write a hook is attached to. `restore` only exists for a soft-deleting table. */
|
|
501
504
|
type WriteOperation = 'insert' | 'update' | 'updateMany' | 'upsert' | 'delete' | 'restore';
|
|
502
505
|
/** What a write hook is handed. See {@link BuildSchemaConfig.onWrite}. */
|
|
503
506
|
type WriteHookPayload = {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
507
|
+
/** Drizzle schema key of the table being written. */
|
|
508
|
+
table: string;
|
|
509
|
+
operation: WriteOperation;
|
|
510
|
+
/** `'before'` runs ahead of the statement, `'after'` once it has returned. */
|
|
511
|
+
position: 'before' | 'after';
|
|
512
|
+
/** Whether the field writes a single row (`createUsersSingle`) or a list. */
|
|
513
|
+
single: boolean;
|
|
514
|
+
/** The field's GraphQL arguments, exactly as the resolver received them. */
|
|
515
|
+
args: any;
|
|
516
|
+
/**
|
|
517
|
+
* The rows the write produced, as the database returned them — before the output mapper,
|
|
518
|
+
* so values are database-shaped. Empty at the `before` position, and on MySQL, whose
|
|
519
|
+
* mutations return no rows.
|
|
520
|
+
*/
|
|
521
|
+
rows: any[];
|
|
522
|
+
context: any;
|
|
523
|
+
info: any;
|
|
524
|
+
/** The executor the mutation itself ran on. Throwing from the hook rolls it back. */
|
|
525
|
+
tx: any;
|
|
523
526
|
};
|
|
524
527
|
type WriteHook = (payload: WriteHookPayload) => void | Promise<void>;
|
|
525
528
|
type WriteHookPositions = {
|
|
526
|
-
|
|
527
|
-
|
|
529
|
+
before?: WriteHook;
|
|
530
|
+
after?: WriteHook;
|
|
528
531
|
};
|
|
529
532
|
type WriteHooks = WriteHook | WriteHookPositions;
|
|
530
533
|
/** Resolved, per-field hooks: `undefined` when the table registered none. */
|
|
531
534
|
type ResolvedWriteHooks = {
|
|
532
|
-
|
|
533
|
-
|
|
535
|
+
before?: WriteHook;
|
|
536
|
+
after?: WriteHook;
|
|
534
537
|
};
|
|
535
538
|
/** Build-time lookup of a table's hooks, installed on {@link TablePolicies}. */
|
|
536
539
|
type WriteHookFor = (tableName: string, operation: WriteOperation) => ResolvedWriteHooks | undefined;
|
|
537
|
-
|
|
540
|
+
//#endregion
|
|
541
|
+
//#region src/util/builders/common/policies.d.ts
|
|
538
542
|
/**
|
|
539
543
|
* A table's row-level scope: the predicate every generated read, update and delete on that
|
|
540
544
|
* table is narrowed by. See `BuildSchemaConfig.scope`.
|
|
@@ -559,30 +563,30 @@ type ScopeFor = (tableName: string) => ScopeHook | undefined;
|
|
|
559
563
|
* takes the NULL-means-alive reading only when no marker was configured.
|
|
560
564
|
*/
|
|
561
565
|
type SoftDeleteInfo = {
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
566
|
+
/** Property name of the column on the drizzle table — also the key on an aliased proxy. */
|
|
567
|
+
columnName: string;
|
|
568
|
+
column: Column;
|
|
569
|
+
nullable: boolean;
|
|
570
|
+
/** Evaluated per delete, so a timestamp form stamps the moment of the delete. */
|
|
571
|
+
writeDeleted: () => any;
|
|
572
|
+
/** Written by the restore mutation. */
|
|
573
|
+
writeRestored: any;
|
|
574
|
+
/**
|
|
575
|
+
* The constant that means "this row is deleted", when the config named one. Required on a
|
|
576
|
+
* NOT NULL column; optional on a nullable one, which otherwise reads NULL as alive.
|
|
577
|
+
*/
|
|
578
|
+
marker?: any;
|
|
579
|
+
/**
|
|
580
|
+
* Which reads hide marked rows by default — `'all'` (the table's own fields and every
|
|
581
|
+
* relation pointing at it) or `'root'` (its own fields only). See
|
|
582
|
+
* {@link relationDeletedDefault}.
|
|
583
|
+
*/
|
|
584
|
+
scope: 'root' | 'all';
|
|
585
|
+
/**
|
|
586
|
+
* Whether the delete mutations take a `hard` argument that issues a real `DELETE`. Off
|
|
587
|
+
* unless the table opts in, so the generated schema says which tables can be purged.
|
|
588
|
+
*/
|
|
589
|
+
hardDelete: boolean;
|
|
586
590
|
};
|
|
587
591
|
/** Build-time lookup: the soft-delete convention of a table, if it declares one. */
|
|
588
592
|
type SoftDeleteFor = (tableName: string) => SoftDeleteInfo | undefined;
|
|
@@ -597,18 +601,66 @@ type ContextValuesFor = (tableName: string) => Record<string, ContextValueHook>
|
|
|
597
601
|
* before doing any work — an unconfigured build generates exactly the SQL it did before.
|
|
598
602
|
*/
|
|
599
603
|
type TablePolicies = {
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
604
|
+
/** See `BuildSchemaConfig.scope`. */
|
|
605
|
+
scope?: ScopeFor;
|
|
606
|
+
/** See `BuildSchemaConfig.contextValues`. */
|
|
607
|
+
contextValues?: ContextValuesFor;
|
|
608
|
+
/** See `BuildSchemaConfig.softDelete`. */
|
|
609
|
+
softDelete?: SoftDeleteFor;
|
|
610
|
+
/** See `BuildSchemaConfig.onWrite`. */
|
|
611
|
+
onWrite?: WriteHookFor;
|
|
612
|
+
/** See `BuildSchemaConfig.defaults`. */
|
|
613
|
+
defaultOrderBy?: DefaultOrderByFor;
|
|
610
614
|
};
|
|
611
|
-
|
|
615
|
+
//#endregion
|
|
616
|
+
//#region src/util/parse-resolve-info.d.ts
|
|
617
|
+
/**
|
|
618
|
+
* The selections made against one concrete type, keyed by the *response key* — the field's
|
|
619
|
+
* alias when it has one, otherwise its name. A selection spanning an abstract type has one
|
|
620
|
+
* entry per type condition it was written against (the interface or union itself included,
|
|
621
|
+
* when fields were selected directly on it).
|
|
622
|
+
*/
|
|
623
|
+
interface FieldsByTypeName {
|
|
624
|
+
[typeName: string]: {
|
|
625
|
+
[responseKey: string]: ResolveTree;
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
/** One selected field: what was asked for, under what alias, with which arguments. */
|
|
629
|
+
interface ResolveTree {
|
|
630
|
+
/** The field name as declared in the schema. */
|
|
631
|
+
name: string;
|
|
632
|
+
/** The response key — the alias when the selection carried one, otherwise `name`. */
|
|
633
|
+
alias: string;
|
|
634
|
+
/** The field's arguments, coerced by graphql's own `getArgumentValues`. */
|
|
635
|
+
args: {
|
|
636
|
+
[argName: string]: unknown;
|
|
637
|
+
};
|
|
638
|
+
/** The field's own sub-selections, keyed by the type they were written against. */
|
|
639
|
+
fieldsByTypeName: FieldsByTypeName;
|
|
640
|
+
}
|
|
641
|
+
/** Options accepted by {@link parseResolveInfo}. */
|
|
642
|
+
interface ParseResolveInfoOptions {
|
|
643
|
+
/**
|
|
644
|
+
* Whether to descend into sub-selections and fragments. Defaults to `true`; `false` reads
|
|
645
|
+
* only the root field's own name, alias and arguments.
|
|
646
|
+
*/
|
|
647
|
+
deep?: boolean;
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Reads the selection under a resolver's own field out of its `info`, as a tree of
|
|
651
|
+
* {@link ResolveTree} nodes.
|
|
652
|
+
*
|
|
653
|
+
* ```ts
|
|
654
|
+
* const parsed = parseResolveInfo(info, { deep: true })!;
|
|
655
|
+
* const selected = parsed.fieldsByTypeName['Users']; // keyed by response key
|
|
656
|
+
* ```
|
|
657
|
+
*
|
|
658
|
+
* Returns `undefined` when the resolver's field produced no node at all, which in practice
|
|
659
|
+
* means `info` carried no field nodes.
|
|
660
|
+
*/
|
|
661
|
+
declare const parseResolveInfo: (info: GraphQLResolveInfo, options?: ParseResolveInfoOptions) => ResolveTree | undefined;
|
|
662
|
+
//#endregion
|
|
663
|
+
//#region src/util/builders/common/order-by.d.ts
|
|
612
664
|
/**
|
|
613
665
|
* Compiles an `orderBy` argument into ORDER BY expressions, highest priority first.
|
|
614
666
|
*
|
|
@@ -627,7 +679,8 @@ type TablePolicies = {
|
|
|
627
679
|
* inputs cannot contain relation keys may omit it.
|
|
628
680
|
*/
|
|
629
681
|
declare const extractOrderBy: <TTable extends Table, TArgs extends OrderByArgs<any> = OrderByArgs<TTable>>(table: TTable, orderArgs: TArgs, ctx?: RelationFilterContext, whereArgs?: Record<string, any>) => SQL[];
|
|
630
|
-
|
|
682
|
+
//#endregion
|
|
683
|
+
//#region src/util/builders/common/cursor.d.ts
|
|
631
684
|
/**
|
|
632
685
|
* Where a dialect's default sort places NULLs relative to non-NULL values:
|
|
633
686
|
* - `nulls-largest` — PostgreSQL: NULLs sort as the largest values (last in ASC, first in DESC).
|
|
@@ -636,7 +689,8 @@ declare const extractOrderBy: <TTable extends Table, TArgs extends OrderByArgs<a
|
|
|
636
689
|
* The keyset predicate has to agree with the dialect's ORDER BY, so each builder passes its own.
|
|
637
690
|
*/
|
|
638
691
|
type NullOrdering = 'nulls-largest' | 'nulls-smallest';
|
|
639
|
-
|
|
692
|
+
//#endregion
|
|
693
|
+
//#region src/util/builders/common/executor.d.ts
|
|
640
694
|
/**
|
|
641
695
|
* Key on the GraphQL context object under which a caller can place a Drizzle transaction
|
|
642
696
|
* (or any other executor: a pooled connection, a logging proxy). Every generated resolver
|
|
@@ -654,7 +708,8 @@ type NullOrdering = 'nulls-largest' | 'nulls-smallest';
|
|
|
654
708
|
* both end up loaded in one process.
|
|
655
709
|
*/
|
|
656
710
|
declare const drizzleExecutorKey: unique symbol;
|
|
657
|
-
|
|
711
|
+
//#endregion
|
|
712
|
+
//#region src/util/builders/common/relations.d.ts
|
|
658
713
|
/**
|
|
659
714
|
* Extracts the join column info from a drizzle-orm v1 Relation object.
|
|
660
715
|
* Returns the JS property name of the local column on the parent table and the
|
|
@@ -662,17 +717,18 @@ declare const drizzleExecutorKey: unique symbol;
|
|
|
662
717
|
* relation internals are not accessible.
|
|
663
718
|
*/
|
|
664
719
|
declare const extractRelationJoinColumns: (relEntry: TableNamedRelations, parentTable: Table, targetTable: Table) => {
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
720
|
+
localColPropName: string;
|
|
721
|
+
foreignCol: Column;
|
|
722
|
+
foreignColPropName: string;
|
|
668
723
|
} | undefined;
|
|
669
724
|
type RelationResolverFactory = (params: {
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
725
|
+
tableName: string;
|
|
726
|
+
relationName: string;
|
|
727
|
+
relEntry: TableNamedRelations;
|
|
728
|
+
isOne: boolean;
|
|
674
729
|
}) => GraphQLFieldResolver<any, any> | undefined;
|
|
675
|
-
|
|
730
|
+
//#endregion
|
|
731
|
+
//#region src/util/builders/common/relation-resolvers.d.ts
|
|
676
732
|
/**
|
|
677
733
|
* Creates a RelationResolverFactory that generates field-level resolvers for each relation.
|
|
678
734
|
* Each resolver:
|
|
@@ -688,16 +744,16 @@ type RelationResolverFactory = (params: {
|
|
|
688
744
|
* MySQL and SQLite.
|
|
689
745
|
*/
|
|
690
746
|
declare const createRelationResolverFactory: (db: any, tables: Record<string, Table>, nullOrdering: NullOrdering, filterCtx?: RelationFilterBase, limits?: LimitPolicyFor, policies?: TablePolicies) => RelationResolverFactory;
|
|
691
|
-
|
|
747
|
+
//#endregion
|
|
748
|
+
//#region src/types.d.ts
|
|
692
749
|
type Relations<TTable extends string = string, TConfig extends Record<string, Relation> = Record<string, Relation>> = {
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
};
|
|
750
|
+
table: {
|
|
751
|
+
_: {
|
|
752
|
+
name: TTable;
|
|
697
753
|
};
|
|
698
|
-
|
|
754
|
+
};
|
|
755
|
+
config: (helpers: unknown) => TConfig;
|
|
699
756
|
};
|
|
700
|
-
|
|
701
757
|
type AnyDrizzleDB<TSchema extends Record<string, any>> = PgAsyncDatabase<any, TSchema> | SQLiteAsyncDatabase<any, any, TSchema> | MySqlAsyncDatabase<any, TSchema>;
|
|
702
758
|
/**
|
|
703
759
|
* The tables a database handle knows about, keyed by their schema key.
|
|
@@ -709,51 +765,41 @@ type AnyDrizzleDB<TSchema extends Record<string, any>> = PgAsyncDatabase<any, TS
|
|
|
709
765
|
* The two branches differ in one detail: a module's members are `readonly`, a
|
|
710
766
|
* relations config's are not, so the derived entity types are `readonly` only on that path.
|
|
711
767
|
*/
|
|
712
|
-
type ExtractTables<TSchema extends Record<string, Table | unknown>> = TSchema extends TablesRelationalConfig ? {
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
};
|
|
717
|
-
type ExtractRelations<TSchema extends Record<string, Table | unknown>> = {
|
|
718
|
-
[K in keyof TSchema as TSchema[K] extends Relations ? K : never]: TSchema[K] extends Relations ? TSchema[K] : never;
|
|
719
|
-
};
|
|
720
|
-
type ExtractTableRelations<TTable extends Table, TSchemaRelations extends Record<string, Relations>> = {
|
|
721
|
-
[K in keyof TSchemaRelations as TSchemaRelations[K]['table']['_']['name'] extends TTable['_']['name'] ? K : never]: TSchemaRelations[K]['table']['_']['name'] extends TTable['_']['name'] ? TSchemaRelations[K] extends Relations<any, infer RelationConfig> ? RelationConfig : never : never;
|
|
722
|
-
};
|
|
723
|
-
type ExtractTableByName<TTableSchema extends Record<string, Table>, TName extends string> = {
|
|
724
|
-
[K in keyof TTableSchema as TTableSchema[K]['_']['name'] extends TName ? K : never]: TTableSchema[K]['_']['name'] extends TName ? TTableSchema[K] : never;
|
|
725
|
-
};
|
|
768
|
+
type ExtractTables<TSchema extends Record<string, Table | unknown>> = TSchema extends TablesRelationalConfig ? { [K in keyof TSchema]: TSchema[K]['table'] extends (infer TTable extends Table) ? TTable : never; } : { [K in keyof TSchema as TSchema[K] extends Table ? K : never]: TSchema[K] extends Table ? TSchema[K] : never; };
|
|
769
|
+
type ExtractRelations<TSchema extends Record<string, Table | unknown>> = { [K in keyof TSchema as TSchema[K] extends Relations ? K : never]: TSchema[K] extends Relations ? TSchema[K] : never; };
|
|
770
|
+
type ExtractTableRelations<TTable extends Table, TSchemaRelations extends Record<string, Relations>> = { [K in keyof TSchemaRelations as TSchemaRelations[K]['table']['_']['name'] extends TTable['_']['name'] ? K : never]: TSchemaRelations[K]['table']['_']['name'] extends TTable['_']['name'] ? TSchemaRelations[K] extends Relations<any, infer RelationConfig> ? RelationConfig : never : never; };
|
|
771
|
+
type ExtractTableByName<TTableSchema extends Record<string, Table>, TName extends string> = { [K in keyof TTableSchema as TTableSchema[K]['_']['name'] extends TName ? K : never]: TTableSchema[K]['_']['name'] extends TName ? TTableSchema[K] : never; };
|
|
726
772
|
type MutationReturnlessResult = {
|
|
727
|
-
|
|
773
|
+
isSuccess: boolean;
|
|
728
774
|
};
|
|
729
775
|
type QueryArgs<TTable extends Table, isSingle extends boolean> = Partial<(isSingle extends true ? {
|
|
730
|
-
|
|
776
|
+
offset: number;
|
|
731
777
|
} : {
|
|
732
|
-
|
|
733
|
-
|
|
778
|
+
offset: number;
|
|
779
|
+
limit: number;
|
|
734
780
|
}) & {
|
|
735
|
-
|
|
736
|
-
|
|
781
|
+
where: Filters<TTable>;
|
|
782
|
+
orderBy: OrderByArgs<TTable>;
|
|
737
783
|
}>;
|
|
738
784
|
type InsertArgs<TTable extends Table, isSingle extends boolean> = isSingle extends true ? {
|
|
739
|
-
|
|
785
|
+
values: GetRemappedTableInsertDataType<TTable>;
|
|
740
786
|
} : {
|
|
741
|
-
|
|
787
|
+
values: Array<GetRemappedTableInsertDataType<TTable>>;
|
|
742
788
|
};
|
|
743
789
|
type UpdateArgs<TTable extends Table> = Partial<{
|
|
744
|
-
|
|
745
|
-
|
|
790
|
+
set: GetRemappedTableUpdateDataType<TTable>;
|
|
791
|
+
where?: Filters<TTable>;
|
|
746
792
|
}>;
|
|
747
793
|
/**
|
|
748
794
|
* One entry of an `update<Table>Many` mutation: the rows `where` matches get this
|
|
749
795
|
* entry's `set` applied. An omitted `where` matches every row, same as `update<Table>`.
|
|
750
796
|
*/
|
|
751
797
|
type UpdateManyEntry<TTable extends Table> = {
|
|
752
|
-
|
|
753
|
-
|
|
798
|
+
where?: Filters<TTable>;
|
|
799
|
+
set: GetRemappedTableUpdateDataType<TTable>;
|
|
754
800
|
};
|
|
755
801
|
type UpdateManyArgs<TTable extends Table> = {
|
|
756
|
-
|
|
802
|
+
updates: Array<UpdateManyEntry<TTable>>;
|
|
757
803
|
};
|
|
758
804
|
/**
|
|
759
805
|
* The `onConflict` argument of the generated upsert mutations.
|
|
@@ -763,32 +809,28 @@ type UpdateManyArgs<TTable extends Table> = {
|
|
|
763
809
|
* predicate, so neither field is generated there.
|
|
764
810
|
*/
|
|
765
811
|
type UpsertConflictArgs<TTable extends Table> = {
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
812
|
+
action?: 'UPDATE' | 'NOTHING';
|
|
813
|
+
target?: string[];
|
|
814
|
+
update?: string[];
|
|
815
|
+
where?: Filters<TTable>;
|
|
770
816
|
};
|
|
771
817
|
type UpsertArgs<TTable extends Table, isSingle extends boolean> = InsertArgs<TTable, isSingle> & {
|
|
772
|
-
|
|
818
|
+
onConflict?: UpsertConflictArgs<TTable>;
|
|
773
819
|
};
|
|
774
820
|
type DeleteArgs<TTable extends Table> = {
|
|
775
|
-
|
|
821
|
+
where?: Filters<TTable>;
|
|
776
822
|
};
|
|
777
823
|
/** Arguments of `update<Table>Single` — unlike the plural variant, `where` is required. */
|
|
778
824
|
type UpdateSingleArgs<TTable extends Table> = {
|
|
779
|
-
|
|
780
|
-
|
|
825
|
+
set: GetRemappedTableUpdateDataType<TTable>;
|
|
826
|
+
where: Filters<TTable>;
|
|
781
827
|
};
|
|
782
828
|
/** Arguments of `delete<Table>Single` — unlike the plural variant, `where` is required. */
|
|
783
829
|
type DeleteSingleArgs<TTable extends Table> = {
|
|
784
|
-
|
|
830
|
+
where: Filters<TTable>;
|
|
785
831
|
};
|
|
786
|
-
type SelectResolver<TTable extends Table, TTables extends Record<string, Table>, TRelations extends Record<string, Relation>> = (source: any, args: Partial<QueryArgs<TTable, false>>, context: any, info: GraphQLResolveInfo) => Promise<keyof TRelations extends infer RelKey ? RelKey extends string ? Array<GetRemappedTableDataType<TTable> & {
|
|
787
|
-
|
|
788
|
-
}> : Array<GetRemappedTableDataType<TTable>> : Array<GetRemappedTableDataType<TTable>>>;
|
|
789
|
-
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> & {
|
|
790
|
-
[K in RelKey]: TRelations[K] extends One<infer TTargetName, any> ? GetRemappedTableDataType<ExtractTableByName<TTables, TTargetName> extends infer T ? T[keyof T] : never> | null : TRelations[K] extends Many<infer TTargetName> ? Array<GetRemappedTableDataType<ExtractTableByName<TTables, TTargetName> extends infer T ? T[keyof T] : never>> : never;
|
|
791
|
-
} : GetRemappedTableDataType<TTable> : GetRemappedTableDataType<TTable>) | null>;
|
|
832
|
+
type SelectResolver<TTable extends Table, TTables extends Record<string, Table>, TRelations extends Record<string, Relation>> = (source: any, args: Partial<QueryArgs<TTable, false>>, context: any, info: GraphQLResolveInfo) => Promise<keyof TRelations extends (infer RelKey) ? RelKey extends string ? Array<GetRemappedTableDataType<TTable> & { [K in RelKey]: TRelations[K] extends One<infer TTargetName, any> ? GetRemappedTableDataType<ExtractTableByName<TTables, TTargetName> extends (infer T) ? T[keyof T] : never> | null : TRelations[K] extends Many<infer TTargetName> ? Array<GetRemappedTableDataType<ExtractTableByName<TTables, TTargetName> extends (infer T) ? T[keyof T] : never>> : never; }> : Array<GetRemappedTableDataType<TTable>> : Array<GetRemappedTableDataType<TTable>>>;
|
|
833
|
+
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> & { [K in RelKey]: TRelations[K] extends One<infer TTargetName, any> ? GetRemappedTableDataType<ExtractTableByName<TTables, TTargetName> extends (infer T) ? T[keyof T] : never> | null : TRelations[K] extends Many<infer TTargetName> ? Array<GetRemappedTableDataType<ExtractTableByName<TTables, TTargetName> extends (infer T) ? T[keyof T] : never>> : never; } : GetRemappedTableDataType<TTable> : GetRemappedTableDataType<TTable>) | null>;
|
|
792
834
|
/** Resolver for `create<Table>Single`: one row in, one row (or `undefined`) out. */
|
|
793
835
|
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>;
|
|
794
836
|
/** Resolver for `create<Table>`: an array of rows in, an array of rows out. */
|
|
@@ -816,7 +858,7 @@ type UpsertArrResolver<TTable extends Table, IsReturnless extends boolean> = (so
|
|
|
816
858
|
* (numeric columns, as Float) and `min` / `max` (orderable columns, as the column's type).
|
|
817
859
|
*/
|
|
818
860
|
type AggregateResolver<TTable extends Table> = (source: any, args: {
|
|
819
|
-
|
|
861
|
+
where?: Filters<TTable>;
|
|
820
862
|
}, context: any, info: GraphQLResolveInfo) => Promise<Record<string, any>>;
|
|
821
863
|
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>;
|
|
822
864
|
/**
|
|
@@ -824,158 +866,134 @@ type DeleteResolver<TTable extends Table, IsReturnless extends boolean> = (sourc
|
|
|
824
866
|
* out. Throws before writing anything when `where` matches more than one row.
|
|
825
867
|
*/
|
|
826
868
|
type DeleteSingleResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: DeleteSingleArgs<TTable>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
|
|
827
|
-
type QueriesCore<TSchemaTables extends Record<string, Table>, TSchemaRelations extends Record<string, Relations>, TInputs extends Record<string, GraphQLInputObjectType>, TOutputs extends Record<string, GraphQLObjectType>> = {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
};
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
} & {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
};
|
|
956
|
-
resolve: UpdateSingleResolver<TSchemaTables[TName], IsReturnless>;
|
|
957
|
-
} : never;
|
|
958
|
-
} & {
|
|
959
|
-
[TName in keyof TSchemaTables as TName extends string ? `delete${Capitalize<TName>}` : never]: TName extends string ? {
|
|
960
|
-
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[Capitalize<TName>]>>>;
|
|
961
|
-
args: {
|
|
962
|
-
where: {
|
|
963
|
-
type: TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never;
|
|
964
|
-
};
|
|
965
|
-
};
|
|
966
|
-
resolve: DeleteResolver<TSchemaTables[TName], IsReturnless>;
|
|
967
|
-
} : never;
|
|
968
|
-
} & {
|
|
969
|
-
[TName in keyof TSchemaTables as TName extends string ? `delete${Capitalize<TName>}Single` : never]: TName extends string ? {
|
|
970
|
-
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[Capitalize<TName>];
|
|
971
|
-
args: {
|
|
972
|
-
where: {
|
|
973
|
-
type: GraphQLNonNull<TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never>;
|
|
974
|
-
};
|
|
975
|
-
};
|
|
976
|
-
resolve: DeleteSingleResolver<TSchemaTables[TName], IsReturnless>;
|
|
977
|
-
} : never;
|
|
978
|
-
};
|
|
869
|
+
type QueriesCore<TSchemaTables extends Record<string, Table>, TSchemaRelations extends Record<string, Relations>, TInputs extends Record<string, GraphQLInputObjectType>, TOutputs extends Record<string, GraphQLObjectType>> = { [TName in keyof TSchemaTables as TName extends string ? `${Uncapitalize<TName>}` : never]: TName extends string ? {
|
|
870
|
+
type: GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[Capitalize<TName>]>>>;
|
|
871
|
+
args: {
|
|
872
|
+
offset: {
|
|
873
|
+
type: GraphQLScalarType<number, number>;
|
|
874
|
+
};
|
|
875
|
+
limit: {
|
|
876
|
+
type: GraphQLScalarType<number, number>;
|
|
877
|
+
};
|
|
878
|
+
orderBy: {
|
|
879
|
+
type: TInputs[`${Capitalize<TName>}OrderBy`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}OrderBy`] : never;
|
|
880
|
+
};
|
|
881
|
+
where: {
|
|
882
|
+
type: TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never;
|
|
883
|
+
};
|
|
884
|
+
distinct: {
|
|
885
|
+
type: GraphQLList<GraphQLNonNull<GraphQLEnumType>>;
|
|
886
|
+
};
|
|
887
|
+
};
|
|
888
|
+
resolve: SelectResolver<TSchemaTables[TName], TSchemaTables, ExtractTableRelations<TSchemaTables[TName], TSchemaRelations> extends (infer R) ? R[keyof R] : never>;
|
|
889
|
+
} : never; } & { [TName in keyof TSchemaTables as TName extends string ? `${Uncapitalize<TName>}Single` : never]: TName extends string ? {
|
|
890
|
+
type: TOutputs[Capitalize<TName>];
|
|
891
|
+
args: {
|
|
892
|
+
offset: {
|
|
893
|
+
type: GraphQLScalarType<number, number>;
|
|
894
|
+
};
|
|
895
|
+
orderBy: {
|
|
896
|
+
type: TInputs[`${Capitalize<TName>}OrderBy`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}OrderBy`] : never;
|
|
897
|
+
};
|
|
898
|
+
where: {
|
|
899
|
+
type: TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never;
|
|
900
|
+
};
|
|
901
|
+
};
|
|
902
|
+
resolve: SelectSingleResolver<TSchemaTables[TName], TSchemaTables, ExtractTableRelations<TSchemaTables[TName], TSchemaRelations> extends (infer R) ? R[keyof R] : never>;
|
|
903
|
+
} : never; } & { [TName in keyof TSchemaTables as TName extends string ? `${Uncapitalize<TName>}Aggregate` : never]: TName extends string ? {
|
|
904
|
+
type: GraphQLNonNull<TOutputs[`${Capitalize<TName>}Aggregate`] extends GraphQLObjectType ? TOutputs[`${Capitalize<TName>}Aggregate`] : GraphQLObjectType>;
|
|
905
|
+
args: {
|
|
906
|
+
where: {
|
|
907
|
+
type: TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never;
|
|
908
|
+
};
|
|
909
|
+
};
|
|
910
|
+
resolve: AggregateResolver<TSchemaTables[TName]>;
|
|
911
|
+
} : never; };
|
|
912
|
+
type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends Record<string, GraphQLInputObjectType>, TOutputs extends Record<string, GraphQLObjectType>, IsReturnless extends boolean> = { [TName in keyof TSchemaTables as TName extends string ? `create${Capitalize<TName>}` : never]: TName extends string ? {
|
|
913
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[Capitalize<TName>]>>>;
|
|
914
|
+
args: {
|
|
915
|
+
values: {
|
|
916
|
+
type: GraphQLNonNull<GraphQLList<GraphQLNonNull<TInputs[`Create${Capitalize<TName>}Input`]>>>;
|
|
917
|
+
};
|
|
918
|
+
};
|
|
919
|
+
resolve: InsertArrResolver<TSchemaTables[TName], IsReturnless>;
|
|
920
|
+
} : never; } & { [TName in keyof TSchemaTables as TName extends string ? `create${Capitalize<TName>}Single` : never]: TName extends string ? {
|
|
921
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[Capitalize<TName>];
|
|
922
|
+
args: {
|
|
923
|
+
values: {
|
|
924
|
+
type: GraphQLNonNull<TInputs[`Create${Capitalize<TName>}Input`]>;
|
|
925
|
+
};
|
|
926
|
+
};
|
|
927
|
+
resolve: InsertResolver<TSchemaTables[TName], IsReturnless>;
|
|
928
|
+
} : never; } & { [TName in keyof TSchemaTables as TName extends string ? `upsert${Capitalize<TName>}` : never]?: TName extends string ? {
|
|
929
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[Capitalize<TName>]>>>;
|
|
930
|
+
args: {
|
|
931
|
+
values: {
|
|
932
|
+
type: GraphQLNonNull<GraphQLList<GraphQLNonNull<TInputs[`Create${Capitalize<TName>}Input`]>>>;
|
|
933
|
+
};
|
|
934
|
+
onConflict: {
|
|
935
|
+
type: GraphQLInputObjectType;
|
|
936
|
+
};
|
|
937
|
+
};
|
|
938
|
+
resolve: UpsertArrResolver<TSchemaTables[TName], IsReturnless>;
|
|
939
|
+
} : never; } & { [TName in keyof TSchemaTables as TName extends string ? `upsert${Capitalize<TName>}Single` : never]?: TName extends string ? {
|
|
940
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[Capitalize<TName>];
|
|
941
|
+
args: {
|
|
942
|
+
values: {
|
|
943
|
+
type: GraphQLNonNull<TInputs[`Create${Capitalize<TName>}Input`]>;
|
|
944
|
+
};
|
|
945
|
+
onConflict: {
|
|
946
|
+
type: GraphQLInputObjectType;
|
|
947
|
+
};
|
|
948
|
+
};
|
|
949
|
+
resolve: UpsertResolver<TSchemaTables[TName], IsReturnless>;
|
|
950
|
+
} : never; } & { [TName in keyof TSchemaTables as TName extends string ? `update${Capitalize<TName>}` : never]: TName extends string ? {
|
|
951
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[Capitalize<TName>]>>>;
|
|
952
|
+
args: {
|
|
953
|
+
set: {
|
|
954
|
+
type: GraphQLNonNull<TInputs[`Update${Capitalize<TName>}Input`]>;
|
|
955
|
+
};
|
|
956
|
+
where: {
|
|
957
|
+
type: TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never;
|
|
958
|
+
};
|
|
959
|
+
};
|
|
960
|
+
resolve: UpdateResolver<TSchemaTables[TName], IsReturnless>;
|
|
961
|
+
} : never; } & { [TName in keyof TSchemaTables as TName extends string ? `update${Capitalize<TName>}Many` : never]: TName extends string ? {
|
|
962
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<TOutputs[Capitalize<TName>]>>;
|
|
963
|
+
args: {
|
|
964
|
+
updates: {
|
|
965
|
+
type: GraphQLNonNull<GraphQLList<GraphQLNonNull<TInputs[`Update${Capitalize<TName>}ManyInput`]>>>;
|
|
966
|
+
};
|
|
967
|
+
};
|
|
968
|
+
resolve: UpdateManyResolver<TSchemaTables[TName], IsReturnless>;
|
|
969
|
+
} : never; } & { [TName in keyof TSchemaTables as TName extends string ? `update${Capitalize<TName>}Single` : never]: TName extends string ? {
|
|
970
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[Capitalize<TName>];
|
|
971
|
+
args: {
|
|
972
|
+
set: {
|
|
973
|
+
type: GraphQLNonNull<TInputs[`Update${Capitalize<TName>}Input`]>;
|
|
974
|
+
};
|
|
975
|
+
where: {
|
|
976
|
+
type: GraphQLNonNull<TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never>;
|
|
977
|
+
};
|
|
978
|
+
};
|
|
979
|
+
resolve: UpdateSingleResolver<TSchemaTables[TName], IsReturnless>;
|
|
980
|
+
} : never; } & { [TName in keyof TSchemaTables as TName extends string ? `delete${Capitalize<TName>}` : never]: TName extends string ? {
|
|
981
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<GraphQLNonNull<TOutputs[Capitalize<TName>]>>>;
|
|
982
|
+
args: {
|
|
983
|
+
where: {
|
|
984
|
+
type: TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never;
|
|
985
|
+
};
|
|
986
|
+
};
|
|
987
|
+
resolve: DeleteResolver<TSchemaTables[TName], IsReturnless>;
|
|
988
|
+
} : never; } & { [TName in keyof TSchemaTables as TName extends string ? `delete${Capitalize<TName>}Single` : never]: TName extends string ? {
|
|
989
|
+
type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[Capitalize<TName>];
|
|
990
|
+
args: {
|
|
991
|
+
where: {
|
|
992
|
+
type: GraphQLNonNull<TInputs[`${Capitalize<TName>}Filters`] extends GraphQLInputObjectType ? TInputs[`${Capitalize<TName>}Filters`] : never>;
|
|
993
|
+
};
|
|
994
|
+
};
|
|
995
|
+
resolve: DeleteSingleResolver<TSchemaTables[TName], IsReturnless>;
|
|
996
|
+
} : never; };
|
|
979
997
|
/**
|
|
980
998
|
* Keys of `entities.inputs`, which is keyed by generated GraphQL input type name.
|
|
981
999
|
*
|
|
@@ -985,17 +1003,7 @@ type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends
|
|
|
985
1003
|
* enabled — `${Table}OnConflict` for upsert, `${Table}Having` for group-by — are not listed,
|
|
986
1004
|
* since whether they were generated is a runtime decision.
|
|
987
1005
|
*/
|
|
988
|
-
type GeneratedInputs<TSchema extends Record<string, Table>> = {
|
|
989
|
-
[TName in keyof TSchema as TName extends string ? `Create${Capitalize<TName>}Input` : never]: GraphQLInputObjectType;
|
|
990
|
-
} & {
|
|
991
|
-
[TName in keyof TSchema as TName extends string ? `Update${Capitalize<TName>}Input` : never]: GraphQLInputObjectType;
|
|
992
|
-
} & {
|
|
993
|
-
[TName in keyof TSchema as TName extends string ? `Update${Capitalize<TName>}ManyInput` : never]: GraphQLInputObjectType;
|
|
994
|
-
} & {
|
|
995
|
-
[TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}OrderBy` : never]: GraphQLInputObjectType;
|
|
996
|
-
} & {
|
|
997
|
-
[TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}Filters` : never]: GraphQLInputObjectType;
|
|
998
|
-
};
|
|
1006
|
+
type GeneratedInputs<TSchema extends Record<string, Table>> = { [TName in keyof TSchema as TName extends string ? `Create${Capitalize<TName>}Input` : never]: GraphQLInputObjectType; } & { [TName in keyof TSchema as TName extends string ? `Update${Capitalize<TName>}Input` : never]: GraphQLInputObjectType; } & { [TName in keyof TSchema as TName extends string ? `Update${Capitalize<TName>}ManyInput` : never]: GraphQLInputObjectType; } & { [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}OrderBy` : never]: GraphQLInputObjectType; } & { [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}Filters` : never]: GraphQLInputObjectType; };
|
|
999
1007
|
/**
|
|
1000
1008
|
* Keys of `entities.types`, which is keyed by generated GraphQL type name.
|
|
1001
1009
|
*
|
|
@@ -1004,33 +1012,25 @@ type GeneratedInputs<TSchema extends Record<string, Table>> = {
|
|
|
1004
1012
|
* type kept those names long after the generator stopped producing them. MySQL still has a
|
|
1005
1013
|
* shared `MutationReturn` instead of per-table return types, because its writes return no rows.
|
|
1006
1014
|
*/
|
|
1007
|
-
type GeneratedOutputs<TSchema extends Record<string, Table>, IsReturnless extends boolean> = {
|
|
1008
|
-
|
|
1009
|
-
}
|
|
1010
|
-
[TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}Aggregate` : never]: GraphQLObjectType;
|
|
1011
|
-
} & (IsReturnless extends true ? {
|
|
1012
|
-
MutationReturn: GraphQLObjectType;
|
|
1013
|
-
} : {
|
|
1014
|
-
[TName in keyof TSchema as TName extends string ? Capitalize<TName> : never]: GraphQLObjectType;
|
|
1015
|
-
});
|
|
1015
|
+
type GeneratedOutputs<TSchema extends Record<string, Table>, IsReturnless extends boolean> = { [TName in keyof TSchema as TName extends string ? Capitalize<TName> : never]: GraphQLObjectType; } & { [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}Aggregate` : never]: GraphQLObjectType; } & (IsReturnless extends true ? {
|
|
1016
|
+
MutationReturn: GraphQLObjectType;
|
|
1017
|
+
} : { [TName in keyof TSchema as TName extends string ? Capitalize<TName> : never]: GraphQLObjectType; });
|
|
1016
1018
|
type GeneratedEntities<TDatabase extends AnyDrizzleDB<TSchema>, TSchema extends Record<string, unknown> = TDatabase extends AnyDrizzleDB<infer ISchema> ? ISchema : never, TSchemaTables extends ExtractTables<TSchema> = ExtractTables<TSchema>, TSchemaRelations extends ExtractRelations<TSchema> = ExtractRelations<TSchema>, TInputs extends GeneratedInputs<TSchemaTables> = GeneratedInputs<TSchemaTables>, TOutputs extends GeneratedOutputs<TSchemaTables, TDatabase extends MySqlAsyncDatabase<any, any> ? true : false> = GeneratedOutputs<TSchemaTables, TDatabase extends MySqlAsyncDatabase<any, any> ? true : false>> = {
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
[TName in keyof TSchemaTables as TName extends string ? TName : never]?: Record<string, (source: any, args: any, context: any, info: GraphQLResolveInfo) => Promise<any>>;
|
|
1029
|
-
};
|
|
1019
|
+
queries: QueriesCore<TSchemaTables, TSchemaRelations, TInputs, TOutputs>;
|
|
1020
|
+
mutations: MutationsCore<TSchemaTables, TInputs, TOutputs, TDatabase extends MySqlAsyncDatabase<any, any> ? true : false>;
|
|
1021
|
+
inputs: TInputs;
|
|
1022
|
+
types: TOutputs;
|
|
1023
|
+
/**
|
|
1024
|
+
* Field-level resolvers for each relation on each table.
|
|
1025
|
+
* Each resolver handles both the eager path (data pre-fetched by the parent query)
|
|
1026
|
+
* and the lazy path (data fetched on demand with N+1 protection via request-scoped batching).
|
|
1027
|
+
* Keyed as `fieldResolvers[tableSchemaKey][relationName]`.
|
|
1028
|
+
*/
|
|
1029
|
+
fieldResolvers: { [TName in keyof TSchemaTables as TName extends string ? TName : never]?: Record<string, (source: any, args: any, context: any, info: GraphQLResolveInfo) => Promise<any>>; };
|
|
1030
1030
|
};
|
|
1031
1031
|
type GeneratedData<TDatabase extends AnyDrizzleDB<any>> = {
|
|
1032
|
-
|
|
1033
|
-
|
|
1032
|
+
schema: GraphQLSchema;
|
|
1033
|
+
entities: GeneratedEntities<TDatabase>;
|
|
1034
1034
|
};
|
|
1035
1035
|
/**
|
|
1036
1036
|
* A feature switch. `true` / `false` decides for the whole build; a predicate decides per
|
|
@@ -1050,196 +1050,196 @@ type FeatureSwitch = boolean | ((tableName: string) => boolean);
|
|
|
1050
1050
|
* See {@link BuildSchemaConfig.features}.
|
|
1051
1051
|
*/
|
|
1052
1052
|
type SchemaFeatures = {
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1053
|
+
/** `<plural>Aggregate` root queries and the aggregate output types. @default true */
|
|
1054
|
+
aggregates?: FeatureSwitch;
|
|
1055
|
+
/**
|
|
1056
|
+
* `<plural>GroupBy` root queries — the same aggregates, one row per group. Requires
|
|
1057
|
+
* `aggregates`, whose output types the grouped result reuses.
|
|
1058
|
+
*
|
|
1059
|
+
* @default true
|
|
1060
|
+
*/
|
|
1061
|
+
groupBy?: FeatureSwitch;
|
|
1062
|
+
/** `<relation>Aggregate` fields on object types, for to-many relations. @default true */
|
|
1063
|
+
relationAggregates?: FeatureSwitch;
|
|
1064
|
+
/** The `distinct` argument on list queries. @default true */
|
|
1065
|
+
distinct?: FeatureSwitch;
|
|
1066
|
+
/** `create<Table>` / `create<Table>Single` mutations. @default true */
|
|
1067
|
+
insert?: FeatureSwitch;
|
|
1068
|
+
/** `update<Table>` / `update<Table>Single` mutations. @default true */
|
|
1069
|
+
update?: FeatureSwitch;
|
|
1070
|
+
/**
|
|
1071
|
+
* `update<Table>Many` mutations — batch update with a per-entry `set` and `where`,
|
|
1072
|
+
* executed inside one transaction. Only generated when `update` is also enabled,
|
|
1073
|
+
* since the entries reuse the update `set` input.
|
|
1074
|
+
*
|
|
1075
|
+
* @default true
|
|
1076
|
+
*/
|
|
1077
|
+
updateMany?: FeatureSwitch;
|
|
1078
|
+
/** `delete<Table>` / `delete<Table>Single` mutations. @default true */
|
|
1079
|
+
delete?: FeatureSwitch;
|
|
1080
|
+
/**
|
|
1081
|
+
* `upsert<Table>` / `upsert<Table>Single` mutations — insert, or update the row that
|
|
1082
|
+
* already holds the same unique key. Off unless asked for, so an existing schema does
|
|
1083
|
+
* not grow new mutations on upgrade.
|
|
1084
|
+
*
|
|
1085
|
+
* @default false
|
|
1086
|
+
*/
|
|
1087
|
+
upsert?: FeatureSwitch;
|
|
1088
|
+
/**
|
|
1089
|
+
* Relation fields on `Create<Table>Input` and `Update<Table>Input`, so a parent row and
|
|
1090
|
+
* the rows it is related to can be written in one mutation. Off unless asked for: it adds
|
|
1091
|
+
* a field per writable relation to every create and update input.
|
|
1092
|
+
*
|
|
1093
|
+
* ```graphql
|
|
1094
|
+
* createPostsSingle(values: {
|
|
1095
|
+
* title: "Hello"
|
|
1096
|
+
* author: { connect: { id: { eq: "a1" } } }
|
|
1097
|
+
* tags: { create: [{ name: "drizzle" }] }
|
|
1098
|
+
* }) { id }
|
|
1099
|
+
* ```
|
|
1100
|
+
*
|
|
1101
|
+
* Each relation field offers `create` and `connect`; the update input adds `disconnect`
|
|
1102
|
+
* and, for a to-many relation, `set` (replace the whole set). `disconnect` and `set` are
|
|
1103
|
+
* generated only when the foreign key is nullable — there is no way to detach a row whose
|
|
1104
|
+
* key is NOT NULL. Nesting is one level deep: the row a nested `create` inserts takes
|
|
1105
|
+
* columns only.
|
|
1106
|
+
*
|
|
1107
|
+
* A many-to-many (`.through()`) relation is written as junction rows: `connect` on the
|
|
1108
|
+
* create input, and `connect` / `disconnect` / `set` on the update input, all
|
|
1109
|
+
* unconditional, since unlinking deletes a junction row rather than nulling a column.
|
|
1110
|
+
* It offers no `create` — inserting a row and linking it are two writes to two tables —
|
|
1111
|
+
* and `set: []` clears the relation.
|
|
1112
|
+
*
|
|
1113
|
+
* The whole tree runs in one transaction (a savepoint when the request already carries
|
|
1114
|
+
* one), and a column a relation fills in (`authorId`, when `author: { create: … }` is
|
|
1115
|
+
* offered) becomes nullable on the create input, since the relation is the other way to
|
|
1116
|
+
* supply it.
|
|
1117
|
+
*
|
|
1118
|
+
* PostgreSQL and SQLite only. MySQL cannot return the rows it just wrote, which is how a
|
|
1119
|
+
* nested write learns the parent's key, so `buildSchema` rejects the flag there. On SQLite
|
|
1120
|
+
* the driver must be asynchronous (libsql, D1, …): a synchronous one commits before an
|
|
1121
|
+
* awaited statement runs, so `buildSchema` rejects the combination outright.
|
|
1122
|
+
*
|
|
1123
|
+
* @default false
|
|
1124
|
+
*/
|
|
1125
|
+
nestedWrites?: boolean;
|
|
1126
|
+
/**
|
|
1127
|
+
* Operation inputs on the update `set`, so a column can be changed relative to its current
|
|
1128
|
+
* value instead of only replaced.
|
|
1129
|
+
*
|
|
1130
|
+
* ```graphql
|
|
1131
|
+
* updatePostsSingle(where: { id: { eq: "p1" } }, set: { views: { increment: 1 } }) { views }
|
|
1132
|
+
* ```
|
|
1133
|
+
*
|
|
1134
|
+
* Every numeric column's field on `Update<Table>Input` becomes a `<Scalar>FieldUpdate`
|
|
1135
|
+
* input carrying `set`, `increment`, `decrement`, `multiply` and `divide`; every array
|
|
1136
|
+
* column's becomes a `<Scalar>ListFieldUpdate` carrying `set` and `push`. Exactly one
|
|
1137
|
+
* operation per field, checked at resolve time. `set` is the explicit spelling of what the
|
|
1138
|
+
* field did before, so `set: { views: 42 }` becomes `set: { views: { set: 42 } }`.
|
|
1139
|
+
*
|
|
1140
|
+
* The arithmetic happens in the database (`SET views = views + 1`), so a counter no longer
|
|
1141
|
+
* needs a read-modify-write round trip and no longer loses concurrent updates. Rounding on
|
|
1142
|
+
* an integer column, and division by zero, follow the database's own rules rather than
|
|
1143
|
+
* being guarded here. Columns owned by a scalar override keep their plain type — an
|
|
1144
|
+
* override owns what the column accepts.
|
|
1145
|
+
*
|
|
1146
|
+
* Off by default: it changes the type of every numeric and array field on every update
|
|
1147
|
+
* input, which no existing document is written against.
|
|
1148
|
+
*
|
|
1149
|
+
* @default false
|
|
1150
|
+
*/
|
|
1151
|
+
fieldUpdateOperations?: FeatureSwitch;
|
|
1152
|
+
/**
|
|
1153
|
+
* `update<Table>Count` / `delete<Table>Count` mutations — the same write as the plural
|
|
1154
|
+
* `update<Table>` / `delete<Table>`, returning the number of rows affected instead of the
|
|
1155
|
+
* rows themselves.
|
|
1156
|
+
*
|
|
1157
|
+
* ```graphql
|
|
1158
|
+
* deletePostsCount(where: { published: { eq: false } }) # Int!
|
|
1159
|
+
* ```
|
|
1160
|
+
*
|
|
1161
|
+
* A mass update or delete otherwise has to `RETURNING *` every row it touched purely so
|
|
1162
|
+
* the caller can count them, which crosses the driver and is serialized through GraphQL
|
|
1163
|
+
* for nothing. Each mutation is generated only when its plural counterpart is
|
|
1164
|
+
* (`features.update` / `features.delete`), and honours `features.requireWhere`.
|
|
1165
|
+
*
|
|
1166
|
+
* Off unless asked for, so an existing schema does not grow new mutations on upgrade.
|
|
1167
|
+
*
|
|
1168
|
+
* @default false
|
|
1169
|
+
*/
|
|
1170
|
+
countMutations?: FeatureSwitch;
|
|
1171
|
+
/**
|
|
1172
|
+
* Makes `where` non-null on the plural `update<Table>` / `delete<Table>` mutations, and
|
|
1173
|
+
* rejects a `where` that collapses to no filters (e.g. `where: {}`), so a schema can rule
|
|
1174
|
+
* out unbounded writes at the type level. Off by default for backwards compatibility.
|
|
1175
|
+
*
|
|
1176
|
+
* The `Single` variants (`update<Table>Single` / `delete<Table>Single`) require a
|
|
1177
|
+
* non-empty `where` regardless of this flag.
|
|
1178
|
+
*
|
|
1179
|
+
* @default false
|
|
1180
|
+
*/
|
|
1181
|
+
requireWhere?: FeatureSwitch;
|
|
1182
|
+
/**
|
|
1183
|
+
* One `where` field per compound unique constraint, so a lookup by a natural key names the
|
|
1184
|
+
* key instead of restating its columns:
|
|
1185
|
+
*
|
|
1186
|
+
* ```graphql
|
|
1187
|
+
* stockSingle(where: { itemId_locationId: { itemId: "i1", locationId: "l1" } }) { quantity }
|
|
1188
|
+
* ```
|
|
1189
|
+
*
|
|
1190
|
+
* The field is named after its member columns and every member is non-null, so a half-
|
|
1191
|
+
* supplied key fails query validation rather than becoming a broader filter that returns
|
|
1192
|
+
* whichever row happens to come first. It compiles to the same equalities the columns would
|
|
1193
|
+
* have — the guarantee is in the input type.
|
|
1194
|
+
*
|
|
1195
|
+
* Single-column constraints get no field (`eq` on the column already says it), and a
|
|
1196
|
+
* constraint whose field name is taken by a column or a relation is skipped. The fields live
|
|
1197
|
+
* on `<Type>Filters`, so they are accepted wherever a filter is: the `Single` reads and
|
|
1198
|
+
* writes they are meant for, but also list queries, relation filters and `onConflict.where`.
|
|
1199
|
+
*
|
|
1200
|
+
* Off unless asked for: it adds an input type per compound constraint.
|
|
1201
|
+
*
|
|
1202
|
+
* @default false
|
|
1203
|
+
*/
|
|
1204
|
+
uniqueKeyFilters?: FeatureSwitch;
|
|
1205
1205
|
};
|
|
1206
1206
|
/**
|
|
1207
1207
|
* Per-field cost hints for `graphql-query-complexity` (or any estimator that reads
|
|
1208
1208
|
* `extensions.complexity`). See {@link BuildSchemaConfig.complexity}.
|
|
1209
1209
|
*/
|
|
1210
1210
|
type ComplexityConfig = {
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1211
|
+
/**
|
|
1212
|
+
* Rows a list field is assumed to return when the query passes no `limit`. Raise it if your
|
|
1213
|
+
* tables are large and clients routinely omit `limit`.
|
|
1214
|
+
*
|
|
1215
|
+
* @default 10
|
|
1216
|
+
*/
|
|
1217
|
+
defaultListSize?: number;
|
|
1218
|
+
/**
|
|
1219
|
+
* Flat cost charged for an aggregate field, on top of whatever is selected inside it. An
|
|
1220
|
+
* aggregate returns one row but reads however many match, so it is priced as a scan.
|
|
1221
|
+
*
|
|
1222
|
+
* @default 10
|
|
1223
|
+
*/
|
|
1224
|
+
aggregateCost?: number;
|
|
1225
1225
|
};
|
|
1226
1226
|
/**
|
|
1227
1227
|
* A limit policy: what a request without `limit` gets, and how large a `limit` may be.
|
|
1228
1228
|
* Every field is optional — an empty policy is the default unbounded behavior.
|
|
1229
1229
|
*/
|
|
1230
1230
|
type TableLimitPolicy = {
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1231
|
+
/** Applied when the client passes no `limit`. Capped by `maxLimit` when both are set. */
|
|
1232
|
+
defaultLimit?: number;
|
|
1233
|
+
/**
|
|
1234
|
+
* The largest `limit` a client may ask for. Also bounds a request that passes no `limit` at
|
|
1235
|
+
* all, since that means every row.
|
|
1236
|
+
*/
|
|
1237
|
+
maxLimit?: number;
|
|
1238
|
+
/**
|
|
1239
|
+
* `false` (default) rejects a `limit` above `maxLimit` with a GraphQL error; `true` reduces
|
|
1240
|
+
* it to `maxLimit` instead.
|
|
1241
|
+
*/
|
|
1242
|
+
clampToMax?: boolean;
|
|
1243
1243
|
};
|
|
1244
1244
|
/**
|
|
1245
1245
|
* One entry of a {@link TableDefaults} ordering: a direction, or a direction with the
|
|
@@ -1247,23 +1247,23 @@ type TableLimitPolicy = {
|
|
|
1247
1247
|
* generated `orderBy` argument).
|
|
1248
1248
|
*/
|
|
1249
1249
|
type DefaultOrderByEntry = 'asc' | 'desc' | {
|
|
1250
|
-
|
|
1251
|
-
|
|
1250
|
+
direction: 'asc' | 'desc';
|
|
1251
|
+
priority?: number;
|
|
1252
1252
|
};
|
|
1253
1253
|
/** {@link DefaultsConfig} — what one table falls back to when the request does not say. */
|
|
1254
1254
|
type TableDefaults = {
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1255
|
+
/**
|
|
1256
|
+
* The ordering a read of this table runs with when the request passes no `orderBy`, keyed
|
|
1257
|
+
* by column property name.
|
|
1258
|
+
*/
|
|
1259
|
+
orderBy?: Record<string, DefaultOrderByEntry>;
|
|
1260
1260
|
};
|
|
1261
1261
|
/** {@link BuildSchemaConfig.defaults} — per-table defaults, keyed by the Drizzle schema key. */
|
|
1262
1262
|
type DefaultsConfig = Record<string, TableDefaults>;
|
|
1263
1263
|
/** {@link BuildSchemaConfig.limits} — a global policy plus per-table overrides. */
|
|
1264
1264
|
type LimitsConfig = TableLimitPolicy & {
|
|
1265
|
-
|
|
1266
|
-
|
|
1265
|
+
/** Per-table overrides, keyed by the table's key in the Drizzle schema. */
|
|
1266
|
+
tables?: Record<string, TableLimitPolicy>;
|
|
1267
1267
|
};
|
|
1268
1268
|
/**
|
|
1269
1269
|
* What a {@link RowScope} may return: a Drizzle `SQL` expression, a filter object in the same
|
|
@@ -1298,49 +1298,48 @@ type ContextValuesConfig<TContext = any> = Record<string, Record<string, (contex
|
|
|
1298
1298
|
* written on delete and on restore. See {@link BuildSchemaConfig.softDelete}.
|
|
1299
1299
|
*/
|
|
1300
1300
|
type SoftDeleteColumn = string | {
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1301
|
+
/** Property name of the column that marks a row deleted. */
|
|
1302
|
+
column: string;
|
|
1303
|
+
/**
|
|
1304
|
+
* Written when a row is deleted. A function is evaluated per delete. Defaults by column
|
|
1305
|
+
* type: `new Date()` for a timestamp, an ISO string for text, `Date.now()` for a number,
|
|
1306
|
+
* `true` for a boolean. Required, as a constant, when the column is NOT NULL and not a
|
|
1307
|
+
* boolean — the predicate that hides marked rows has to compare against it.
|
|
1308
|
+
*/
|
|
1309
|
+
deletedValue?: any;
|
|
1310
|
+
/**
|
|
1311
|
+
* Written when a row is restored. Defaults to `null` for a nullable column and `false`
|
|
1312
|
+
* for a NOT NULL boolean; required for any other NOT NULL column.
|
|
1313
|
+
*/
|
|
1314
|
+
restoredValue?: any;
|
|
1315
|
+
/**
|
|
1316
|
+
* Which generated reads hide marked rows by default.
|
|
1317
|
+
*
|
|
1318
|
+
* - `'all'` (the default) — the table's own query fields and every relation field that
|
|
1319
|
+
* points at it. A *required* to-one relation is the one exception: hiding the row
|
|
1320
|
+
* there can only produce "Cannot return null for non-nullable field", never a usable
|
|
1321
|
+
* result, so it reads `INCLUDE` unless the request says otherwise.
|
|
1322
|
+
* - `'root'` — only the table's own query fields. Relation fields read marked rows,
|
|
1323
|
+
* which is what "retired, not erased" usually means: keep the row off the pickers and
|
|
1324
|
+
* the lists, keep rendering it on the historical rows that reference it.
|
|
1325
|
+
*
|
|
1326
|
+
* The `deleted` argument is generated either way, so either default can be overridden
|
|
1327
|
+
* per request.
|
|
1328
|
+
*/
|
|
1329
|
+
scope?: 'root' | 'all';
|
|
1330
|
+
/**
|
|
1331
|
+
* Whether the table's delete mutations accept `hard: Boolean = false`, which issues a
|
|
1332
|
+
* real `DELETE` instead of writing the marker — emptying the trash, reclaiming a unique
|
|
1333
|
+
* key, clearing a table. Opt-in per table, and the argument is only generated when it is
|
|
1334
|
+
* on, so the schema itself says which tables can be purged.
|
|
1335
|
+
*
|
|
1336
|
+
* A hard delete reads at `INCLUDE`: it reaches already-marked rows, which is the case it
|
|
1337
|
+
* mostly exists for. A `scope` still confines it, exactly as it confines every other write.
|
|
1338
|
+
*
|
|
1339
|
+
* @default false
|
|
1340
|
+
*/
|
|
1341
|
+
hardDelete?: boolean;
|
|
1342
1342
|
};
|
|
1343
|
-
|
|
1344
1343
|
/**
|
|
1345
1344
|
* Write hooks, either applied to every table (a bare function, or an object naming the
|
|
1346
1345
|
* positions) or registered per table by Drizzle schema key. See
|
|
@@ -1359,707 +1358,708 @@ type SoftDeleteConfig = Record<string, SoftDeleteColumn> | ((table: any, tableNa
|
|
|
1359
1358
|
* GraphQL name.
|
|
1360
1359
|
*/
|
|
1361
1360
|
type SchemaExclusions = {
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1361
|
+
/**
|
|
1362
|
+
* Tables that generate nothing at all: no object type, no queries, no mutations, and no
|
|
1363
|
+
* relation fields on other tables that point at them.
|
|
1364
|
+
*/
|
|
1365
|
+
tables?: string[];
|
|
1366
|
+
/** Per-table column exclusions, keyed by the table's key in the Drizzle schema. */
|
|
1367
|
+
columns?: Record<string, string[]>;
|
|
1369
1368
|
};
|
|
1370
1369
|
type BuildSchemaConfig = {
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
1370
|
+
/**
|
|
1371
|
+
* Determines whether generated mutations will be passed to returned schema.
|
|
1372
|
+
*
|
|
1373
|
+
* Set value to `false` to omit mutations from returned schema.
|
|
1374
|
+
*
|
|
1375
|
+
* Flag is treated as if set to `true` by default.
|
|
1376
|
+
*/
|
|
1377
|
+
mutations?: boolean;
|
|
1378
|
+
/**
|
|
1379
|
+
* Limits depth of relation-field generation.
|
|
1380
|
+
*
|
|
1381
|
+
* Expects a non-negative integer or `undefined`.
|
|
1382
|
+
*
|
|
1383
|
+
* `undefined` (default) — no limit; all relations are generated recursively
|
|
1384
|
+
* until a cycle is detected.
|
|
1385
|
+
*
|
|
1386
|
+
* `0` — no relation fields are generated on any type. Useful for a flat,
|
|
1387
|
+
* columns-only schema.
|
|
1388
|
+
*
|
|
1389
|
+
* `N > 0` — each table's own direct relations are still generated (every
|
|
1390
|
+
* table's root type is processed at depth 0, which is always < N). The
|
|
1391
|
+
* depth limit controls how deep the generation RECURSES when traversing
|
|
1392
|
+
* related types; because all types share a single instance via the type
|
|
1393
|
+
* cache, setting N > 0 currently behaves the same as `undefined` for the
|
|
1394
|
+
* final schema shape. The principal useful values are `0` (no relations)
|
|
1395
|
+
* and `undefined` (unlimited).
|
|
1396
|
+
*/
|
|
1397
|
+
relationsDepthLimit?: number;
|
|
1398
|
+
/**
|
|
1399
|
+
* Customizes query name prefixes for generated GraphQL operations.
|
|
1400
|
+
*
|
|
1401
|
+
* @default { insert: 'create', delete: 'delete', update: 'update', upsert: 'upsert' }
|
|
1402
|
+
*/
|
|
1403
|
+
prefixes?: {
|
|
1404
|
+
/** Prefix for insert mutations (e.g., 'users' -> 'createUsers') */
|
|
1405
|
+
insert?: string;
|
|
1406
|
+
/** Prefix for delete mutations (e.g., 'users' -> 'deleteUsers') */
|
|
1407
|
+
delete?: string;
|
|
1408
|
+
/** Prefix for update mutations (e.g., 'users' -> 'updateUsers') */
|
|
1409
|
+
update?: string;
|
|
1410
|
+
/** Prefix for upsert mutations (e.g., 'users' -> 'upsertUsers') */
|
|
1411
|
+
upsert?: string;
|
|
1412
|
+
/**
|
|
1413
|
+
* Prefix for the restore mutations of a soft-deleting table (e.g., 'users' ->
|
|
1414
|
+
* 'restoreUsers'). Only used when {@link BuildSchemaConfig.softDelete} names the table.
|
|
1415
|
+
*/
|
|
1416
|
+
restore?: string;
|
|
1417
|
+
};
|
|
1418
|
+
/**
|
|
1419
|
+
* Customizes query name suffixes for generated GraphQL operations.
|
|
1420
|
+
*
|
|
1421
|
+
* @default { list: '', single: 'Single' }
|
|
1422
|
+
*/
|
|
1423
|
+
suffixes?: {
|
|
1424
|
+
/** Suffix for list queries (e.g., 'users' -> 'users' + suffix) */
|
|
1425
|
+
list?: string;
|
|
1426
|
+
/** Suffix for single queries (e.g., 'users' -> 'users' + suffix) */
|
|
1427
|
+
single?: string;
|
|
1428
|
+
};
|
|
1429
|
+
/**
|
|
1430
|
+
* When true, insert mutations will use onConflictDoNothing() to silently
|
|
1431
|
+
* ignore duplicate key violations. Defaults to false (conflicts throw errors).
|
|
1432
|
+
*
|
|
1433
|
+
* PostgreSQL and SQLite only — MySQL's insert builder has no equivalent, so the flag is
|
|
1434
|
+
* ignored there and conflicts keep throwing.
|
|
1435
|
+
*
|
|
1436
|
+
* @deprecated Build-wide and unconditional: a request cannot opt out of it, and a
|
|
1437
|
+
* swallowed insert returns `null` with no indication why. Turn on `features.upsert` and
|
|
1438
|
+
* pass `onConflict: { action: NOTHING }` per request instead. This flag keeps working
|
|
1439
|
+
* until the next major.
|
|
1440
|
+
*/
|
|
1441
|
+
conflictDoNothing?: boolean;
|
|
1442
|
+
/**
|
|
1443
|
+
* Cost hints published as `extensions.complexity` on the generated fields, for
|
|
1444
|
+
* `graphql-query-complexity`'s `fieldExtensionsEstimator`.
|
|
1445
|
+
*
|
|
1446
|
+
* The generator knows which fields are paginated and which are aggregates, so a list field is
|
|
1447
|
+
* priced at `(limit ?? defaultListSize) * childComplexity` and an aggregate at
|
|
1448
|
+
* `aggregateCost + childComplexity`. Everything else is left alone and falls through to your
|
|
1449
|
+
* estimator's default. The hints are inert until you install a complexity rule, so they are on
|
|
1450
|
+
* by default; pass `false` to omit them.
|
|
1451
|
+
*
|
|
1452
|
+
* Cost is not a depth bound — a cyclic relation graph still lets a client nest arbitrarily
|
|
1453
|
+
* deep. Put a depth limit in front of a publicly exposed schema as well.
|
|
1454
|
+
*
|
|
1455
|
+
* ```ts
|
|
1456
|
+
* import { createComplexityRule, fieldExtensionsEstimator, simpleEstimator } from 'graphql-query-complexity';
|
|
1457
|
+
*
|
|
1458
|
+
* const rule = createComplexityRule({
|
|
1459
|
+
* maximumComplexity: 1000,
|
|
1460
|
+
* estimators: [fieldExtensionsEstimator(), simpleEstimator({ defaultComplexity: 1 })],
|
|
1461
|
+
* });
|
|
1462
|
+
* ```
|
|
1463
|
+
*
|
|
1464
|
+
* @default true
|
|
1465
|
+
*/
|
|
1466
|
+
complexity?: boolean | ComplexityConfig;
|
|
1467
|
+
/**
|
|
1468
|
+
* Turns individual generated features off, for the whole build or per table.
|
|
1469
|
+
*
|
|
1470
|
+
* Every flag defaults to `true` except `upsert` and `nestedWrites`, which are opt-in: a
|
|
1471
|
+
* build with no `features` block generates exactly what it generated before this option
|
|
1472
|
+
* existed. Turning one off removes both the schema surface it adds and the work behind it.
|
|
1473
|
+
*
|
|
1474
|
+
* ```ts
|
|
1475
|
+
* buildSchema(db, {
|
|
1476
|
+
* features: {
|
|
1477
|
+
* aggregates: false, // no `<plural>Aggregate` root queries
|
|
1478
|
+
* relationAggregates: false, // no `<relation>Aggregate` fields on object types
|
|
1479
|
+
* distinct: false, // no `distinct` argument on list queries
|
|
1480
|
+
* delete: false, // no delete mutations
|
|
1481
|
+
* upsert: true, // opt in to `upsert<Table>` mutations
|
|
1482
|
+
* },
|
|
1483
|
+
* });
|
|
1484
|
+
* ```
|
|
1485
|
+
*
|
|
1486
|
+
* Any flag may instead be a predicate, which is asked once per table with the table's key
|
|
1487
|
+
* in the Drizzle schema — the usual case, where a handful of tables must not be written
|
|
1488
|
+
* through the API and the rest want the full set:
|
|
1489
|
+
*
|
|
1490
|
+
* ```ts
|
|
1491
|
+
* buildSchema(db, {
|
|
1492
|
+
* features: {
|
|
1493
|
+
* delete: (table) => table !== 'auditLog',
|
|
1494
|
+
* update: (table) => !ownedByCustomResolver.has(table),
|
|
1495
|
+
* upsert: (table) => table === 'settings',
|
|
1496
|
+
* },
|
|
1497
|
+
* });
|
|
1498
|
+
* ```
|
|
1499
|
+
*
|
|
1500
|
+
* A table that generates nothing at all belongs in {@link BuildSchemaConfig.exclude}; this
|
|
1501
|
+
* decides which operations a table that *is* in the schema offers. `nestedWrites` is the one
|
|
1502
|
+
* flag that stays build-wide: its plans are computed once over the whole relation graph, and
|
|
1503
|
+
* a nested write reaches a second table by definition.
|
|
1504
|
+
*
|
|
1505
|
+
* Some operations are built out of others — an upsert writes through insert and update, a
|
|
1506
|
+
* batch update reuses the update input, a grouped query reuses the aggregate types. Flags
|
|
1507
|
+
* that contradict those implications warn on the console at build time (naming the tables)
|
|
1508
|
+
* rather than leaving a second write path past the operation you turned off to be found
|
|
1509
|
+
* later.
|
|
1510
|
+
*
|
|
1511
|
+
* Turning off every mutation feature for every table omits the `Mutation` type entirely,
|
|
1512
|
+
* exactly as `mutations: false` does. Query-side features can all be off — the list and
|
|
1513
|
+
* single queries are always generated, so `Query` is never empty.
|
|
1514
|
+
*/
|
|
1515
|
+
features?: SchemaFeatures;
|
|
1516
|
+
/**
|
|
1517
|
+
* Automatic transactions for GraphQL documents that fire more than one mutation.
|
|
1518
|
+
*
|
|
1519
|
+
* `'none'` (default) — every root mutation field runs on its own connection, so a failure
|
|
1520
|
+
* mid-document leaves the earlier mutations committed (today's behavior).
|
|
1521
|
+
*
|
|
1522
|
+
* `'auto'` — when a request's document selects more than one root mutation field, the
|
|
1523
|
+
* library opens `db.transaction()` once for the whole request and runs every mutation
|
|
1524
|
+
* field (and the reads nested under them) inside it. The transaction commits when the
|
|
1525
|
+
* last mutation field completes and rolls back when any of them fails; mutation fields
|
|
1526
|
+
* after a failure are not executed against the rolled-back transaction — they fail fast.
|
|
1527
|
+
* The object form additionally sets the safety timeout (default 30000ms) after which an
|
|
1528
|
+
* abandoned transaction — e.g. the host server stopped calling resolvers because of a
|
|
1529
|
+
* non-null completion error — is rolled back instead of leaking a connection.
|
|
1530
|
+
*
|
|
1531
|
+
* Never nests: a caller-supplied executor on the GraphQL context under
|
|
1532
|
+
* `drizzleExecutorKey` always wins, and the library opens nothing of its own.
|
|
1533
|
+
*
|
|
1534
|
+
* Requirements and caveats:
|
|
1535
|
+
* - The driver must support `db.transaction()` (e.g. `neon-http` does not). For SQLite
|
|
1536
|
+
* only asynchronous drivers (libsql, better-sqlite3 is synchronous) can hold a
|
|
1537
|
+
* transaction open across resolvers; `buildSchema` throws for synchronous ones.
|
|
1538
|
+
* - The GraphQL context value must be a fresh object per request (every mainstream
|
|
1539
|
+
* server does this) — it keys the per-request transaction state.
|
|
1540
|
+
* - Documents that mix in mutation fields not generated by this build (consumer
|
|
1541
|
+
* extensions) are left alone: their completion cannot be tracked, so no transaction
|
|
1542
|
+
* is opened.
|
|
1543
|
+
*
|
|
1544
|
+
* @default 'none'
|
|
1545
|
+
*/
|
|
1546
|
+
transactions?: 'auto' | 'none' | {
|
|
1547
|
+
mode: 'auto';
|
|
1548
|
+
timeoutMs?: number;
|
|
1549
|
+
};
|
|
1550
|
+
/**
|
|
1551
|
+
* Bounds on the `limit` argument of list queries and to-many relation fields.
|
|
1552
|
+
*
|
|
1553
|
+
* Both knobs are off by default: without them a client can omit `limit` and pull a whole
|
|
1554
|
+
* table, or pass `limit: 1000000` and do the same thing politely. Turning either on changes
|
|
1555
|
+
* observable behavior for existing consumers, so nothing is applied unless asked for.
|
|
1556
|
+
*
|
|
1557
|
+
* ```ts
|
|
1558
|
+
* buildSchema(db, {
|
|
1559
|
+
* limits: {
|
|
1560
|
+
* defaultLimit: 50, // used when the client passes no `limit`
|
|
1561
|
+
* maxLimit: 500, // anything above is rejected
|
|
1562
|
+
* tables: {
|
|
1563
|
+
* auditLog: { defaultLimit: 20, maxLimit: 100 },
|
|
1564
|
+
* },
|
|
1565
|
+
* },
|
|
1566
|
+
* });
|
|
1567
|
+
* ```
|
|
1568
|
+
*
|
|
1569
|
+
* - Applies to root list queries **and** to to-many relation fields — an unbounded relation
|
|
1570
|
+
* inside a bounded root is the same scan one level down. A relation field takes the policy
|
|
1571
|
+
* of the table it *targets*, so a table is bounded wherever it is reached from. Single-row
|
|
1572
|
+
* queries and aggregates take no `limit` and are unaffected.
|
|
1573
|
+
* - A `limit` above `maxLimit` is rejected with a GraphQL error. Set `clampToMax: true` to
|
|
1574
|
+
* silently reduce it instead — honest paginating clients prefer the error, since a clamped
|
|
1575
|
+
* page looks like the end of the results.
|
|
1576
|
+
* - `maxLimit` on its own also bounds the *omitted* case: no `limit` means every row, which
|
|
1577
|
+
* is above any maximum. `defaultLimit` is what a request without `limit` gets, capped by
|
|
1578
|
+
* `maxLimit` if both are set.
|
|
1579
|
+
* - `tables` overrides per table, keyed by the Drizzle schema key. A table's entry replaces
|
|
1580
|
+
* the top-level value for whichever keys it sets.
|
|
1581
|
+
* - Cursor pagination inherits the same policy — a keyset page needs a limit to be
|
|
1582
|
+
* meaningful, and `defaultLimit` is what makes `after`-only pagination well-formed.
|
|
1583
|
+
* - The complexity hints price the *effective* limit, so cost estimation and enforcement
|
|
1584
|
+
* agree.
|
|
1585
|
+
*/
|
|
1586
|
+
limits?: LimitsConfig;
|
|
1587
|
+
/**
|
|
1588
|
+
* Per-table defaults for arguments the request leaves out. Today that is `orderBy`: the
|
|
1589
|
+
* presentation order a table has, declared once on the server instead of repeated by every
|
|
1590
|
+
* client.
|
|
1591
|
+
*
|
|
1592
|
+
* ```ts
|
|
1593
|
+
* buildSchema(db, {
|
|
1594
|
+
* defaults: {
|
|
1595
|
+
* Todos: { orderBy: { priority: 'desc', createdAt: 'desc' } },
|
|
1596
|
+
* AuditLog: { orderBy: { createdAt: { direction: 'desc', priority: 10 } } },
|
|
1597
|
+
* },
|
|
1598
|
+
* });
|
|
1599
|
+
* ```
|
|
1600
|
+
*
|
|
1601
|
+
* - Applies to the table's list and single queries, and to every to-many relation field
|
|
1602
|
+
* that *targets* it — a relation is ordered by the default of the table it reads, so a
|
|
1603
|
+
* table presents the same way wherever it is reached from. Eagerly and lazily loaded
|
|
1604
|
+
* relations agree.
|
|
1605
|
+
* - Only a missing `orderBy` is replaced. `orderBy: {}` is a request for no ordering and
|
|
1606
|
+
* stays one, and any `orderBy` the client sends replaces the default outright rather than
|
|
1607
|
+
* merging with it.
|
|
1608
|
+
* - Cursor pagination is defined over the effective ordering, so a default `orderBy` is
|
|
1609
|
+
* what an `after`-only page is ordered by. Changing a table's default changes what its
|
|
1610
|
+
* existing cursors mean.
|
|
1611
|
+
* - Entries name column property names of that table; a direction alone is shorthand for
|
|
1612
|
+
* `{ direction }`. Unknown table or column names throw at build time.
|
|
1613
|
+
* - Aggregates and `groupBy` take their own ordering and are unaffected.
|
|
1614
|
+
*
|
|
1615
|
+
* Off by default: a table with no entry keeps returning rows in whatever order the database
|
|
1616
|
+
* gives them, tiebroken by primary key where an operation needs a total order.
|
|
1617
|
+
*/
|
|
1618
|
+
defaults?: DefaultsConfig;
|
|
1619
|
+
/**
|
|
1620
|
+
* Row-level scoping: a predicate, derived from the GraphQL context, that every read and
|
|
1621
|
+
* write of a table is confined to. This is the multi-tenancy / ownership knob — the one
|
|
1622
|
+
* rule a wrapper cannot enforce from outside, because a nested relation field never passes
|
|
1623
|
+
* through a root resolver.
|
|
1624
|
+
*
|
|
1625
|
+
* ```ts
|
|
1626
|
+
* import { and, eq } from 'drizzle-orm';
|
|
1627
|
+
*
|
|
1628
|
+
* buildSchema(db, {
|
|
1629
|
+
* scope: {
|
|
1630
|
+
* posts: (ctx, table) => eq(table.orgId, ctx.orgId),
|
|
1631
|
+
* // A filter object works too, and can scope through a relation:
|
|
1632
|
+
* comments: (ctx) => ({ post: { orgId: { eq: ctx.orgId } } }),
|
|
1633
|
+
* },
|
|
1634
|
+
* });
|
|
1635
|
+
* ```
|
|
1636
|
+
*
|
|
1637
|
+
* - The predicate is ANDed on **last**, after the client's `where`, so a client filter can
|
|
1638
|
+
* only ever narrow the scope, never widen it.
|
|
1639
|
+
* - It applies to every path that reads the table: list and single queries, aggregates and
|
|
1640
|
+
* `groupBy`, relation fields (batched and eager), relation aggregates, and cursor pages.
|
|
1641
|
+
* - It applies to every path that writes it: `update`, `updateMany`, `delete`, the
|
|
1642
|
+
* conflict-update half of an upsert (PostgreSQL and SQLite), and the rows a nested
|
|
1643
|
+
* `connect` / `disconnect` / `set` is allowed to reach. An out-of-scope row is simply not
|
|
1644
|
+
* matched — a scoped `delete` reports zero rows rather than refusing.
|
|
1645
|
+
* - It cannot apply to a plain `insert`: there is no existing row to filter. Use
|
|
1646
|
+
* {@link BuildSchemaConfig.contextValues} to stamp the owning column on the way in.
|
|
1647
|
+
* - `table` is the table the current statement runs against, which for a relational read is
|
|
1648
|
+
* Drizzle's aliased copy — always build the predicate from that argument.
|
|
1649
|
+
* - Returning `undefined` means "no restriction for this context", so a hook can let an
|
|
1650
|
+
* admin through. A table with no entry is unscoped.
|
|
1651
|
+
* - MySQL's `ON DUPLICATE KEY UPDATE` takes no predicate, so a MySQL upsert cannot be
|
|
1652
|
+
* scoped on the conflict path; scope the table's `update` and rely on `contextValues`
|
|
1653
|
+
* for the insert half.
|
|
1654
|
+
*/
|
|
1655
|
+
scope?: ScopeConfig;
|
|
1656
|
+
/**
|
|
1657
|
+
* Columns whose value the server derives from the request context rather than accepting
|
|
1658
|
+
* from the client — the write-side half of {@link BuildSchemaConfig.scope}.
|
|
1659
|
+
*
|
|
1660
|
+
* ```ts
|
|
1661
|
+
* buildSchema(db, {
|
|
1662
|
+
* contextValues: {
|
|
1663
|
+
* posts: {
|
|
1664
|
+
* orgId: (ctx) => ctx.orgId,
|
|
1665
|
+
* authorId: (ctx) => ctx.userId,
|
|
1666
|
+
* },
|
|
1667
|
+
* },
|
|
1668
|
+
* });
|
|
1669
|
+
* ```
|
|
1670
|
+
*
|
|
1671
|
+
* - The column is removed from the generated insert and update inputs, so a client cannot
|
|
1672
|
+
* send it at all — the schema itself documents that it is server-owned.
|
|
1673
|
+
* - Every insert stamps it, including the rows created by a nested `create`.
|
|
1674
|
+
* - Updates never write it: an update cannot hand a row to another owner.
|
|
1675
|
+
* - Keyed by the Drizzle schema key, then by the column's property name (not its database
|
|
1676
|
+
* name), the same keying {@link BuildSchemaConfig.exclude} uses.
|
|
1677
|
+
*/
|
|
1678
|
+
contextValues?: ContextValuesConfig;
|
|
1679
|
+
/**
|
|
1680
|
+
* Tables that mark rows deleted instead of removing them.
|
|
1681
|
+
*
|
|
1682
|
+
* ```ts
|
|
1683
|
+
* buildSchema(db, {
|
|
1684
|
+
* softDelete: {
|
|
1685
|
+
* users: 'deletedAt', // nullable timestamp: stamped on delete
|
|
1686
|
+
* posts: { column: 'isDeleted', deletedValue: true, restoredValue: false },
|
|
1687
|
+
* },
|
|
1688
|
+
* });
|
|
1689
|
+
*
|
|
1690
|
+
* // or as a convention across the whole schema:
|
|
1691
|
+
* buildSchema(db, { softDelete: (table) => ('deletedAt' in table ? 'deletedAt' : undefined) });
|
|
1692
|
+
* ```
|
|
1693
|
+
*
|
|
1694
|
+
* For a table that declares one:
|
|
1695
|
+
*
|
|
1696
|
+
* - `delete<Table>` and `delete<Table>Single` issue an `UPDATE` of the marker column
|
|
1697
|
+
* instead of a `DELETE`, and return the rows as they now stand.
|
|
1698
|
+
* - `restore<Table>` and `restore<Table>Single` are generated alongside them, matching only
|
|
1699
|
+
* marked rows and writing the restored value. The prefix is configurable through
|
|
1700
|
+
* {@link BuildSchemaConfig.prefixes}.
|
|
1701
|
+
* - Every generated read hides marked rows: list and single queries, aggregates, `groupBy`,
|
|
1702
|
+
* relation fields on both the eager and the batched path, and relation aggregates. Each
|
|
1703
|
+
* of those fields takes a `deleted: EXCLUDE | INCLUDE | ONLY` argument (default
|
|
1704
|
+
* `EXCLUDE`); `ONLY` is a trash view.
|
|
1705
|
+
* - Every generated write skips them too: an `update`, a `delete`, or a nested `connect`
|
|
1706
|
+
* cannot reach a row that is already marked.
|
|
1707
|
+
* - The marker column is removed from the create and update inputs, so the only ways to set
|
|
1708
|
+
* or clear it are the delete and restore mutations.
|
|
1709
|
+
* - The predicate is ANDed on before {@link BuildSchemaConfig.scope}, and both are ANDed
|
|
1710
|
+
* after the client's `where` — a request can only ever narrow them.
|
|
1711
|
+
*
|
|
1712
|
+
* Two consequences of the pattern itself, which this does not paper over:
|
|
1713
|
+
*
|
|
1714
|
+
* - A marked row still occupies its unique keys, so inserting a row that reuses the natural
|
|
1715
|
+
* key of a deleted one still fails on the constraint.
|
|
1716
|
+
* - An upsert whose conflict target hits a marked row updates nothing on PostgreSQL and
|
|
1717
|
+
* SQLite (the conflict predicate excludes it) but revives it on MySQL, whose
|
|
1718
|
+
* `ON DUPLICATE KEY UPDATE` takes no predicate.
|
|
1719
|
+
*
|
|
1720
|
+
* Marking a parent deleted does not mark its children — a cascade is a schema decision.
|
|
1721
|
+
*/
|
|
1722
|
+
softDelete?: SoftDeleteConfig;
|
|
1723
|
+
/**
|
|
1724
|
+
* A hook that runs **inside the mutation's transaction**, so its writes commit or roll back
|
|
1725
|
+
* with the mutation itself — the position an audit row, an outbox row, or a denormalized
|
|
1726
|
+
* counter needs, and the one a `graphql-middleware` wrapper cannot occupy.
|
|
1727
|
+
*
|
|
1728
|
+
* ```ts
|
|
1729
|
+
* buildSchema(db, {
|
|
1730
|
+
* onWrite: {
|
|
1731
|
+
* posts: async ({ table, operation, rows, tx }) => {
|
|
1732
|
+
* await tx.insert(auditLog).values(rows.map((row) => ({ table, operation, rowId: row.id })));
|
|
1733
|
+
* },
|
|
1734
|
+
* },
|
|
1735
|
+
* });
|
|
1736
|
+
* ```
|
|
1737
|
+
*
|
|
1738
|
+
* A bare function is the **`after`** hook — the position that has rows. `{ before, after }`
|
|
1739
|
+
* names them explicitly; `before` receives the field's args ahead of the statement, for a
|
|
1740
|
+
* check that has to read inside the same snapshot. Registering a bare function (or a
|
|
1741
|
+
* positions object) at the top level applies it to every table; anything else is read as a
|
|
1742
|
+
* table map keyed by Drizzle schema key, and an unknown name fails the build.
|
|
1743
|
+
*
|
|
1744
|
+
* - **`tx` is the executor the mutation ran on** — a caller-supplied executor under
|
|
1745
|
+
* `drizzleExecutorKey`, the request's auto-transaction, or, for a field that would
|
|
1746
|
+
* otherwise have run unwrapped, a transaction opened for it because the hook is there.
|
|
1747
|
+
* - **Throwing rolls the mutation back.** That is the point of the position.
|
|
1748
|
+
* - **`rows` are the post-write rows as the database returned them**, before the output
|
|
1749
|
+
* mapper. Empty at the `before` position, and on MySQL, whose mutations return no rows.
|
|
1750
|
+
* - The hook fires for the **mutation field's own table**. Rows a nested write creates in
|
|
1751
|
+
* another table do not fire that table's hook.
|
|
1752
|
+
*
|
|
1753
|
+
* Off by default, and a build without it opens exactly the transactions it did before.
|
|
1754
|
+
*/
|
|
1755
|
+
onWrite?: OnWriteConfig;
|
|
1756
|
+
/**
|
|
1757
|
+
* Tables and columns to leave out of the generated schema entirely.
|
|
1758
|
+
*
|
|
1759
|
+
* ```ts
|
|
1760
|
+
* buildSchema(db, {
|
|
1761
|
+
* exclude: {
|
|
1762
|
+
* tables: ['magicLinks', 'sessions'],
|
|
1763
|
+
* columns: { apiKeys: ['keyHash'] },
|
|
1764
|
+
* },
|
|
1765
|
+
* });
|
|
1766
|
+
* ```
|
|
1767
|
+
*
|
|
1768
|
+
* An excluded **table** generates nothing: no object type, no root queries or mutations, no
|
|
1769
|
+
* aggregates, and no relation field on any other table that points at it. Filtering another
|
|
1770
|
+
* table by a relation to it is gone too, so it is unreachable rather than merely unnamed.
|
|
1771
|
+
*
|
|
1772
|
+
* An excluded **column** disappears from every surface at once — the object type, the
|
|
1773
|
+
* create/update/upsert inputs, the filter type, `orderBy`, the aggregate fields, the
|
|
1774
|
+
* `distinct` and `groupBy` enums, and the upsert conflict targets. The exclusion is
|
|
1775
|
+
* deliberately all-or-nothing: a column you can filter on but not select is an oracle, since
|
|
1776
|
+
* `where: { keyHash: { eq: '…' } }` confirms a value without ever returning it.
|
|
1777
|
+
*
|
|
1778
|
+
* Excluding a `NOT NULL` column that has no default makes that table's inserts impossible to
|
|
1779
|
+
* satisfy — `buildSchema` warns on the console when it sees this, and still builds, since a
|
|
1780
|
+
* read-only table is a reasonable thing to want.
|
|
1781
|
+
*
|
|
1782
|
+
* Names that match nothing throw, so a renamed column fails the build instead of quietly
|
|
1783
|
+
* un-hiding itself.
|
|
1784
|
+
*/
|
|
1785
|
+
exclude?: SchemaExclusions;
|
|
1786
|
+
/**
|
|
1787
|
+
* Optional mapper from table key to singular/plural name pair.
|
|
1788
|
+
* When provided for a table, overrides the default (table key) naming for GraphQL type names,
|
|
1789
|
+
* query field names, and mutation field names.
|
|
1790
|
+
* Return `undefined` for tables that should use the default naming.
|
|
1791
|
+
*
|
|
1792
|
+
* Example: `(name) => name === 'users' ? { singular: 'user', plural: 'users' } : undefined`
|
|
1793
|
+
* produces type `User`, queries `users` / `user`, mutations `createUsers` / `createUser` for
|
|
1794
|
+
* the `users` table, and leaves other tables with their default names.
|
|
1795
|
+
*
|
|
1796
|
+
* Pass the string `'singularize'` for the built-in preset, which derives both forms of every
|
|
1797
|
+
* table key with the library's own `pluralize` — the mapper most schemas with plural table
|
|
1798
|
+
* keys would otherwise write by hand:
|
|
1799
|
+
*
|
|
1800
|
+
* ```ts
|
|
1801
|
+
* buildSchema(db, { typeNameMapper: 'singularize' });
|
|
1802
|
+
* // tasks -> type Task, queries `tasks` / `task`, mutations `createTasks` / `createTask`
|
|
1803
|
+
* ```
|
|
1804
|
+
*
|
|
1805
|
+
* The same function is exported as `singularizeMapper` for wrapping — e.g. to keep one
|
|
1806
|
+
* table's names as they are: `(t) => (t === 'audit_log' ? undefined : singularizeMapper(t))`.
|
|
1807
|
+
*
|
|
1808
|
+
* The function half is the exported {@link TypeNameMapper}, so a mapper can be declared once
|
|
1809
|
+
* and handed both to `buildSchema` and to `selectionToWith` / `resolveSelection`, which need
|
|
1810
|
+
* the same naming rule to read a selection back out of a schema built with it.
|
|
1811
|
+
*/
|
|
1812
|
+
typeNameMapper?: 'singularize' | TypeNameMapper;
|
|
1813
|
+
/**
|
|
1814
|
+
* Renames the types generated *around* a table — the filter, the write inputs, the
|
|
1815
|
+
* order-by, the aggregate family, the group-by types, the conflict input, the shared scalar
|
|
1816
|
+
* filters. `typeNameMapper` names a table's object type and its root fields; those derived
|
|
1817
|
+
* names follow from it by a fixed rule, and this is the hook that overrides the rule.
|
|
1818
|
+
*
|
|
1819
|
+
* Asked once per generated type, with the kind, the name the library would use, and the
|
|
1820
|
+
* table it belongs to where it belongs to one. Return `undefined` — or the same name — to
|
|
1821
|
+
* keep the default, so a mapper that answers for one kind leaves everything else alone:
|
|
1822
|
+
*
|
|
1823
|
+
* ```ts
|
|
1824
|
+
* buildSchema(db, {
|
|
1825
|
+
* derivedTypeNameMapper: ({ kind, table, operation, defaultName }) =>
|
|
1826
|
+
* kind === 'aggregate' && operation ? `${table}Aggregate${operation}` : undefined,
|
|
1827
|
+
* });
|
|
1828
|
+
* ```
|
|
1829
|
+
*
|
|
1830
|
+
* A returned name is used verbatim — {@link BuildSchemaConfig.typeNamePrefix} and
|
|
1831
|
+
* {@link BuildSchemaConfig.typeNameSuffix} do not wrap it, since the more specific of the
|
|
1832
|
+
* two knobs wins.
|
|
1833
|
+
*
|
|
1834
|
+
* The point of it is stitching: a schema merged with a second generator over the same
|
|
1835
|
+
* tables collides on the derived names constantly, because both derive them from the model
|
|
1836
|
+
* name by the same obvious rule. Renaming them here means the collision never exists, rather
|
|
1837
|
+
* than being papered over by a `RenameTypes` transform on the way out.
|
|
1838
|
+
*/
|
|
1839
|
+
derivedTypeNameMapper?: DerivedTypeNameMapper;
|
|
1840
|
+
/**
|
|
1841
|
+
* Prepended to every generated type name — object types, filters, write inputs, the
|
|
1842
|
+
* aggregate family, the shared scalar filters, everything — that
|
|
1843
|
+
* {@link BuildSchemaConfig.derivedTypeNameMapper} did not answer for. The one-line way to
|
|
1844
|
+
* make a whole subschema collision-free before stitching it:
|
|
1845
|
+
*
|
|
1846
|
+
* ```ts
|
|
1847
|
+
* buildSchema(db, { typeNamePrefix: 'Db' });
|
|
1848
|
+
* // type DbUsers, input DbUsersFilters, input DbStringFilter, enum DbOrderNulls, …
|
|
1849
|
+
* ```
|
|
1850
|
+
*
|
|
1851
|
+
* Custom scalars, database enum types and `PgGeometryObject` keep their own names: their
|
|
1852
|
+
* definition does not vary between builds, so a gateway merges them rather than colliding
|
|
1853
|
+
* on them. Field and argument names are untouched too — only type names move, so a client's
|
|
1854
|
+
* queries are unaffected apart from the names it spells in variable declarations.
|
|
1855
|
+
*
|
|
1856
|
+
* Must be a valid GraphQL name start (`/^[_A-Za-z][_0-9A-Za-z]*$/`); anything else throws.
|
|
1857
|
+
*/
|
|
1858
|
+
typeNamePrefix?: string;
|
|
1859
|
+
/**
|
|
1860
|
+
* Appended to every generated type name that {@link BuildSchemaConfig.derivedTypeNameMapper}
|
|
1861
|
+
* did not answer for. The counterpart of {@link BuildSchemaConfig.typeNamePrefix}; both may
|
|
1862
|
+
* be given at once.
|
|
1863
|
+
*/
|
|
1864
|
+
typeNameSuffix?: string;
|
|
1865
|
+
/**
|
|
1866
|
+
* Controls whether a relation is eagerly pre-fetched via Drizzle's `with:` clause
|
|
1867
|
+
* when its parent is loaded through a generated query or mutation.
|
|
1868
|
+
*
|
|
1869
|
+
* `true` (default) — every selected relation is eager-loaded in the parent's query.
|
|
1870
|
+
*
|
|
1871
|
+
* `false` — no relation is ever eager-loaded; all relations resolve lazily through
|
|
1872
|
+
* their (request-batched) field resolvers.
|
|
1873
|
+
*
|
|
1874
|
+
* `(tableName, relationName) => boolean` — decide per relation. Return `false` to
|
|
1875
|
+
* exclude that relation from `with:` (and from the mutation eager re-fetch).
|
|
1876
|
+
*
|
|
1877
|
+
* Opting a relation out does NOT remove its field resolver — it still resolves
|
|
1878
|
+
* lazily via the request-scoped batch loader. This is the hook for overriding a
|
|
1879
|
+
* relation's resolver (e.g. via `@graphql-tools/schema`'s `addResolversToSchema`)
|
|
1880
|
+
* without the eager `with:` query also fetching it from the database:
|
|
1881
|
+
*
|
|
1882
|
+
* ```ts
|
|
1883
|
+
* const { schema } = buildSchema(db, {
|
|
1884
|
+
* eagerLoadRelations: (t, r) => !(t === 'Users' && r === 'posts'),
|
|
1885
|
+
* });
|
|
1886
|
+
* const finalSchema = addResolversToSchema({
|
|
1887
|
+
* schema,
|
|
1888
|
+
* resolvers: { Users: { posts: (parent) => myLoader.load(parent.id) } },
|
|
1889
|
+
* });
|
|
1890
|
+
* ```
|
|
1891
|
+
*
|
|
1892
|
+
* Table and relation names are the Drizzle schema keys (e.g. `Users`, `posts`),
|
|
1893
|
+
* matching the keys of `entities.fieldResolvers`.
|
|
1894
|
+
*
|
|
1895
|
+
* @default true
|
|
1896
|
+
*/
|
|
1897
|
+
eagerLoadRelations?: boolean | ((tableName: string, relationName: string) => boolean);
|
|
1898
|
+
/**
|
|
1899
|
+
* Declarative per-table, per-column scalar overrides — replaces the GraphQL type built-in
|
|
1900
|
+
* detection would pick for a column with the scalar you provide, everywhere that column's
|
|
1901
|
+
* type surfaces: the object type, create/update inputs, filter operands (in a filter type
|
|
1902
|
+
* named `${Scalar}Filter`), and aggregate min/max fields.
|
|
1903
|
+
*
|
|
1904
|
+
* Keys are the Drizzle schema keys: the table's key in your schema object and the column's
|
|
1905
|
+
* property name. The value is either one scalar for both directions, or `{ output, input }`
|
|
1906
|
+
* to type outputs and inputs differently (either side may be omitted to keep the default).
|
|
1907
|
+
*
|
|
1908
|
+
* ```ts
|
|
1909
|
+
* buildSchema(db, {
|
|
1910
|
+
* scalars: {
|
|
1911
|
+
* users: {
|
|
1912
|
+
* balance: GraphQLBigIntString, // both directions
|
|
1913
|
+
* settings: { output: PrettyJSON }, // output only, input stays default
|
|
1914
|
+
* },
|
|
1915
|
+
* },
|
|
1916
|
+
* });
|
|
1917
|
+
* ```
|
|
1918
|
+
*
|
|
1919
|
+
* Validation and coercion become the scalar's job: for an overridden column the generated
|
|
1920
|
+
* resolvers pass values through untouched — `parseValue`/`parseLiteral` results go to the
|
|
1921
|
+
* database driver as-is, and raw driver values go to `serialize` as-is — so the scalar must
|
|
1922
|
+
* accept what the driver produces and produce what the driver accepts.
|
|
1923
|
+
*
|
|
1924
|
+
* A declarative entry fully decides its column and wins over {@link mapColumnType}.
|
|
1925
|
+
*/
|
|
1926
|
+
scalars?: ScalarOverridesConfig;
|
|
1927
|
+
/**
|
|
1928
|
+
* Rule-based scalar mapping, called once per column at build time — the tool for applying
|
|
1929
|
+
* a convention across many columns (e.g. "every `numeric` column is `Money`") or for typing
|
|
1930
|
+
* custom column types the built-in detection does not know.
|
|
1931
|
+
*
|
|
1932
|
+
* Return a scalar (or `{ output, input }` pair) to override the column, or `undefined` to
|
|
1933
|
+
* keep the default. `info` carries the table/column schema keys and the types built-in
|
|
1934
|
+
* detection would use (`defaultType` / `defaultInputType`), so rules can key off either the
|
|
1935
|
+
* Drizzle column or the default GraphQL type.
|
|
1936
|
+
*
|
|
1937
|
+
* ```ts
|
|
1938
|
+
* buildSchema(db, {
|
|
1939
|
+
* mapColumnType: (column, { columnName }) =>
|
|
1940
|
+
* column.columnType === 'PgNumeric' ? MoneyScalar : undefined,
|
|
1941
|
+
* });
|
|
1942
|
+
* ```
|
|
1943
|
+
*
|
|
1944
|
+
* Same semantics as {@link scalars} otherwise; a column matched by both is decided by
|
|
1945
|
+
* `scalars` alone.
|
|
1946
|
+
*/
|
|
1947
|
+
mapColumnType?: ColumnTypeMapper;
|
|
1948
|
+
/**
|
|
1949
|
+
* Called for every error thrown by a generated resolver, before it reaches the client.
|
|
1950
|
+
*
|
|
1951
|
+
* Return an error to surface that one instead. Return nothing to fall through to the
|
|
1952
|
+
* default handling, which makes this a pure logging hook:
|
|
1953
|
+
*
|
|
1954
|
+
* ```ts
|
|
1955
|
+
* buildSchema(db, { onError: (error) => { logger.error(error) } })
|
|
1956
|
+
* ```
|
|
1957
|
+
*
|
|
1958
|
+
* The default passes through errors drizzle-graphql raises itself (bad filter, missing
|
|
1959
|
+
* values, invalid date, …) and replaces everything else — driver and database errors —
|
|
1960
|
+
* with a generic `Internal server error`, keeping the original on `originalError` so it
|
|
1961
|
+
* is still available to server-side logging. Database messages routinely name tables,
|
|
1962
|
+
* columns, constraints and the values that violated them, which is not something a
|
|
1963
|
+
* public API should hand back.
|
|
1964
|
+
*
|
|
1965
|
+
* To surface raw database errors instead (useful in development):
|
|
1966
|
+
*
|
|
1967
|
+
* ```ts
|
|
1968
|
+
* buildSchema(db, { onError: (error) => error as Error })
|
|
1969
|
+
* ```
|
|
1970
|
+
*/
|
|
1971
|
+
onError?: (error: unknown) => unknown;
|
|
1972
|
+
/**
|
|
1973
|
+
* Supplies the GraphQL `description` for a column, everywhere that column becomes a field:
|
|
1974
|
+
* the object type, the create/update inputs, the filter input, and the aggregate
|
|
1975
|
+
* `min`/`max`/`group` fields.
|
|
1976
|
+
*
|
|
1977
|
+
* Nothing is generated by default. The library used to emit the column's own type name
|
|
1978
|
+
* ("DateTime", "JSON") as its description, which documented nothing a reader could not see
|
|
1979
|
+
* from the type — that is gone, and this hook is what puts real prose in its place. Drizzle
|
|
1980
|
+
* carries no column-comment metadata to read, so the text has to come from here.
|
|
1981
|
+
*
|
|
1982
|
+
* ```ts
|
|
1983
|
+
* const columnDocs = { Users: { email: 'Primary contact address. Unique, case-insensitive.' } };
|
|
1984
|
+
*
|
|
1985
|
+
* buildSchema(db, {
|
|
1986
|
+
* describeColumn: (_column, { tableName, columnName }) => columnDocs[tableName]?.[columnName],
|
|
1987
|
+
* });
|
|
1988
|
+
* ```
|
|
1989
|
+
*
|
|
1990
|
+
* `tableName` and `columnName` are the Drizzle schema keys. Return `undefined` to leave the
|
|
1991
|
+
* field undocumented.
|
|
1992
|
+
*/
|
|
1993
|
+
describeColumn?: ColumnDescriber;
|
|
1994
|
+
/**
|
|
1995
|
+
* Supplies the GraphQL `description` for a table's object type.
|
|
1996
|
+
*
|
|
1997
|
+
* ```ts
|
|
1998
|
+
* buildSchema(db, { describeTable: (tableName) => tableDocs[tableName] });
|
|
1999
|
+
* ```
|
|
2000
|
+
*/
|
|
2001
|
+
describeTable?: TableDescriber;
|
|
2002
|
+
/**
|
|
2003
|
+
* Supplies the GraphQL `description` for a relation field on a table's object type.
|
|
2004
|
+
*
|
|
2005
|
+
* ```ts
|
|
2006
|
+
* buildSchema(db, {
|
|
2007
|
+
* describeRelation: (tableName, relationName) =>
|
|
2008
|
+
* tableName === 'Users' && relationName === 'posts' ? 'Posts this user authored.' : undefined,
|
|
2009
|
+
* });
|
|
2010
|
+
* ```
|
|
2011
|
+
*
|
|
2012
|
+
* The generated `<relation>Aggregate` companion fields are not covered — they are derived
|
|
2013
|
+
* fields rather than the relation itself.
|
|
2014
|
+
*/
|
|
2015
|
+
describeRelation?: RelationDescriber;
|
|
2016
|
+
/**
|
|
2017
|
+
* Supplies the GraphQL `deprecationReason` for a column, marking it `@deprecated` on the
|
|
2018
|
+
* object type and on the create/update inputs.
|
|
2019
|
+
*
|
|
2020
|
+
* ```ts
|
|
2021
|
+
* buildSchema(db, {
|
|
2022
|
+
* deprecateColumn: (_column, { columnName }) =>
|
|
2023
|
+
* columnName === 'legacyFlag' ? 'Use `status` instead.' : undefined,
|
|
2024
|
+
* });
|
|
2025
|
+
* ```
|
|
2026
|
+
*
|
|
2027
|
+
* A required input field cannot be deprecated — GraphQL rejects the schema, since a client
|
|
2028
|
+
* has no way to stop sending it — so the reason is dropped on non-null input fields and
|
|
2029
|
+
* kept everywhere else. Filter and orderBy fields are never deprecated either: filtering on
|
|
2030
|
+
* a deprecated column is how a caller finds the rows that still use it.
|
|
2031
|
+
*/
|
|
2032
|
+
deprecateColumn?: ColumnDeprecator;
|
|
2033
|
+
/**
|
|
2034
|
+
* Names the GraphQL enum types generated for enum columns.
|
|
2035
|
+
*
|
|
2036
|
+
* By default a column declared with a named `pgEnum` gets one shared type named after the
|
|
2037
|
+
* enum (`pgEnum('status', …)` → `StatusEnum`), reused by every column declared with that
|
|
2038
|
+
* same `pgEnum` — the database column is the same type, so a client variable typed
|
|
2039
|
+
* `StatusEnum!` is passable to any of them. A column with an inline value list
|
|
2040
|
+
* (`text({ enum: [...] })`, `mysqlEnum(...)`) keeps a per-column type named for its table
|
|
2041
|
+
* and column (`UsersRoleTextEnum`), because its values are shared with nothing.
|
|
2042
|
+
*
|
|
2043
|
+
* This hook overrides the name either way — for lining the schema up with another schema it
|
|
2044
|
+
* is stitched into, or for opting a specific column back into a type of its own:
|
|
2045
|
+
*
|
|
2046
|
+
* ```ts
|
|
2047
|
+
* buildSchema(db, {
|
|
2048
|
+
* enumNameMapper: (info) => (info.enumName === 'status' ? 'PublicationStatus' : undefined),
|
|
2049
|
+
* });
|
|
2050
|
+
* ```
|
|
2051
|
+
*
|
|
2052
|
+
* Two columns the mapper sends to the same name share one type when their values match —
|
|
2053
|
+
* the way to unify inline enums declared separately that mean the same thing. Sending two
|
|
2054
|
+
* *different* value lists to one name throws at build time rather than producing an
|
|
2055
|
+
* invalid schema.
|
|
2056
|
+
*
|
|
2057
|
+
* Return `undefined` to keep the default name.
|
|
2058
|
+
*/
|
|
2059
|
+
enumNameMapper?: EnumNameMapper;
|
|
2061
2060
|
};
|
|
2062
|
-
|
|
2061
|
+
//#endregion
|
|
2062
|
+
//#region src/util/case-ops/index.d.ts
|
|
2063
2063
|
/**
|
|
2064
2064
|
* The `typeNameMapper` preset behind `typeNameMapper: 'singularize'`.
|
|
2065
2065
|
*
|
|
@@ -2075,10 +2075,11 @@ type BuildSchemaConfig = {
|
|
|
2075
2075
|
* the schema key looks like. The type name is capitalized by the generator either way.
|
|
2076
2076
|
*/
|
|
2077
2077
|
declare const singularizeMapper: (tableName: string) => {
|
|
2078
|
-
|
|
2079
|
-
|
|
2078
|
+
singular: string;
|
|
2079
|
+
plural: string;
|
|
2080
2080
|
};
|
|
2081
|
-
|
|
2081
|
+
//#endregion
|
|
2082
|
+
//#region src/util/scalars/index.d.ts
|
|
2082
2083
|
/**
|
|
2083
2084
|
* A 64-bit integer. Always transported as a decimal string, in both directions, so no value
|
|
2084
2085
|
* is ever silently rounded by JSON's double-precision numbers. `graphql-scalars`' own
|
|
@@ -2093,27 +2094,28 @@ declare const GraphQLBigIntString: GraphQLScalarType<string, string>;
|
|
|
2093
2094
|
* non-numeric strings (including 'NaN' and 'Infinity').
|
|
2094
2095
|
*/
|
|
2095
2096
|
declare const GraphQLDecimalString: GraphQLScalarType<string, string>;
|
|
2096
|
-
|
|
2097
|
+
//#endregion
|
|
2098
|
+
//#region src/util/selection.d.ts
|
|
2097
2099
|
/** Options shared by {@link selectionToWith} and {@link resolveSelection}. */
|
|
2098
2100
|
type SelectionOptions = {
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2101
|
+
/** The drizzle instance the schema was built from. */
|
|
2102
|
+
db: AnyDrizzleDB<any>;
|
|
2103
|
+
/** The Drizzle schema key of the table the selection is rooted at. */
|
|
2104
|
+
table: string;
|
|
2105
|
+
/**
|
|
2106
|
+
* The `typeNameMapper` the schema was built with, when one was configured. The translation
|
|
2107
|
+
* matches selections against GraphQL type names, so a build that renames its types has to
|
|
2108
|
+
* pass the same mapper here or nothing will match.
|
|
2109
|
+
*/
|
|
2110
|
+
typeNameMapper?: TypeNameMapper;
|
|
2111
|
+
/**
|
|
2112
|
+
* The `derivedTypeNameMapper` / `typeNamePrefix` / `typeNameSuffix` the schema was built
|
|
2113
|
+
* with, when any were configured. Same reason as `typeNameMapper`: the translation matches
|
|
2114
|
+
* selections against the names the build actually published.
|
|
2115
|
+
*/
|
|
2116
|
+
derivedTypeNameMapper?: DerivedTypeNameMapper;
|
|
2117
|
+
typeNamePrefix?: string;
|
|
2118
|
+
typeNameSuffix?: string;
|
|
2117
2119
|
};
|
|
2118
2120
|
/**
|
|
2119
2121
|
* Translates a GraphQL selection set into the relational query builder's `with` tree — the
|
|
@@ -2139,21 +2141,21 @@ type SelectionOptions = {
|
|
|
2139
2141
|
declare const selectionToWith: (info: GraphQLResolveInfo | ResolveTree, options: SelectionOptions) => Record<string, any> | undefined;
|
|
2140
2142
|
/** Options for {@link resolveSelection} — the selection options plus the read itself. */
|
|
2141
2143
|
type ResolveSelectionOptions = SelectionOptions & {
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2144
|
+
/**
|
|
2145
|
+
* The transaction (or other drizzle executor) to read on. Defaults to `db`, so an override
|
|
2146
|
+
* that has opened its own transaction passes it here to see its own uncommitted writes.
|
|
2147
|
+
*/
|
|
2148
|
+
executor?: any;
|
|
2149
|
+
/** Whether to return one row or a list. A single read ignores `limit`. */
|
|
2150
|
+
single?: boolean;
|
|
2151
|
+
/** The generated `where` argument, in the schema's filter DSL — compiled the same way. */
|
|
2152
|
+
where?: any;
|
|
2153
|
+
/** The generated `orderBy` argument. */
|
|
2154
|
+
orderBy?: any;
|
|
2155
|
+
limit?: number;
|
|
2156
|
+
offset?: number;
|
|
2157
|
+
/** The generated `after` cursor argument, for keyset pagination. */
|
|
2158
|
+
after?: string;
|
|
2157
2159
|
};
|
|
2158
2160
|
/**
|
|
2159
2161
|
* Runs the read a generated select resolver would have run, against whichever executor is
|
|
@@ -2170,7 +2172,9 @@ type ResolveSelectionOptions = SelectionOptions & {
|
|
|
2170
2172
|
* because it is the generated schema's own code path.
|
|
2171
2173
|
*/
|
|
2172
2174
|
declare const resolveSelection: (info: GraphQLResolveInfo | ResolveTree, options: ResolveSelectionOptions) => Promise<any>;
|
|
2173
|
-
|
|
2175
|
+
//#endregion
|
|
2176
|
+
//#region src/index.d.ts
|
|
2174
2177
|
declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
|
|
2175
|
-
|
|
2176
|
-
export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ColumnDeprecator, type ColumnDescriber, type ColumnDocInfo, type ColumnTypeMapper, type ColumnTypeMapperInfo, type ComplexityConfig, type ContextValuesConfig, type DefaultOrderByEntry, type DefaultsConfig, type DeleteResolver, type DeleteSingleResolver, type DerivedTypeNameMapper, type DrizzleErrorCode, type DrizzleErrorContext, type DrizzleExtension, type DrizzleFieldExtension, type DrizzleFieldKind, type DrizzleFieldOperation, type DrizzleTargetArg, type DrizzleTypeExtension, type EnumNameInfo, type EnumNameMapper, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type FeatureSwitch, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, type GeneratedTypeInfo, type GeneratedTypeKind, GraphQLBigIntString, GraphQLDecimalString, type IdentifiedRows, type InsertArrResolver, type InsertResolver, type LimitsConfig, type MutationReturnlessResult, type MutationsCore, type OnWriteConfig, type QueriesCore, type RelationDescriber, type RelationResolverFactory, type ResolveSelectionOptions, type RowScope, type RowScopeFilter, type ScalarOverride, type ScalarOverridesConfig, type SchemaDocs, type SchemaExclusions, type SchemaFeatures, type ScopeConfig, type SelectResolver, type SelectSingleResolver, type SelectionOptions, type SoftDeleteColumn, type SoftDeleteConfig, type TableDefaults, type TableDescriber, type TableLimitPolicy, type TableNamedRelations, type TypeNameMapper, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, type WriteHook, type WriteHookPayload, type WriteHookPositions, type WriteHooks, type WriteOperation, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleError, drizzleExecutorKey, drizzleExtension, extractFilters, extractOrderBy, extractRelationJoinColumns, identifyRows, isDrizzleFieldExtension, resolveSelection, selectionToWith, singularizeMapper };
|
|
2178
|
+
//#endregion
|
|
2179
|
+
export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ColumnDeprecator, type ColumnDescriber, type ColumnDocInfo, type ColumnTypeMapper, type ColumnTypeMapperInfo, type ComplexityConfig, type ContextValuesConfig, type DefaultOrderByEntry, type DefaultsConfig, type DeleteResolver, type DeleteSingleResolver, type DerivedTypeNameMapper, type DrizzleErrorCode, type DrizzleErrorContext, type DrizzleExtension, type DrizzleFieldExtension, type DrizzleFieldKind, type DrizzleFieldOperation, type DrizzleTargetArg, type DrizzleTypeExtension, type EnumNameInfo, type EnumNameMapper, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type FeatureSwitch, type FieldsByTypeName, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, type GeneratedTypeInfo, type GeneratedTypeKind, GraphQLBigIntString, GraphQLDate, GraphQLDateTime, GraphQLDecimalString, GraphQLJSON, GraphQLUUID, type IdentifiedRows, type InsertArrResolver, type InsertResolver, type LimitsConfig, type MutationReturnlessResult, type MutationsCore, type OnWriteConfig, type ParseResolveInfoOptions, type QueriesCore, type RelationDescriber, type RelationResolverFactory, type ResolveSelectionOptions, type ResolveTree, type RowScope, type RowScopeFilter, type ScalarOverride, type ScalarOverridesConfig, type SchemaDocs, type SchemaExclusions, type SchemaFeatures, type ScopeConfig, type SelectResolver, type SelectSingleResolver, type SelectionOptions, type SoftDeleteColumn, type SoftDeleteConfig, type TableDefaults, type TableDescriber, type TableLimitPolicy, type TableNamedRelations, type TypeNameMapper, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, type WriteHook, type WriteHookPayload, type WriteHookPositions, type WriteHooks, type WriteOperation, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleError, drizzleExecutorKey, drizzleExtension, extractFilters, extractOrderBy, extractRelationJoinColumns, identifyRows, isDrizzleFieldExtension, parseResolveInfo, resolveSelection, selectionToWith, singularizeMapper };
|
|
2180
|
+
//# sourceMappingURL=index.d.cts.map
|