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