@vantreeseba/drizzle-graphql 5.5.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import { is as is7 } from "drizzle-orm";
2
+ import { is as is8 } from "drizzle-orm";
3
3
  import { MySqlDatabase } from "drizzle-orm/mysql-core";
4
4
  import { PgAsyncDatabase } from "drizzle-orm/pg-core";
5
5
  import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core";
@@ -17,6 +17,7 @@ import {
17
17
  asc,
18
18
  desc,
19
19
  eq,
20
+ extractExtendedColumnType as extractExtendedColumnType2,
20
21
  getColumns,
21
22
  getTableAsAliasSQL,
22
23
  gt,
@@ -104,200 +105,29 @@ var uncapitalize = (input) => input?.length ? `${input[0].toLocaleLowerCase()}${
104
105
  var capitalize = (input) => input?.length ? `${input[0].toLocaleUpperCase()}${input.length > 1 ? input.slice(1, input.length) : ""}` : input;
105
106
 
106
107
  // src/util/data-mappers/index.ts
107
- import { getTableColumns, is, One } from "drizzle-orm";
108
- import { GraphQLError } from "graphql";
109
- var isJsonColumn = (column) => (column.dataType ?? "").includes("json") && column.columnType !== "PgGeometryObject";
110
- var remapToGraphQLCore = (key, value, tableName, column, relationMap) => {
111
- if (Array.isArray(value)) {
112
- const relations = relationMap?.[tableName];
113
- if (relations?.[key]) {
114
- const rel = relations[key];
115
- return remapToGraphQLArrayOutput(
116
- value,
117
- rel.targetTableName,
118
- rel.relation?.targetTable ?? rel.relation?.referencedTable,
119
- relationMap
120
- );
121
- }
122
- }
123
- if (typeof value === "object" && value !== null) {
124
- const relations = relationMap?.[tableName];
125
- if (relations?.[key]) {
126
- const rel = relations[key];
127
- const remapped = remapToGraphQLSingleOutput(
128
- value,
129
- rel.targetTableName,
130
- rel.relation?.targetTable ?? rel.relation?.referencedTable,
131
- relationMap
132
- );
133
- return remapped;
134
- }
135
- }
136
- if (!column) {
137
- return value;
138
- }
139
- if (isJsonColumn(column)) {
140
- return value;
141
- }
142
- if (value instanceof Date) {
143
- return value.toISOString();
144
- }
145
- if (value instanceof Buffer) {
146
- return Array.from(value);
147
- }
148
- if (typeof value === "bigint") {
149
- return value.toString();
150
- }
151
- if (Array.isArray(value)) {
152
- if (column.columnType === "PgGeometry" || column.columnType === "PgVector") {
153
- return value;
154
- }
155
- return value.map((arrVal) => remapToGraphQLCore(key, arrVal, tableName, column, relationMap));
156
- }
157
- if (typeof value === "object" && value !== null) {
158
- if (column.columnType === "PgGeometryObject") {
159
- return value;
160
- }
161
- return JSON.stringify(value);
162
- }
163
- return value;
164
- };
165
- var remapToGraphQLSingleOutput = (queryOutput, tableName, table, relationMap) => {
166
- for (const [key, value] of Object.entries(queryOutput)) {
167
- if (value === void 0 || value === null) {
168
- const relEntry = value === null ? relationMap?.[tableName]?.[key] : void 0;
169
- if (relEntry && is(relEntry.relation, One)) {
170
- queryOutput[key] = null;
171
- continue;
172
- }
173
- delete queryOutput[key];
174
- continue;
175
- }
176
- const column = table[key];
177
- if (value === 0n && column && column.columnType === "SQLiteBigInt" && !column.notNull) {
178
- delete queryOutput[key];
179
- continue;
180
- }
181
- queryOutput[key] = remapToGraphQLCore(key, value, tableName, column, relationMap);
182
- }
183
- return queryOutput;
184
- };
185
- var remapToGraphQLArrayOutput = (queryOutput, tableName, table, relationMap) => {
186
- for (const entry of queryOutput) {
187
- remapToGraphQLSingleOutput(entry, tableName, table, relationMap);
188
- }
189
- return queryOutput;
190
- };
191
- var remapFromGraphQLCore = (value, column, columnName) => {
192
- const dataType = column.dataType ?? "";
193
- const columnType = column.columnType ?? "";
194
- const isTimestampColumn = columnType === "SQLiteTimestamp" || columnType === "SQLiteTimestampMs" || columnType === "MySqlTimestamp" || columnType === "MySqlDateTime" || columnType === "PgTimestamp" || columnType === "PgTimestampString";
195
- if (isTimestampColumn) {
196
- const formatted = new Date(value);
197
- if (Number.isNaN(formatted.getTime())) {
198
- throw new GraphQLError(`Field '${columnName}' is not a valid date!`);
199
- }
200
- return formatted;
201
- }
202
- const isDateOnlyColumn = columnType === "MySqlDate" || columnType === "PgDate";
203
- if (isDateOnlyColumn && typeof value === "string") {
204
- const dateOnly = value.includes("T") ? value.split("T")[0] : value;
205
- const check = new Date(dateOnly);
206
- if (Number.isNaN(check.getTime())) {
207
- throw new GraphQLError(`Field '${columnName}' is not a valid date!`);
208
- }
209
- return dateOnly;
210
- }
211
- if (dataType.includes("bigint")) {
212
- try {
213
- return BigInt(value);
214
- } catch {
215
- throw new GraphQLError(`Field '${columnName}' is not a BigInt!`);
216
- }
217
- }
218
- if (dataType.includes("json") && column.columnType !== "PgGeometryObject") {
219
- return value;
220
- }
221
- switch (dataType) {
222
- case "date": {
223
- const formatted = new Date(value);
224
- if (Number.isNaN(formatted.getTime())) {
225
- throw new GraphQLError(`Field '${columnName}' is not a valid date!`);
226
- }
227
- return formatted;
228
- }
229
- case "buffer": {
230
- if (!Array.isArray(value)) {
231
- throw new GraphQLError(`Field '${columnName}' is not an array!`);
232
- }
233
- return Buffer.from(value);
234
- }
235
- case "json": {
236
- if (column.columnType === "PgGeometryObject") {
237
- return value;
238
- }
239
- try {
240
- return JSON.parse(value);
241
- } catch (e) {
242
- throw new GraphQLError(
243
- `Invalid JSON in field '${columnName}':
244
- ${e instanceof Error ? e.message : "Unknown error"}`
245
- );
246
- }
247
- }
248
- case "array": {
249
- if (!Array.isArray(value)) {
250
- throw new GraphQLError(`Field '${columnName}' is not an array!`);
251
- }
252
- if (column.columnType === "PgGeometry" && value.length !== 2) {
253
- throw new GraphQLError(
254
- `Invalid float tuple in field '${columnName}': expected array with length of 2, received ${value.length}`
255
- );
256
- }
257
- return value;
258
- }
259
- case "bigint": {
260
- try {
261
- return BigInt(value);
262
- } catch (_error) {
263
- throw new GraphQLError(`Field '${columnName}' is not a BigInt!`);
264
- }
265
- }
266
- default: {
267
- if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) === null) {
268
- return Object.assign({}, value);
269
- }
270
- return value;
271
- }
272
- }
273
- };
274
- var remapFromGraphQLSingleInput = (queryInput, table) => {
275
- for (const [key, value] of Object.entries(queryInput)) {
276
- if (value === void 0) {
277
- delete queryInput[key];
278
- } else {
279
- const column = getTableColumns(table)[key];
280
- if (!column) {
281
- throw new GraphQLError(`Unknown column: ${key}`);
282
- }
283
- if (value === null && column.notNull) {
284
- delete queryInput[key];
285
- continue;
286
- }
287
- queryInput[key] = remapFromGraphQLCore(value, column, key);
288
- }
289
- }
290
- return queryInput;
291
- };
292
- var remapFromGraphQLArrayInput = (queryInput, table) => {
293
- for (const entry of queryInput) {
294
- remapFromGraphQLSingleInput(entry, table);
295
- }
296
- return queryInput;
297
- };
108
+ import { getTableColumns as getTableColumns2, is as is2, One } from "drizzle-orm";
109
+ import { GraphQLError as GraphQLError2 } from "graphql";
110
+
111
+ // src/util/type-converter/index.ts
112
+ import { extractExtendedColumnType, getTableColumns, is } from "drizzle-orm";
113
+ import { MySqlInt, MySqlSerial } from "drizzle-orm/mysql-core";
114
+ import { PgDate, PgDateString, PgInteger, PgSerial, PgTimestamp, PgTimestampString, PgUUID } from "drizzle-orm/pg-core";
115
+ import { SQLiteInteger } from "drizzle-orm/sqlite-core";
116
+ import {
117
+ GraphQLBoolean,
118
+ GraphQLEnumType,
119
+ GraphQLFloat,
120
+ GraphQLInputObjectType,
121
+ GraphQLInt,
122
+ GraphQLList,
123
+ GraphQLNonNull,
124
+ GraphQLObjectType,
125
+ GraphQLScalarType as GraphQLScalarType2,
126
+ GraphQLString
127
+ } from "graphql";
298
128
 
299
129
  // src/util/scalars/index.ts
300
- import { GraphQLError as GraphQLError2, GraphQLScalarType, Kind } from "graphql";
130
+ import { GraphQLError, GraphQLScalarType, Kind } from "graphql";
301
131
  import { GraphQLDate, GraphQLDateTime, GraphQLJSON, GraphQLUUID } from "graphql-scalars";
302
132
  var asDecimalString = (value) => {
303
133
  if (typeof value === "bigint") {
@@ -305,10 +135,10 @@ var asDecimalString = (value) => {
305
135
  }
306
136
  if (typeof value === "number") {
307
137
  if (!Number.isInteger(value)) {
308
- throw new GraphQLError2(`BigInt cannot represent non-integer value: ${value}`);
138
+ throw new GraphQLError(`BigInt cannot represent non-integer value: ${value}`);
309
139
  }
310
140
  if (!Number.isSafeInteger(value)) {
311
- throw new GraphQLError2(
141
+ throw new GraphQLError(
312
142
  `BigInt cannot represent the number ${value} without precision loss \u2014 pass it as a string instead`
313
143
  );
314
144
  }
@@ -316,11 +146,11 @@ var asDecimalString = (value) => {
316
146
  }
317
147
  if (typeof value === "string") {
318
148
  if (!/^-?\d+$/.test(value)) {
319
- throw new GraphQLError2(`BigInt cannot represent non-integer value: "${value}"`);
149
+ throw new GraphQLError(`BigInt cannot represent non-integer value: "${value}"`);
320
150
  }
321
151
  return value;
322
152
  }
323
- throw new GraphQLError2(`BigInt cannot represent value: ${JSON.stringify(value)}`);
153
+ throw new GraphQLError(`BigInt cannot represent value: ${JSON.stringify(value)}`);
324
154
  };
325
155
  var GraphQLBigIntString = new GraphQLScalarType({
326
156
  name: "BigInt",
@@ -329,7 +159,7 @@ var GraphQLBigIntString = new GraphQLScalarType({
329
159
  parseValue: asDecimalString,
330
160
  parseLiteral: (ast) => {
331
161
  if (ast.kind !== Kind.STRING && ast.kind !== Kind.INT) {
332
- throw new GraphQLError2(`BigInt cannot represent a ${ast.kind}`, { nodes: ast });
162
+ throw new GraphQLError(`BigInt cannot represent a ${ast.kind}`, { nodes: ast });
333
163
  }
334
164
  return asDecimalString(ast.value);
335
165
  }
@@ -341,17 +171,17 @@ var asNumericString = (value) => {
341
171
  }
342
172
  if (typeof value === "number") {
343
173
  if (!Number.isFinite(value)) {
344
- throw new GraphQLError2(`Decimal cannot represent non-finite value: ${value}`);
174
+ throw new GraphQLError(`Decimal cannot represent non-finite value: ${value}`);
345
175
  }
346
176
  return String(value);
347
177
  }
348
178
  if (typeof value === "string") {
349
179
  if (!numericStringPattern.test(value)) {
350
- throw new GraphQLError2(`Decimal cannot represent non-numeric value: "${value}"`);
180
+ throw new GraphQLError(`Decimal cannot represent non-numeric value: "${value}"`);
351
181
  }
352
182
  return value;
353
183
  }
354
- throw new GraphQLError2(`Decimal cannot represent value: ${JSON.stringify(value)}`);
184
+ throw new GraphQLError(`Decimal cannot represent value: ${JSON.stringify(value)}`);
355
185
  };
356
186
  var GraphQLDecimalString = new GraphQLScalarType({
357
187
  name: "Decimal",
@@ -360,38 +190,50 @@ var GraphQLDecimalString = new GraphQLScalarType({
360
190
  parseValue: asNumericString,
361
191
  parseLiteral: (ast) => {
362
192
  if (ast.kind !== Kind.STRING && ast.kind !== Kind.INT && ast.kind !== Kind.FLOAT) {
363
- throw new GraphQLError2(`Decimal cannot represent a ${ast.kind}`, { nodes: ast });
193
+ throw new GraphQLError(`Decimal cannot represent a ${ast.kind}`, { nodes: ast });
364
194
  }
365
195
  return asNumericString(ast.value);
366
196
  }
367
197
  });
368
198
 
369
199
  // src/util/type-converter/index.ts
370
- import { extractExtendedColumnType, is as is2 } from "drizzle-orm";
371
- import { MySqlInt, MySqlSerial } from "drizzle-orm/mysql-core";
372
- import { PgDate, PgDateString, PgInteger, PgSerial, PgTimestamp, PgTimestampString, PgUUID } from "drizzle-orm/pg-core";
373
- import { SQLiteInteger } from "drizzle-orm/sqlite-core";
374
- import {
375
- GraphQLBoolean,
376
- GraphQLEnumType,
377
- GraphQLFloat,
378
- GraphQLInputObjectType,
379
- GraphQLInt,
380
- GraphQLList,
381
- GraphQLNonNull,
382
- GraphQLObjectType,
383
- GraphQLString
384
- } from "graphql";
385
200
  var allowedNameChars = /^[a-zA-Z0-9_]+$/;
386
- var enumMap = /* @__PURE__ */ new WeakMap();
201
+ var declaredEnum = (column) => {
202
+ const declared = column.enum;
203
+ return typeof declared?.enumName === "string" ? { enumName: declared.enumName, schema: typeof declared.schema === "string" ? declared.schema : void 0 } : void 0;
204
+ };
205
+ var pascalize = (input) => input.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => capitalize(part)).join("");
206
+ var enumValuesKey = (values) => JSON.stringify(values);
207
+ var enumNamesInUse = /* @__PURE__ */ new Map();
208
+ var enumNameMapper;
209
+ var registerEnumConfig = (config) => {
210
+ enumNameMapper = config.enumNameMapper;
211
+ enumNamesInUse = /* @__PURE__ */ new Map();
212
+ };
387
213
  var generateEnumCached = (column, columnName, tableName) => {
388
- if (enumMap.has(column)) {
389
- return enumMap.get(column);
214
+ const declared = declaredEnum(column);
215
+ const values = column.enumValues;
216
+ const name = enumNameMapper?.({
217
+ enumName: declared?.enumName,
218
+ schema: declared?.schema,
219
+ tableName,
220
+ columnName,
221
+ values
222
+ }) ?? (declared ? `${pascalize(declared.enumName)}Enum` : `${capitalize(tableName)}${capitalize(columnName)}Enum`);
223
+ const valuesKey = enumValuesKey(values);
224
+ const claimed = enumNamesInUse.get(name);
225
+ if (claimed) {
226
+ if (claimed.valuesKey !== valuesKey) {
227
+ throw new Error(
228
+ `Drizzle-GraphQL Error: Two different enums both map to the GraphQL type name '${name}' (most recently '${tableName}.${columnName}'). Give one of them a different name via config.enumNameMapper.`
229
+ );
230
+ }
231
+ return claimed.type;
390
232
  }
391
233
  const gqlEnum = new GraphQLEnumType({
392
- name: `${capitalize(tableName)}${capitalize(columnName)}Enum`,
234
+ name,
393
235
  values: Object.fromEntries(
394
- column.enumValues.map((e, index) => [
236
+ values.map((e, index) => [
395
237
  allowedNameChars.test(e) ? e : `Option${index}`,
396
238
  {
397
239
  value: e,
@@ -400,7 +242,7 @@ var generateEnumCached = (column, columnName, tableName) => {
400
242
  ])
401
243
  )
402
244
  });
403
- enumMap.set(column, gqlEnum);
245
+ enumNamesInUse.set(name, { type: gqlEnum, valuesKey });
404
246
  return gqlEnum;
405
247
  };
406
248
  var geoXyType = new GraphQLObjectType({
@@ -421,100 +263,343 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
421
263
  const dimensions = column.dimensions;
422
264
  if (dimensions !== void 0 && dimensions > 0) {
423
265
  const inner = columnBaseToGraphQLCore(column, columnName, tableName, isInput);
424
- const innerDesc = inner.description ?? inner.type.name;
266
+ const innerLabel = inner.typeLabel ?? inner.type.name;
425
267
  let type = inner.type;
426
- let description = innerDesc;
268
+ let typeLabel = innerLabel;
427
269
  for (let i = 0; i < dimensions; i++) {
428
270
  type = new GraphQLList(new GraphQLNonNull(type));
429
- description = `Array<${description}>`;
271
+ typeLabel = `Array<${typeLabel}>`;
272
+ }
273
+ return { type, typeLabel };
274
+ }
275
+ return columnBaseToGraphQLCore(column, columnName, tableName, isInput);
276
+ };
277
+ var columnBaseToGraphQLCore = (column, columnName, tableName, isInput) => {
278
+ const { type: baseType, constraint } = extractExtendedColumnType(column);
279
+ switch (baseType) {
280
+ case "boolean":
281
+ return { type: GraphQLBoolean, typeLabel: "Boolean" };
282
+ case "object":
283
+ if (column instanceof PgTimestamp || column instanceof PgDate) {
284
+ return { type: GraphQLDateTime, typeLabel: "DateTime" };
285
+ }
286
+ return column.columnType === "PgGeometryObject" ? {
287
+ type: isInput ? geoXyInputType : geoXyType,
288
+ typeLabel: "Geometry points XY"
289
+ } : column.columnType === "PgBytea" ? {
290
+ type: new GraphQLList(new GraphQLNonNull(GraphQLInt)),
291
+ typeLabel: "Buffer"
292
+ } : { type: GraphQLJSON, typeLabel: "JSON" };
293
+ case "string":
294
+ if (column.enumValues?.length) {
295
+ return { type: generateEnumCached(column, columnName, tableName) };
296
+ }
297
+ if (constraint === "numeric" && !column.dimensions) {
298
+ return { type: GraphQLDecimalString, typeLabel: "Decimal" };
299
+ }
300
+ if (column instanceof PgTimestamp || column instanceof PgTimestampString) {
301
+ return { type: GraphQLDateTime, typeLabel: "DateTime" };
302
+ }
303
+ if (column instanceof PgUUID) {
304
+ return { type: GraphQLUUID, typeLabel: "UUID" };
305
+ }
306
+ if (column instanceof PgDateString) {
307
+ return isInput ? { type: GraphQLString, typeLabel: "Date" } : { type: GraphQLDate, typeLabel: "Date" };
308
+ }
309
+ return { type: GraphQLString, typeLabel: "String" };
310
+ case "bigint":
311
+ return { type: GraphQLBigIntString, typeLabel: "BigInt" };
312
+ case "number": {
313
+ return is(column, PgInteger) || is(column, PgSerial) || is(column, MySqlInt) || is(column, MySqlSerial) || is(column, SQLiteInteger) ? { type: GraphQLInt, typeLabel: "Integer" } : { type: GraphQLFloat, typeLabel: "Float" };
314
+ }
315
+ case "array": {
316
+ if (column.columnType === "PgVector") {
317
+ return {
318
+ type: new GraphQLList(new GraphQLNonNull(GraphQLFloat)),
319
+ typeLabel: "Array<Float>"
320
+ };
321
+ }
322
+ if (column.columnType === "PgGeometry") {
323
+ return {
324
+ type: new GraphQLList(new GraphQLNonNull(GraphQLFloat)),
325
+ typeLabel: "Tuple<[Float, Float]>"
326
+ };
327
+ }
328
+ const innerType = columnToGraphQLCore(
329
+ column.baseColumn,
330
+ columnName,
331
+ tableName,
332
+ isInput
333
+ );
334
+ return {
335
+ type: new GraphQLList(new GraphQLNonNull(innerType.type)),
336
+ typeLabel: `Array<${innerType.typeLabel}>`
337
+ };
338
+ }
339
+ default:
340
+ throw new Error(`Drizzle-GraphQL Error: Type ${column.dataType} is not implemented!`);
341
+ }
342
+ };
343
+ var columnScalarOverrides = /* @__PURE__ */ new WeakMap();
344
+ var getColumnScalarOverride = (column, isInput) => {
345
+ const override = columnScalarOverrides.get(column);
346
+ return override ? isInput ? override.input : override.output : void 0;
347
+ };
348
+ var normalizeScalarOverride = (override, tableName, columnName) => {
349
+ const pair = override instanceof GraphQLScalarType2 ? { output: override, input: override } : { output: override.output, input: override.input };
350
+ for (const scalar of [pair.output, pair.input]) {
351
+ if (scalar !== void 0 && !(scalar instanceof GraphQLScalarType2)) {
352
+ throw new Error(
353
+ `Drizzle-GraphQL Error: Scalar override for column '${tableName}.${columnName}' must be a GraphQLScalarType!`
354
+ );
355
+ }
356
+ }
357
+ return pair;
358
+ };
359
+ var registerScalarOverrides = (tables, config) => {
360
+ for (const [tableName, table] of Object.entries(tables)) {
361
+ for (const [columnName, column] of Object.entries(getTableColumns(table))) {
362
+ const declared = config.scalars?.[tableName]?.[columnName];
363
+ let resolved;
364
+ if (declared !== void 0) {
365
+ resolved = normalizeScalarOverride(declared, tableName, columnName);
366
+ } else if (config.mapColumnType) {
367
+ let defaultType;
368
+ let defaultInputType;
369
+ try {
370
+ defaultType = columnToGraphQLCore(column, columnName, tableName, false).type;
371
+ } catch {
372
+ }
373
+ try {
374
+ defaultInputType = columnToGraphQLCore(column, columnName, tableName, true).type;
375
+ } catch {
376
+ }
377
+ const mapped = config.mapColumnType(column, { tableName, columnName, defaultType, defaultInputType });
378
+ if (mapped !== void 0) {
379
+ resolved = normalizeScalarOverride(mapped, tableName, columnName);
380
+ }
381
+ }
382
+ if (resolved && (resolved.output !== void 0 || resolved.input !== void 0)) {
383
+ columnScalarOverrides.set(column, resolved);
384
+ } else {
385
+ columnScalarOverrides.delete(column);
386
+ }
387
+ }
388
+ }
389
+ };
390
+ var drizzleColumnToGraphQLType = (column, columnName, tableName, forceNullable = false, defaultIsNullable = false, isInput = false) => {
391
+ const override = getColumnScalarOverride(column, isInput);
392
+ const typeDesc = override ? { type: override, typeLabel: override.name } : columnToGraphQLCore(column, columnName, tableName, isInput);
393
+ if (forceNullable) {
394
+ return typeDesc;
395
+ }
396
+ if (column.notNull && !(defaultIsNullable && (column.hasDefault || column.defaultFn))) {
397
+ return {
398
+ type: new GraphQLNonNull(typeDesc.type),
399
+ typeLabel: typeDesc.typeLabel
400
+ };
401
+ }
402
+ return typeDesc;
403
+ };
404
+
405
+ // src/util/data-mappers/index.ts
406
+ var isJsonColumn = (column) => (column.dataType ?? "").includes("json") && column.columnType !== "PgGeometryObject";
407
+ var remapToGraphQLCore = (key, value, tableName, column, relationMap) => {
408
+ if (Array.isArray(value)) {
409
+ const relations = relationMap?.[tableName];
410
+ if (relations?.[key]) {
411
+ const rel = relations[key];
412
+ return remapToGraphQLArrayOutput(
413
+ value,
414
+ rel.targetTableName,
415
+ rel.relation?.targetTable ?? rel.relation?.referencedTable,
416
+ relationMap
417
+ );
418
+ }
419
+ }
420
+ if (typeof value === "object" && value !== null) {
421
+ const relations = relationMap?.[tableName];
422
+ if (relations?.[key]) {
423
+ const rel = relations[key];
424
+ const remapped = remapToGraphQLSingleOutput(
425
+ value,
426
+ rel.targetTableName,
427
+ rel.relation?.targetTable ?? rel.relation?.referencedTable,
428
+ relationMap
429
+ );
430
+ return remapped;
431
+ }
432
+ }
433
+ if (!column) {
434
+ return value;
435
+ }
436
+ if (getColumnScalarOverride(column, false)) {
437
+ return value;
438
+ }
439
+ if (isJsonColumn(column)) {
440
+ return value;
441
+ }
442
+ if (value instanceof Date) {
443
+ return value.toISOString();
444
+ }
445
+ if (value instanceof Buffer) {
446
+ return Array.from(value);
447
+ }
448
+ if (typeof value === "bigint") {
449
+ return value.toString();
450
+ }
451
+ if (Array.isArray(value)) {
452
+ if (column.columnType === "PgGeometry" || column.columnType === "PgVector") {
453
+ return value;
454
+ }
455
+ return value.map((arrVal) => remapToGraphQLCore(key, arrVal, tableName, column, relationMap));
456
+ }
457
+ if (typeof value === "object" && value !== null) {
458
+ if (column.columnType === "PgGeometryObject") {
459
+ return value;
460
+ }
461
+ return JSON.stringify(value);
462
+ }
463
+ return value;
464
+ };
465
+ var remapToGraphQLSingleOutput = (queryOutput, tableName, table, relationMap) => {
466
+ for (const [key, value] of Object.entries(queryOutput)) {
467
+ if (value === void 0 || value === null) {
468
+ const relEntry = value === null ? relationMap?.[tableName]?.[key] : void 0;
469
+ if (relEntry && is2(relEntry.relation, One)) {
470
+ queryOutput[key] = null;
471
+ continue;
472
+ }
473
+ delete queryOutput[key];
474
+ continue;
475
+ }
476
+ const column = table[key];
477
+ if (value === 0n && column && column.columnType === "SQLiteBigInt" && !column.notNull) {
478
+ delete queryOutput[key];
479
+ continue;
480
+ }
481
+ queryOutput[key] = remapToGraphQLCore(key, value, tableName, column, relationMap);
482
+ }
483
+ return queryOutput;
484
+ };
485
+ var remapToGraphQLArrayOutput = (queryOutput, tableName, table, relationMap) => {
486
+ for (const entry of queryOutput) {
487
+ remapToGraphQLSingleOutput(entry, tableName, table, relationMap);
488
+ }
489
+ return queryOutput;
490
+ };
491
+ var remapFromGraphQLCore = (value, column, columnName) => {
492
+ if (getColumnScalarOverride(column, true)) {
493
+ if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) === null) {
494
+ return Object.assign({}, value);
495
+ }
496
+ return value;
497
+ }
498
+ const dataType = column.dataType ?? "";
499
+ const columnType = column.columnType ?? "";
500
+ const isTimestampColumn = columnType === "SQLiteTimestamp" || columnType === "SQLiteTimestampMs" || columnType === "MySqlTimestamp" || columnType === "MySqlDateTime" || columnType === "PgTimestamp" || columnType === "PgTimestampString";
501
+ if (isTimestampColumn) {
502
+ const formatted = new Date(value);
503
+ if (Number.isNaN(formatted.getTime())) {
504
+ throw new GraphQLError2(`Field '${columnName}' is not a valid date!`);
505
+ }
506
+ return formatted;
507
+ }
508
+ const isDateOnlyColumn = columnType === "MySqlDate" || columnType === "PgDate";
509
+ if (isDateOnlyColumn && typeof value === "string") {
510
+ const dateOnly = value.includes("T") ? value.split("T")[0] : value;
511
+ const check = new Date(dateOnly);
512
+ if (Number.isNaN(check.getTime())) {
513
+ throw new GraphQLError2(`Field '${columnName}' is not a valid date!`);
514
+ }
515
+ return dateOnly;
516
+ }
517
+ if (dataType.includes("bigint")) {
518
+ try {
519
+ return BigInt(value);
520
+ } catch {
521
+ throw new GraphQLError2(`Field '${columnName}' is not a BigInt!`);
430
522
  }
431
- return { type, description };
432
523
  }
433
- return columnBaseToGraphQLCore(column, columnName, tableName, isInput);
434
- };
435
- var columnBaseToGraphQLCore = (column, columnName, tableName, isInput) => {
436
- const { type: baseType, constraint } = extractExtendedColumnType(column);
437
- switch (baseType) {
438
- case "boolean":
439
- return { type: GraphQLBoolean, description: "Boolean" };
440
- case "object":
441
- if (column instanceof PgTimestamp || column instanceof PgDate) {
442
- return { type: GraphQLDateTime, description: "DateTime" };
524
+ if (dataType.includes("json") && column.columnType !== "PgGeometryObject") {
525
+ return value;
526
+ }
527
+ switch (dataType) {
528
+ case "date": {
529
+ const formatted = new Date(value);
530
+ if (Number.isNaN(formatted.getTime())) {
531
+ throw new GraphQLError2(`Field '${columnName}' is not a valid date!`);
443
532
  }
444
- return column.columnType === "PgGeometryObject" ? {
445
- type: isInput ? geoXyInputType : geoXyType,
446
- description: "Geometry points XY"
447
- } : column.columnType === "PgBytea" ? {
448
- type: new GraphQLList(new GraphQLNonNull(GraphQLInt)),
449
- description: "Buffer"
450
- } : { type: GraphQLJSON, description: "JSON" };
451
- case "string":
452
- if (column.enumValues?.length) {
453
- return { type: generateEnumCached(column, columnName, tableName) };
533
+ return formatted;
534
+ }
535
+ case "buffer": {
536
+ if (!Array.isArray(value)) {
537
+ throw new GraphQLError2(`Field '${columnName}' is not an array!`);
454
538
  }
455
- if (constraint === "numeric" && !column.dimensions) {
456
- return { type: GraphQLDecimalString, description: "Decimal" };
539
+ return Buffer.from(value);
540
+ }
541
+ case "json": {
542
+ if (column.columnType === "PgGeometryObject") {
543
+ return value;
457
544
  }
458
- if (column instanceof PgTimestamp || column instanceof PgTimestampString) {
459
- return { type: GraphQLDateTime, description: "DateTime" };
545
+ try {
546
+ return JSON.parse(value);
547
+ } catch (e) {
548
+ throw new GraphQLError2(
549
+ `Invalid JSON in field '${columnName}':
550
+ ${e instanceof Error ? e.message : "Unknown error"}`
551
+ );
460
552
  }
461
- if (column instanceof PgUUID) {
462
- return { type: GraphQLUUID, description: "UUID" };
553
+ }
554
+ case "array": {
555
+ if (!Array.isArray(value)) {
556
+ throw new GraphQLError2(`Field '${columnName}' is not an array!`);
463
557
  }
464
- if (column instanceof PgDateString) {
465
- return isInput ? { type: GraphQLString, description: "Date" } : { type: GraphQLDate, description: "Date" };
558
+ if (column.columnType === "PgGeometry" && value.length !== 2) {
559
+ throw new GraphQLError2(
560
+ `Invalid float tuple in field '${columnName}': expected array with length of 2, received ${value.length}`
561
+ );
466
562
  }
467
- return { type: GraphQLString, description: "String" };
468
- case "bigint":
469
- return { type: GraphQLBigIntString, description: "BigInt" };
470
- case "number": {
471
- return is2(column, PgInteger) || is2(column, PgSerial) || is2(column, MySqlInt) || is2(column, MySqlSerial) || is2(column, SQLiteInteger) ? { type: GraphQLInt, description: "Integer" } : { type: GraphQLFloat, description: "Float" };
563
+ return value;
472
564
  }
473
- case "array": {
474
- if (column.columnType === "PgVector") {
475
- return {
476
- type: new GraphQLList(new GraphQLNonNull(GraphQLFloat)),
477
- description: "Array<Float>"
478
- };
565
+ case "bigint": {
566
+ try {
567
+ return BigInt(value);
568
+ } catch (_error) {
569
+ throw new GraphQLError2(`Field '${columnName}' is not a BigInt!`);
479
570
  }
480
- if (column.columnType === "PgGeometry") {
481
- return {
482
- type: new GraphQLList(new GraphQLNonNull(GraphQLFloat)),
483
- description: "Tuple<[Float, Float]>"
484
- };
571
+ }
572
+ default: {
573
+ if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) === null) {
574
+ return Object.assign({}, value);
485
575
  }
486
- const innerType = columnToGraphQLCore(
487
- column.baseColumn,
488
- columnName,
489
- tableName,
490
- isInput
491
- );
492
- return {
493
- type: new GraphQLList(new GraphQLNonNull(innerType.type)),
494
- description: `Array<${innerType.description}>`
495
- };
576
+ return value;
496
577
  }
497
- default:
498
- throw new Error(`Drizzle-GraphQL Error: Type ${column.dataType} is not implemented!`);
499
578
  }
500
579
  };
501
- var drizzleColumnToGraphQLType = (column, columnName, tableName, forceNullable = false, defaultIsNullable = false, isInput = false) => {
502
- const typeDesc = columnToGraphQLCore(column, columnName, tableName, isInput);
503
- const noDesc = ["string", "boolean", "number"];
504
- const { type: baseType } = extractExtendedColumnType(column);
505
- if (noDesc.find((e) => e === baseType)) {
506
- delete typeDesc.description;
507
- }
508
- if (forceNullable) {
509
- return typeDesc;
580
+ var remapFromGraphQLSingleInput = (queryInput, table) => {
581
+ for (const [key, value] of Object.entries(queryInput)) {
582
+ if (value === void 0) {
583
+ delete queryInput[key];
584
+ } else {
585
+ const column = getTableColumns2(table)[key];
586
+ if (!column) {
587
+ throw new GraphQLError2(`Unknown column: ${key}`);
588
+ }
589
+ if (value === null && column.notNull) {
590
+ delete queryInput[key];
591
+ continue;
592
+ }
593
+ queryInput[key] = remapFromGraphQLCore(value, column, key);
594
+ }
510
595
  }
511
- if (column.notNull && !(defaultIsNullable && (column.hasDefault || column.defaultFn))) {
512
- return {
513
- type: new GraphQLNonNull(typeDesc.type),
514
- description: typeDesc.description
515
- };
596
+ return queryInput;
597
+ };
598
+ var remapFromGraphQLArrayInput = (queryInput, table) => {
599
+ for (const entry of queryInput) {
600
+ remapFromGraphQLSingleInput(entry, table);
516
601
  }
517
- return typeDesc;
602
+ return queryInput;
518
603
  };
519
604
 
520
605
  // src/util/builders/common.ts
@@ -894,6 +979,22 @@ var createRelationResolverFactory = (db, tables, filterCtx) => ({ tableName, rel
894
979
  return loader.load(localValue);
895
980
  };
896
981
  };
982
+ var columnDocs = (docs, column, tableName, columnName) => {
983
+ const description = docs.describeColumn?.(column, { tableName, columnName });
984
+ const deprecationReason = docs.deprecateColumn?.(column, { tableName, columnName });
985
+ return {
986
+ ...description !== void 0 ? { description } : {},
987
+ ...deprecationReason !== void 0 ? { deprecationReason } : {}
988
+ };
989
+ };
990
+ var inputFieldDocs = (docs, column, tableName, columnName, fieldType) => {
991
+ const resolved = columnDocs(docs, column, tableName, columnName);
992
+ if (resolved.deprecationReason !== void 0 && fieldType instanceof GraphQLNonNull2) {
993
+ const { deprecationReason: _dropped, ...rest } = resolved;
994
+ return rest;
995
+ }
996
+ return resolved;
997
+ };
897
998
  var listFieldComplexity = (options) => ({ args, childComplexity }) => {
898
999
  const limit = args["limit"];
899
1000
  const rows = typeof limit === "number" && limit > 0 ? limit : options.defaultListSize;
@@ -901,18 +1002,21 @@ var listFieldComplexity = (options) => ({ args, childComplexity }) => {
901
1002
  };
902
1003
  var aggregateFieldComplexity = (options) => ({ childComplexity }) => options.aggregateCost + childComplexity;
903
1004
  var AGGREGATE_FIELD_SUFFIX = "Aggregate";
904
- var relationAggregateJoinColumns = (tree, table, selectionCtx) => {
905
- const relations = selectionCtx?.relationMap[selectionCtx.tableName];
906
- if (!relations || !selectionCtx) {
1005
+ var relationJoinColumns = (tree, table, selectionCtx) => {
1006
+ if (!selectionCtx) {
1007
+ return [];
1008
+ }
1009
+ const relations = (selectionCtx.allRelations ?? selectionCtx.relationMap)[selectionCtx.tableName] ?? selectionCtx.relationMap[selectionCtx.tableName];
1010
+ if (!relations) {
907
1011
  return [];
908
1012
  }
909
1013
  const tableColumns = getColumns(table);
910
1014
  const needed = [];
911
1015
  for (const fieldData of Object.values(tree)) {
912
- if (tableColumns[fieldData.name] || !fieldData.name.endsWith(AGGREGATE_FIELD_SUFFIX)) {
1016
+ if (tableColumns[fieldData.name]) {
913
1017
  continue;
914
1018
  }
915
- const relEntry = relations[fieldData.name.slice(0, -AGGREGATE_FIELD_SUFFIX.length)];
1019
+ const relEntry = fieldData.name.endsWith(AGGREGATE_FIELD_SUFFIX) ? relations[fieldData.name.slice(0, -AGGREGATE_FIELD_SUFFIX.length)] : relations[fieldData.name];
916
1020
  const targetTable = relEntry ? selectionCtx.tables[relEntry.targetTableName] : void 0;
917
1021
  if (!relEntry || !targetTable) {
918
1022
  continue;
@@ -934,7 +1038,7 @@ var extractSelectedColumnsFromTree = (tree, table, selectionCtx) => {
934
1038
  }
935
1039
  selectedColumns.push([fieldData.name, true]);
936
1040
  }
937
- for (const columnName of relationAggregateJoinColumns(tree, table, selectionCtx)) {
1041
+ for (const columnName of relationJoinColumns(tree, table, selectionCtx)) {
938
1042
  selectedColumns.push([columnName, true]);
939
1043
  }
940
1044
  if (!selectedColumns.length) {
@@ -954,7 +1058,7 @@ var extractSelectedColumnsFromTreeSQLFormat = (tree, table, selectionCtx) => {
954
1058
  }
955
1059
  selectedColumns.push([fieldData.name, tableColumns[fieldData.name]]);
956
1060
  }
957
- for (const columnName of relationAggregateJoinColumns(tree, table, selectionCtx)) {
1061
+ for (const columnName of relationJoinColumns(tree, table, selectionCtx)) {
958
1062
  selectedColumns.push([columnName, tableColumns[columnName]]);
959
1063
  }
960
1064
  if (!selectedColumns.length) {
@@ -1075,44 +1179,69 @@ var jsonFilterFields = (column, colType) => {
1075
1179
  isNotNull: { type: GraphQLBoolean2 }
1076
1180
  };
1077
1181
  };
1078
- var arrayFilterFields = (colType, colArr, colDesc) => {
1182
+ var IN_ARRAY_DESCRIPTION = "Matches any one of these values (SQL `IN`)";
1183
+ var NOT_IN_ARRAY_DESCRIPTION = "Matches none of these values (SQL `NOT IN`)";
1184
+ var arrayFilterFields = (colType, colArr) => {
1079
1185
  let element = colType.ofType;
1080
1186
  if (element instanceof GraphQLNonNull2) {
1081
1187
  element = element.ofType;
1082
1188
  }
1083
1189
  const elementList = new GraphQLList2(new GraphQLNonNull2(element));
1084
1190
  return {
1085
- eq: { type: colType, description: colDesc },
1086
- ne: { type: colType, description: colDesc },
1191
+ eq: { type: colType, description: "The whole array equals this array" },
1192
+ ne: { type: colType, description: "The whole array differs from this array" },
1087
1193
  has: { type: element, description: "Array contains this element" },
1088
1194
  hasSome: { type: elementList, description: "Array contains at least one of these elements (overlap, `&&`)" },
1089
1195
  hasEvery: { type: elementList, description: "Array contains every one of these elements (containment, `@>`)" },
1090
1196
  isEmpty: { type: GraphQLBoolean2, description: "When true, matches arrays with no elements" },
1091
- inArray: { type: colArr, description: `Array<${colDesc}>` },
1092
- notInArray: { type: colArr, description: `Array<${colDesc}>` },
1197
+ inArray: { type: colArr, description: IN_ARRAY_DESCRIPTION },
1198
+ notInArray: { type: colArr, description: NOT_IN_ARRAY_DESCRIPTION },
1093
1199
  isNull: { type: GraphQLBoolean2 },
1094
1200
  isNotNull: { type: GraphQLBoolean2 }
1095
1201
  };
1096
1202
  };
1097
1203
  var FILTERS_WITHOUT_STRING_OPS = /* @__PURE__ */ new Set(["Id", "Int", "Float", "BigInt", "Decimal"]);
1204
+ var BUILTIN_FILTER_SCALARS = /* @__PURE__ */ new Set([
1205
+ GraphQLString2,
1206
+ GraphQLInt2,
1207
+ GraphQLFloat2,
1208
+ GraphQLBoolean2,
1209
+ GraphQLBigIntString,
1210
+ GraphQLDecimalString,
1211
+ GraphQLUUID,
1212
+ GraphQLJSON,
1213
+ GraphQLDate,
1214
+ GraphQLDateTime
1215
+ ]);
1216
+ var resolveOverrideFilterDescriptor = (scalar) => {
1217
+ if (scalar === GraphQLJSON) {
1218
+ return { name: "JSON", kind: "json" };
1219
+ }
1220
+ if (scalar === GraphQLUUID) {
1221
+ return { name: "Id", kind: "scalar" };
1222
+ }
1223
+ return { name: scalar.name, kind: "scalar" };
1224
+ };
1098
1225
  var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
1099
1226
  const columnGraphQLType = drizzleColumnToGraphQLType(column, columnName, tableName, true, false, true);
1100
- const { name: genericName, kind } = resolveGenericFilterDescriptor(column, columnGraphQLType);
1227
+ const inputOverride = getColumnScalarOverride(column, true);
1228
+ const { name: genericName, kind } = inputOverride ? resolveOverrideFilterDescriptor(inputOverride) : resolveGenericFilterDescriptor(column, columnGraphQLType);
1101
1229
  const cached = cacheCtx.genericFilterCache.get(genericName);
1102
1230
  if (cached) {
1103
1231
  return cached;
1104
1232
  }
1105
1233
  const colType = columnGraphQLType.type;
1106
- const colDesc = columnGraphQLType.description;
1107
1234
  const colArr = new GraphQLList2(new GraphQLNonNull2(colType));
1108
- const omitStringOps = FILTERS_WITHOUT_STRING_OPS.has(genericName);
1109
- const baseFields = kind === "json" ? jsonFilterFields(column, colType) : kind === "array" ? arrayFilterFields(colType, colArr, colDesc) : {
1110
- eq: { type: colType, description: colDesc },
1111
- ne: { type: colType, description: colDesc },
1112
- lt: { type: colType, description: colDesc },
1113
- lte: { type: colType, description: colDesc },
1114
- gt: { type: colType, description: colDesc },
1115
- gte: { type: colType, description: colDesc },
1235
+ const customOverrideFilter = inputOverride !== void 0 && !BUILTIN_FILTER_SCALARS.has(inputOverride);
1236
+ const underlying = extractExtendedColumnType2(column);
1237
+ const omitStringOps = customOverrideFilter ? underlying.type !== "string" || underlying.constraint === "numeric" : FILTERS_WITHOUT_STRING_OPS.has(genericName);
1238
+ const baseFields = kind === "json" ? jsonFilterFields(column, colType) : kind === "array" ? arrayFilterFields(colType, colArr) : {
1239
+ eq: { type: colType, description: "Equal to" },
1240
+ ne: { type: colType, description: "Not equal to" },
1241
+ lt: { type: colType, description: "Less than" },
1242
+ lte: { type: colType, description: "Less than or equal to" },
1243
+ gt: { type: colType, description: "Greater than" },
1244
+ gte: { type: colType, description: "Greater than or equal to" },
1116
1245
  ...omitStringOps ? {} : {
1117
1246
  like: { type: GraphQLString2 },
1118
1247
  notLike: { type: GraphQLString2 },
@@ -1143,10 +1272,10 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
1143
1272
  description: "Case-insensitive `contains`."
1144
1273
  }
1145
1274
  },
1146
- inArray: { type: colArr, description: `Array<${colDesc}>` },
1147
- notInArray: { type: colArr, description: `Array<${colDesc}>` },
1148
- isNull: { type: GraphQLBoolean2 },
1149
- isNotNull: { type: GraphQLBoolean2 }
1275
+ inArray: { type: colArr, description: IN_ARRAY_DESCRIPTION },
1276
+ notInArray: { type: colArr, description: NOT_IN_ARRAY_DESCRIPTION },
1277
+ isNull: { type: GraphQLBoolean2, description: "When true, matches rows where the column is NULL" },
1278
+ isNotNull: { type: GraphQLBoolean2, description: "When true, matches rows where the column is not NULL" }
1150
1279
  };
1151
1280
  const mainType = new GraphQLInputObjectType2({
1152
1281
  name: `${genericName}Filter`,
@@ -1186,35 +1315,40 @@ var generateTableOrderCached = (table) => {
1186
1315
  }
1187
1316
  return remapped;
1188
1317
  };
1189
- var filterMap = /* @__PURE__ */ new WeakMap();
1190
1318
  var generateTableFilterValuesCached = (table, tableName, cacheCtx) => {
1191
- if (filterMap.has(table)) {
1192
- return filterMap.get(table);
1319
+ if (cacheCtx.filterFieldCache.has(table)) {
1320
+ return cacheCtx.filterFieldCache.get(table);
1193
1321
  }
1194
1322
  const columns = getColumns(table);
1195
1323
  const columnEntries = Object.entries(columns);
1196
1324
  const remapped = Object.fromEntries(
1197
- columnEntries.map(([columnName, columnDescription]) => [
1325
+ columnEntries.map(([columnName, column]) => [
1198
1326
  columnName,
1199
1327
  {
1200
- type: generateColumnFilterValues(columnDescription, tableName, columnName, cacheCtx)
1328
+ type: generateColumnFilterValues(column, tableName, columnName, cacheCtx),
1329
+ // A filter field is the same column, so it carries the same documentation. Deprecation
1330
+ // is not propagated: filtering on a deprecated column is how a caller finds the rows
1331
+ // that still use it.
1332
+ ...cacheCtx.docs.describeColumn ? { description: cacheCtx.docs.describeColumn(column, { tableName, columnName }) } : {}
1201
1333
  }
1202
1334
  ])
1203
1335
  );
1204
- filterMap.set(table, remapped);
1336
+ cacheCtx.filterFieldCache.set(table, remapped);
1205
1337
  return remapped;
1206
1338
  };
1207
- var fieldMap = /* @__PURE__ */ new WeakMap();
1208
- var generateTableSelectTypeFieldsCached = (table, tableName) => {
1209
- if (fieldMap.has(table)) {
1210
- return fieldMap.get(table);
1339
+ var generateTableSelectTypeFieldsCached = (table, tableName, cacheCtx) => {
1340
+ if (cacheCtx.selectFieldCache.has(table)) {
1341
+ return cacheCtx.selectFieldCache.get(table);
1211
1342
  }
1212
1343
  const columns = getColumns(table);
1213
1344
  const columnEntries = Object.entries(columns);
1214
1345
  const remapped = Object.fromEntries(
1215
- columnEntries.map(([columnName, columnDescription]) => [
1346
+ columnEntries.map(([columnName, column]) => [
1216
1347
  columnName,
1217
- drizzleColumnToGraphQLType(columnDescription, columnName, tableName)
1348
+ {
1349
+ ...drizzleColumnToGraphQLType(column, columnName, tableName),
1350
+ ...columnDocs(cacheCtx.docs, column, tableName, columnName)
1351
+ }
1218
1352
  ])
1219
1353
  );
1220
1354
  if (!remapped[CURSOR_FIELD_NAME]) {
@@ -1224,7 +1358,7 @@ var generateTableSelectTypeFieldsCached = (table, tableName) => {
1224
1358
  resolve: rowCursorResolver
1225
1359
  };
1226
1360
  }
1227
- fieldMap.set(table, remapped);
1361
+ cacheCtx.selectFieldCache.set(table, remapped);
1228
1362
  return remapped;
1229
1363
  };
1230
1364
  var isFilterableRelation = (relation) => !relation.through;
@@ -1374,7 +1508,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1374
1508
  const table = tables[tableName];
1375
1509
  const order = withOrder ? generateTableOrderTypeCached(table, tableName, typeNameMapper, cacheCtx, relationMap, tables) : void 0;
1376
1510
  const filters = generateTableFilterTypeCached(table, tableName, cacheCtx, typeNameMapper, relationMap, tables);
1377
- const tableFields = generateTableSelectTypeFieldsCached(table, tableName);
1511
+ const tableFields = generateTableSelectTypeFieldsCached(table, tableName, cacheCtx);
1378
1512
  const relationsForTable = relationMap[tableName];
1379
1513
  const relationEntries = relationsForTable ? Object.entries(relationsForTable) : [];
1380
1514
  if (relationsDepthLimit !== void 0 && currentDepth >= relationsDepthLimit) {
@@ -1411,6 +1545,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1411
1545
  const typeName = resolveTypeName(tableName, typeNameMapper);
1412
1546
  const shell = new GraphQLObjectType2({
1413
1547
  name: typeName,
1548
+ description: cacheCtx.docs.describeTable?.(tableName),
1414
1549
  fields: () => ({ ...tableFields, ...container.fields })
1415
1550
  });
1416
1551
  cacheCtx.objectTypeCache.set(tableName, shell);
@@ -1443,7 +1578,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1443
1578
  let relType = cacheCtx.objectTypeCache.get(targetTableName);
1444
1579
  if (!relType) {
1445
1580
  const targetTable = tables[targetTableName];
1446
- const targetTableFields = generateTableSelectTypeFieldsCached(targetTable, targetTableName);
1581
+ const targetTableFields = generateTableSelectTypeFieldsCached(targetTable, targetTableName, cacheCtx);
1447
1582
  let targetContainer = cacheCtx.relationFieldContainers.get(targetTableName);
1448
1583
  if (!targetContainer) {
1449
1584
  targetContainer = { fields: {} };
@@ -1452,11 +1587,14 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1452
1587
  const capturedTargetContainer = targetContainer;
1453
1588
  relType = new GraphQLObjectType2({
1454
1589
  name: resolveTypeName(targetTableName, typeNameMapper),
1590
+ description: cacheCtx.docs.describeTable?.(targetTableName),
1455
1591
  fields: () => ({ ...targetTableFields, ...capturedTargetContainer.fields })
1456
1592
  });
1457
1593
  cacheCtx.objectTypeCache.set(targetTableName, relType);
1458
1594
  }
1459
1595
  const resolve = resolverFactory?.({ tableName, relationName, relEntry, isOne });
1596
+ const relationDescription = cacheCtx.docs.describeRelation?.(tableName, relationName);
1597
+ const relationDocs = relationDescription !== void 0 ? { description: relationDescription } : {};
1460
1598
  if (isOne) {
1461
1599
  const isRequired = relation.optional === false;
1462
1600
  rawRelationFields.push([
@@ -1466,7 +1604,8 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1466
1604
  args: {
1467
1605
  where: { type: relSelectData.filters }
1468
1606
  },
1469
- resolve
1607
+ resolve,
1608
+ ...relationDocs
1470
1609
  }
1471
1610
  ]);
1472
1611
  continue;
@@ -1482,6 +1621,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1482
1621
  limit: { type: GraphQLInt2 }
1483
1622
  },
1484
1623
  resolve,
1624
+ ...relationDocs,
1485
1625
  ...cacheCtx.complexity ? { extensions: { complexity: listFieldComplexity(cacheCtx.complexity) } } : {}
1486
1626
  }
1487
1627
  ]);
@@ -1529,7 +1669,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1529
1669
  relationFields: {}
1530
1670
  };
1531
1671
  };
1532
- var generateTableTypes = (tableName, tables, relationMap, withReturning, relationsDepthLimit, cacheCtx, typeNameMapper = void 0, insertPrefix = "create", updatePrefix = "update", resolverFactory, relationAggregateFactory) => {
1672
+ var generateTableTypes = (tableName, tables, relationMap, withReturning, relationsDepthLimit, cacheCtx, typeNameMapper = void 0, insertPrefix = "create", updatePrefix = "update", resolverFactory, relationAggregateFactory, nestedWrites) => {
1533
1673
  const { tableFields, relationFields, filters, order } = generateSelectFields(
1534
1674
  tables,
1535
1675
  tableName,
@@ -1550,28 +1690,44 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
1550
1690
  const table = tables[tableName];
1551
1691
  const columns = getColumns(table);
1552
1692
  const columnEntries = Object.entries(columns);
1693
+ const relaxedColumns = nestedWrites?.relaxedColumns(tableName);
1553
1694
  const insertFields = Object.fromEntries(
1554
- columnEntries.map(([columnName, columnDescription]) => [
1555
- columnName,
1556
- drizzleColumnToGraphQLType(columnDescription, columnName, tableName, false, true, true)
1557
- ])
1695
+ columnEntries.map(([columnName, column]) => {
1696
+ const converted = drizzleColumnToGraphQLType(
1697
+ column,
1698
+ columnName,
1699
+ tableName,
1700
+ !!relaxedColumns?.has(columnName),
1701
+ true,
1702
+ true
1703
+ );
1704
+ return [
1705
+ columnName,
1706
+ { ...converted, ...inputFieldDocs(cacheCtx.docs, column, tableName, columnName, converted.type) }
1707
+ ];
1708
+ })
1558
1709
  );
1559
1710
  const updateFields = Object.fromEntries(
1560
- columnEntries.map(([columnName, columnDescription]) => [
1561
- columnName,
1562
- drizzleColumnToGraphQLType(columnDescription, columnName, tableName, true, false, true)
1563
- ])
1711
+ columnEntries.map(([columnName, column]) => {
1712
+ const converted = drizzleColumnToGraphQLType(column, columnName, tableName, true, false, true);
1713
+ return [
1714
+ columnName,
1715
+ { ...converted, ...inputFieldDocs(cacheCtx.docs, column, tableName, columnName, converted.type) }
1716
+ ];
1717
+ })
1564
1718
  );
1719
+ const typeName = resolveTypeName(tableName, typeNameMapper);
1565
1720
  const insertInput = new GraphQLInputObjectType2({
1566
- name: `${capitalize(insertPrefix)}${resolveTypeName(tableName, typeNameMapper)}Input`,
1567
- fields: insertFields
1721
+ name: `${capitalize(insertPrefix)}${typeName}Input`,
1722
+ fields: nestedWrites ? () => ({ ...insertFields, ...nestedWrites.createFields(tableName, typeName) }) : insertFields
1568
1723
  });
1569
1724
  const updateInput = new GraphQLInputObjectType2({
1570
- name: `${capitalize(updatePrefix)}${resolveTypeName(tableName, typeNameMapper)}Input`,
1571
- fields: updateFields
1725
+ name: `${capitalize(updatePrefix)}${typeName}Input`,
1726
+ fields: nestedWrites ? () => ({ ...updateFields, ...nestedWrites.updateFields(tableName, typeName) }) : updateFields
1572
1727
  });
1573
1728
  const selectSingleOutput = cacheCtx.objectTypeCache.get(tableName) ?? new GraphQLObjectType2({
1574
1729
  name: resolveTypeName(tableName, typeNameMapper),
1730
+ description: cacheCtx.docs.describeTable?.(tableName),
1575
1731
  fields: { ...tableFields, ...relationFields }
1576
1732
  });
1577
1733
  const selectArrOutput = new GraphQLNonNull2(new GraphQLList2(new GraphQLNonNull2(selectSingleOutput)));
@@ -1963,6 +2119,13 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
1963
2119
  if (!field) {
1964
2120
  continue;
1965
2121
  }
2122
+ const selectionCount = Object.values(baseField).reduce(
2123
+ (n, f) => n + (f.name === relName ? 1 : 0),
2124
+ 0
2125
+ );
2126
+ if (selectionCount > 1) {
2127
+ continue;
2128
+ }
1966
2129
  const relField = field?.fieldsByTypeName;
1967
2130
  const relFieldSelection = relField?.[relTypeName];
1968
2131
  if (!relFieldSelection) {
@@ -1971,7 +2134,8 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
1971
2134
  const columns = extractSelectedColumnsFromTree(relFieldSelection, tables[targetTableName], {
1972
2135
  tableName: targetTableName,
1973
2136
  relationMap,
1974
- tables
2137
+ tables,
2138
+ allRelations: filterCtx?.relationMap
1975
2139
  });
1976
2140
  const thisRecord = {};
1977
2141
  thisRecord.columns = columns;
@@ -2577,7 +2741,8 @@ var runRelationalSelect = async (opts) => {
2577
2741
  columns: extractSelectedColumnsFromTree(parsedInfo.fieldsByTypeName[typeName], table, {
2578
2742
  tableName,
2579
2743
  relationMap,
2580
- tables
2744
+ tables,
2745
+ allRelations: filterCtx?.relationMap
2581
2746
  }),
2582
2747
  offset: distinctKeys ? void 0 : offset,
2583
2748
  // drizzle-orm v1 RQB calls orderBy/where with the aliased table proxy — use it
@@ -2706,7 +2871,7 @@ import {
2706
2871
  count,
2707
2872
  countDistinct,
2708
2873
  eq as eq2,
2709
- extractExtendedColumnType as extractExtendedColumnType2,
2874
+ extractExtendedColumnType as extractExtendedColumnType3,
2710
2875
  getColumns as getColumns2,
2711
2876
  gt as gt2,
2712
2877
  gte as gte2,
@@ -2750,7 +2915,7 @@ var classifyAggregateColumns = (table, tableName) => {
2750
2915
  if (gqlType instanceof GraphQLList3 || gqlType instanceof GraphQLObjectType3) {
2751
2916
  continue;
2752
2917
  }
2753
- const { type: dataType, constraint } = extractExtendedColumnType2(column);
2918
+ const { type: dataType, constraint } = extractExtendedColumnType3(column);
2754
2919
  if (dataType === "boolean" || dataType === "array" || dataType === "custom") {
2755
2920
  continue;
2756
2921
  }
@@ -2789,9 +2954,9 @@ var generateAggregateTypes = (table, tableName, typeName, cacheCtx) => {
2789
2954
  type: new GraphQLObjectType3({
2790
2955
  name: `${typeName}${capitalize(op)}Aggregate`,
2791
2956
  fields: Object.fromEntries(
2792
- Object.entries(orderable).map(([columnName, { converted }]) => [
2957
+ Object.entries(orderable).map(([columnName, { column, converted }]) => [
2793
2958
  columnName,
2794
- { type: converted.type, description: converted.description }
2959
+ { type: converted.type, ...columnDocs(cacheCtx?.docs ?? {}, column, tableName, columnName) }
2795
2960
  ])
2796
2961
  )
2797
2962
  })
@@ -2838,7 +3003,7 @@ var aggregateTarget = (table, tableName, typeName) => {
2838
3003
  typeName,
2839
3004
  columns: getColumns2(table),
2840
3005
  dateTimeColumns: new Set(
2841
- Object.entries(orderable).filter(([, { converted }]) => converted.description === "DateTime").map(([columnName]) => columnName)
3006
+ Object.entries(orderable).filter(([, { converted }]) => converted.typeLabel === "DateTime").map(([columnName]) => columnName)
2842
3007
  )
2843
3008
  };
2844
3009
  };
@@ -2991,7 +3156,7 @@ var groupableColumns = (table, tableName) => {
2991
3156
  if (groupable[columnName]) {
2992
3157
  continue;
2993
3158
  }
2994
- const { type: dataType } = extractExtendedColumnType2(column);
3159
+ const { type: dataType } = extractExtendedColumnType3(column);
2995
3160
  if (dataType !== "boolean") {
2996
3161
  continue;
2997
3162
  }
@@ -3056,9 +3221,9 @@ var generateGroupByType = (table, tableName, typeName, cacheCtx) => {
3056
3221
  name: `${typeName}GroupKeys`,
3057
3222
  description: `The grouped column values of one ${typeName} group. A column the query did not group by is null.`,
3058
3223
  fields: Object.fromEntries(
3059
- Object.entries(groupable).map(([columnName, { converted }]) => [
3224
+ Object.entries(groupable).map(([columnName, { column, converted }]) => [
3060
3225
  columnName,
3061
- { type: converted.type, description: converted.description }
3226
+ { type: converted.type, ...columnDocs(cacheCtx?.docs ?? {}, column, tableName, columnName) }
3062
3227
  ])
3063
3228
  )
3064
3229
  });
@@ -3458,6 +3623,13 @@ var generateSchemaData = (db, schema, relations, options) => {
3458
3623
  "Drizzle-GraphQL Error: No tables detected in Drizzle-ORM's database instance. Did you forget to pass schema to drizzle constructor?"
3459
3624
  );
3460
3625
  }
3626
+ if (features.nestedWrites) {
3627
+ throw new Error(
3628
+ "Drizzle-GraphQL Error: features.nestedWrites is not supported on MySQL \u2014 a nested write needs the parent row it just inserted returned to it, and MySQL has no RETURNING clause."
3629
+ );
3630
+ }
3631
+ registerScalarOverrides(tables, options);
3632
+ registerEnumConfig(options);
3461
3633
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
3462
3634
  attachTargetPrimaryKeys(namedRelations, tables, mysqlPrimaryKeyPropNames);
3463
3635
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
@@ -3469,11 +3641,14 @@ var generateSchemaData = (db, schema, relations, options) => {
3469
3641
  relationFieldContainers: /* @__PURE__ */ new Map(),
3470
3642
  fullyBuiltTables: /* @__PURE__ */ new Set(),
3471
3643
  relationTypeCache: /* @__PURE__ */ new Map(),
3644
+ selectFieldCache: /* @__PURE__ */ new WeakMap(),
3645
+ filterFieldCache: /* @__PURE__ */ new WeakMap(),
3472
3646
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
3473
3647
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
3474
3648
  listRelationFilterCache: /* @__PURE__ */ new Map(),
3475
3649
  aggregateTypeCache: /* @__PURE__ */ new Map(),
3476
- complexity
3650
+ complexity,
3651
+ docs: options.docs ?? {}
3477
3652
  };
3478
3653
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
3479
3654
  const queries = {};
@@ -3721,58 +3896,443 @@ var generateSchemaData = (db, schema, relations, options) => {
3721
3896
  };
3722
3897
  }
3723
3898
  }
3724
- const activeInputs = [
3725
- // The insert input types the upsert mutations too, so either feature keeps it.
3726
- ...features.insert || onConflictInput ? [insertInput] : [],
3727
- ...onConflictInput ? [onConflictInput] : [],
3728
- ...features.update ? [updateInput] : [],
3729
- ...updateManyInput ? [updateManyInput] : [],
3730
- tableFilters,
3731
- tableOrder
3732
- ];
3733
- activeInputs.forEach((e) => {
3734
- inputs[e.name] = e;
3899
+ const activeInputs = [
3900
+ // The insert input types the upsert mutations too, so either feature keeps it.
3901
+ ...features.insert || onConflictInput ? [insertInput] : [],
3902
+ ...onConflictInput ? [onConflictInput] : [],
3903
+ ...features.update ? [updateInput] : [],
3904
+ ...updateManyInput ? [updateManyInput] : [],
3905
+ tableFilters,
3906
+ tableOrder
3907
+ ];
3908
+ activeInputs.forEach((e) => {
3909
+ inputs[e.name] = e;
3910
+ });
3911
+ outputs[selectSingleOutput.name] = selectSingleOutput;
3912
+ if (aggregateType) {
3913
+ outputs[aggregateType.name] = aggregateType;
3914
+ }
3915
+ if (groupByType && havingInput) {
3916
+ outputs[groupByType.name] = groupByType;
3917
+ inputs[havingInput.name] = havingInput;
3918
+ }
3919
+ }
3920
+ if (mutationTxCtx) {
3921
+ for (const name of Object.keys(mutations)) {
3922
+ mutationTxCtx.fieldNames.add(name);
3923
+ }
3924
+ }
3925
+ const fieldResolvers = {};
3926
+ for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
3927
+ const relResolvers = {};
3928
+ for (const [relName, relEntry] of Object.entries(tableRelations)) {
3929
+ const isOne = is4(relEntry.relation ?? relEntry, One3);
3930
+ const resolver = resolverFactory({ tableName, relationName: relName, relEntry, isOne });
3931
+ if (resolver) {
3932
+ relResolvers[relName] = resolver;
3933
+ }
3934
+ }
3935
+ if (Object.keys(relResolvers).length > 0) {
3936
+ fieldResolvers[tableName] = relResolvers;
3937
+ }
3938
+ }
3939
+ return { queries, mutations, inputs, types: outputs, fieldResolvers };
3940
+ };
3941
+
3942
+ // src/util/builders/pg.ts
3943
+ import { and as and4, getColumns as getColumns4, is as is6, One as One5 } from "drizzle-orm";
3944
+ import { getTableConfig as getTableConfig2, PgTable } from "drizzle-orm/pg-core";
3945
+ import {
3946
+ GraphQLError as GraphQLError7,
3947
+ GraphQLList as GraphQLList6,
3948
+ GraphQLNonNull as GraphQLNonNull6
3949
+ } from "graphql";
3950
+ import { parseResolveInfo as parseResolveInfo3 } from "graphql-parse-resolve-info";
3951
+
3952
+ // src/util/builders/nested-writes.ts
3953
+ import { and as and3, eq as eq3, getColumns as getColumns3, is as is5, One as One4 } from "drizzle-orm";
3954
+ import {
3955
+ GraphQLBoolean as GraphQLBoolean4,
3956
+ GraphQLError as GraphQLError6,
3957
+ GraphQLInputObjectType as GraphQLInputObjectType4,
3958
+ GraphQLList as GraphQLList5,
3959
+ GraphQLNonNull as GraphQLNonNull5
3960
+ } from "graphql";
3961
+ var isOptionalOnInsert = (column) => !column.notNull || !!column.hasDefault || !!column.defaultFn;
3962
+ var buildNestedWritePlans = (tables, relationMap, resolveUniqueSets, resolvePrimaryKeys, extractJoinColumns) => {
3963
+ const uniqueCache = /* @__PURE__ */ new Map();
3964
+ const singleColumnUniques = (tableName, table) => {
3965
+ let cached = uniqueCache.get(tableName);
3966
+ if (!cached) {
3967
+ cached = new Set(
3968
+ resolveUniqueSets(table).filter((set) => set.length === 1).map((set) => set[0])
3969
+ );
3970
+ uniqueCache.set(tableName, cached);
3971
+ }
3972
+ return cached;
3973
+ };
3974
+ const pkCache = /* @__PURE__ */ new Map();
3975
+ const singleColumnPk = (tableName, table) => {
3976
+ if (!pkCache.has(tableName)) {
3977
+ const pk = resolvePrimaryKeys(table);
3978
+ pkCache.set(tableName, pk.length === 1 ? pk[0] : void 0);
3979
+ }
3980
+ return pkCache.get(tableName);
3981
+ };
3982
+ const plans = {};
3983
+ for (const [tableName, relations] of Object.entries(relationMap)) {
3984
+ const table = tables[tableName];
3985
+ if (!table) {
3986
+ continue;
3987
+ }
3988
+ const tablePlans = {};
3989
+ for (const [relationName, relEntry] of Object.entries(relations)) {
3990
+ const relation = relEntry.relation;
3991
+ if (relation.through) {
3992
+ continue;
3993
+ }
3994
+ const targetTableName = relEntry.targetTableName;
3995
+ const targetTable = tables[targetTableName];
3996
+ if (!targetTable) {
3997
+ continue;
3998
+ }
3999
+ const joinColumns = extractJoinColumns(relEntry, table, targetTable);
4000
+ if (!joinColumns) {
4001
+ continue;
4002
+ }
4003
+ const { localColPropName, foreignCol, foreignColPropName } = joinColumns;
4004
+ const localCol = getColumns3(table)[localColPropName];
4005
+ if (!localCol) {
4006
+ continue;
4007
+ }
4008
+ const isOne = is5(relation, One4);
4009
+ const localIsPk = singleColumnPk(tableName, table) === localColPropName;
4010
+ const foreignIsPk = singleColumnPk(targetTableName, targetTable) === foreignColPropName;
4011
+ const localIsUnique = singleColumnUniques(tableName, table).has(localColPropName);
4012
+ const foreignIsUnique = singleColumnUniques(targetTableName, targetTable).has(foreignColPropName);
4013
+ let fkSide;
4014
+ if (!isOne) {
4015
+ fkSide = "child";
4016
+ } else if (foreignIsPk && !localIsPk) {
4017
+ fkSide = "parent";
4018
+ } else if (localIsPk) {
4019
+ fkSide = "child";
4020
+ } else if (foreignIsUnique) {
4021
+ fkSide = "parent";
4022
+ } else if (localIsUnique) {
4023
+ fkSide = "child";
4024
+ } else {
4025
+ continue;
4026
+ }
4027
+ const fkColumn = fkSide === "child" ? foreignCol : localCol;
4028
+ tablePlans[relationName] = {
4029
+ relationName,
4030
+ targetTableName,
4031
+ targetTable,
4032
+ localColPropName,
4033
+ foreignColPropName,
4034
+ foreignCol,
4035
+ localCol,
4036
+ isOne,
4037
+ fkSide,
4038
+ canDetach: !fkColumn.notNull
4039
+ };
4040
+ }
4041
+ if (Object.keys(tablePlans).length) {
4042
+ plans[tableName] = tablePlans;
4043
+ }
4044
+ }
4045
+ return plans;
4046
+ };
4047
+ var NO_COLUMNS = /* @__PURE__ */ new Set();
4048
+ var createNestedWriteTypes = (params) => {
4049
+ const { plans, cacheCtx, typeNameMapper, insertPrefix } = params;
4050
+ const wrapperCache = /* @__PURE__ */ new Map();
4051
+ const payloadCache = /* @__PURE__ */ new Map();
4052
+ const payloadType = (tableName, typeName, plan) => {
4053
+ const key = `${tableName}.${plan.relationName}`;
4054
+ const cached = payloadCache.get(key);
4055
+ if (cached) {
4056
+ return cached;
4057
+ }
4058
+ const omitted = plan.fkSide === "child" ? plan.foreignColPropName : void 0;
4059
+ const fields = Object.fromEntries(
4060
+ Object.entries(getColumns3(plan.targetTable)).filter(([columnName]) => columnName !== omitted).map(([columnName, column]) => [
4061
+ columnName,
4062
+ drizzleColumnToGraphQLType(column, columnName, plan.targetTableName, false, true, true)
4063
+ ])
4064
+ );
4065
+ const type = new GraphQLInputObjectType4({
4066
+ name: `${capitalize(insertPrefix)}${typeName}${capitalize(plan.relationName)}Input`,
4067
+ description: omitted === void 0 ? `A new ${resolveTypeName(plan.targetTableName, typeNameMapper)} row for ${typeName}.${plan.relationName}` : `A new ${resolveTypeName(plan.targetTableName, typeNameMapper)} row for ${typeName}.${plan.relationName}. \`${omitted}\` is set from the ${typeName} row this is written with.`,
4068
+ fields
4069
+ });
4070
+ payloadCache.set(key, type);
4071
+ return type;
4072
+ };
4073
+ const targetFilters = (plan) => cacheCtx.filterTypeCache.get(plan.targetTable);
4074
+ const listOf = (type) => new GraphQLList5(new GraphQLNonNull5(type));
4075
+ const wrapperType = (tableName, typeName, plan, forUpdate) => {
4076
+ const key = `${tableName}.${plan.relationName}.${forUpdate ? "update" : "create"}`;
4077
+ const cached = wrapperCache.get(key);
4078
+ if (cached) {
4079
+ return cached;
4080
+ }
4081
+ const filters = targetFilters(plan);
4082
+ const payload = payloadType(tableName, typeName, plan);
4083
+ const targetTypeName = resolveTypeName(plan.targetTableName, typeNameMapper);
4084
+ const fields = {};
4085
+ if (plan.isOne) {
4086
+ fields["create"] = { type: payload, description: `Insert a ${targetTypeName} row and attach it` };
4087
+ if (filters) {
4088
+ fields["connect"] = {
4089
+ type: filters,
4090
+ description: `Attach the existing ${targetTypeName} row this matches. Must match exactly one row.`
4091
+ };
4092
+ }
4093
+ if (forUpdate && plan.canDetach) {
4094
+ fields["disconnect"] = {
4095
+ type: GraphQLBoolean4,
4096
+ description: `Detach the currently attached ${targetTypeName} row, leaving it in place`
4097
+ };
4098
+ }
4099
+ } else {
4100
+ fields["create"] = { type: listOf(payload), description: `Insert these ${targetTypeName} rows and attach them` };
4101
+ if (filters) {
4102
+ fields["connect"] = {
4103
+ type: listOf(filters),
4104
+ description: `Attach every existing ${targetTypeName} row these match`
4105
+ };
4106
+ if (forUpdate && plan.canDetach) {
4107
+ fields["disconnect"] = {
4108
+ type: listOf(filters),
4109
+ description: `Detach every attached ${targetTypeName} row these match, leaving the rows in place`
4110
+ };
4111
+ fields["set"] = {
4112
+ type: listOf(filters),
4113
+ description: `Replace the whole set: detach everything attached, then attach every ${targetTypeName} row these match. Applied before \`disconnect\`, \`connect\` and \`create\`.`
4114
+ };
4115
+ }
4116
+ }
4117
+ }
4118
+ const type = new GraphQLInputObjectType4({
4119
+ name: `${typeName}${capitalize(plan.relationName)}Nested${forUpdate ? "Update" : "Create"}Input`,
4120
+ description: `Writes through ${typeName}.${plan.relationName}`,
4121
+ fields
3735
4122
  });
3736
- outputs[selectSingleOutput.name] = selectSingleOutput;
3737
- if (aggregateType) {
3738
- outputs[aggregateType.name] = aggregateType;
4123
+ wrapperCache.set(key, type);
4124
+ return type;
4125
+ };
4126
+ const relationFields = (tableName, typeName, forUpdate) => {
4127
+ const tablePlans = plans[tableName];
4128
+ if (!tablePlans) {
4129
+ return {};
4130
+ }
4131
+ return Object.fromEntries(
4132
+ Object.values(tablePlans).flatMap((plan) => {
4133
+ const wrapper = wrapperType(tableName, typeName, plan, forUpdate);
4134
+ return wrapper ? [[plan.relationName, { type: wrapper, description: `Writes through ${typeName}.${plan.relationName}` }]] : [];
4135
+ })
4136
+ );
4137
+ };
4138
+ return {
4139
+ createFields: (tableName, typeName) => relationFields(tableName, typeName, false),
4140
+ updateFields: (tableName, typeName) => relationFields(tableName, typeName, true),
4141
+ relaxedColumns: (tableName) => {
4142
+ const tablePlans = plans[tableName];
4143
+ if (!tablePlans) {
4144
+ return NO_COLUMNS;
4145
+ }
4146
+ const relaxed = /* @__PURE__ */ new Set();
4147
+ for (const plan of Object.values(tablePlans)) {
4148
+ if (plan.fkSide === "parent" && !isOptionalOnInsert(plan.localCol)) {
4149
+ relaxed.add(plan.localColPropName);
4150
+ }
4151
+ }
4152
+ return relaxed.size ? relaxed : NO_COLUMNS;
3739
4153
  }
3740
- if (groupByType && havingInput) {
3741
- outputs[groupByType.name] = groupByType;
3742
- inputs[havingInput.name] = havingInput;
4154
+ };
4155
+ };
4156
+ var mergedOps = (entries) => Object.assign({}, ...entries.map((entry) => entry.ops));
4157
+ var asArray = (value) => Array.isArray(value) ? value : value === void 0 ? [] : [value];
4158
+ var createNestedWriteRuntime = (params) => {
4159
+ const { plans, filterCtx } = params;
4160
+ const conditionOf = (plan, filter, operation) => {
4161
+ const condition = extractFilters(
4162
+ plan.targetTable,
4163
+ plan.targetTableName,
4164
+ filter,
4165
+ relationFilterCtx(filterCtx, plan.targetTableName)
4166
+ );
4167
+ if (!condition) {
4168
+ throw new GraphQLError6(
4169
+ `Drizzle-GraphQL Error: '${operation}' on '${plan.relationName}' needs a filter that selects rows \u2014 it was given one that matches everything.`
4170
+ );
3743
4171
  }
3744
- }
3745
- if (mutationTxCtx) {
3746
- for (const name of Object.keys(mutations)) {
3747
- mutationTxCtx.fieldNames.add(name);
4172
+ return condition;
4173
+ };
4174
+ const assertSingleOperation = (plan, op) => {
4175
+ const supplied = ["create", "connect", "disconnect"].filter((key) => op[key] !== void 0 && op[key] !== null);
4176
+ if (supplied.length > 1) {
4177
+ throw new GraphQLError6(
4178
+ `Drizzle-GraphQL Error: '${plan.relationName}' takes one of ${supplied.join(", ")} at a time \u2014 it holds a single row.`
4179
+ );
3748
4180
  }
3749
- }
3750
- const fieldResolvers = {};
3751
- for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
3752
- const relResolvers = {};
3753
- for (const [relName, relEntry] of Object.entries(tableRelations)) {
3754
- const isOne = is4(relEntry.relation ?? relEntry, One3);
3755
- const resolver = resolverFactory({ tableName, relationName: relName, relEntry, isOne });
3756
- if (resolver) {
3757
- relResolvers[relName] = resolver;
4181
+ };
4182
+ const detachAll = async (executor, plan, key) => executor.update(plan.targetTable).set({ [plan.foreignColPropName]: null }).where(eq3(plan.foreignCol, key));
4183
+ return {
4184
+ enabled: (tableName) => !!plans[tableName],
4185
+ split: (tableName, values) => {
4186
+ const tablePlans = plans[tableName];
4187
+ if (!tablePlans) {
4188
+ return { columns: values, ops: {} };
4189
+ }
4190
+ const columns = {};
4191
+ const ops = {};
4192
+ for (const [key, value] of Object.entries(values)) {
4193
+ if (tablePlans[key] && value !== void 0 && value !== null) {
4194
+ ops[key] = value;
4195
+ } else if (!tablePlans[key]) {
4196
+ columns[key] = value;
4197
+ }
4198
+ }
4199
+ return { columns, ops };
4200
+ },
4201
+ hasOps: (ops) => Object.keys(ops).length > 0,
4202
+ withJoinColumns: (tableName, ops, columns, table) => {
4203
+ const tablePlans = plans[tableName];
4204
+ if (!tablePlans) {
4205
+ return columns;
4206
+ }
4207
+ const allColumns = getColumns3(table);
4208
+ for (const relationName of Object.keys(ops)) {
4209
+ const plan = tablePlans[relationName];
4210
+ if (plan?.fkSide === "child" && !(plan.localColPropName in columns) && allColumns[plan.localColPropName]) {
4211
+ columns[plan.localColPropName] = allColumns[plan.localColPropName];
4212
+ }
4213
+ }
4214
+ return columns;
4215
+ },
4216
+ applyParentSide: async (executor, tableName, ops) => {
4217
+ const tablePlans = plans[tableName];
4218
+ const patch = {};
4219
+ if (!tablePlans) {
4220
+ return patch;
4221
+ }
4222
+ for (const [relationName, op] of Object.entries(ops)) {
4223
+ const plan = tablePlans[relationName];
4224
+ if (!plan || plan.fkSide !== "parent") {
4225
+ continue;
4226
+ }
4227
+ assertSingleOperation(plan, op);
4228
+ if (op["create"] !== void 0) {
4229
+ const values = remapFromGraphQLSingleInput({ ...op["create"] }, plan.targetTable);
4230
+ const inserted = await executor.insert(plan.targetTable).values(values).returning();
4231
+ const created = inserted[0];
4232
+ if (!created) {
4233
+ throw new GraphQLError6(
4234
+ `Drizzle-GraphQL Error: 'create' on '${relationName}' inserted no row, so there is nothing to attach.`
4235
+ );
4236
+ }
4237
+ patch[plan.localColPropName] = created[plan.foreignColPropName];
4238
+ } else if (op["connect"] !== void 0) {
4239
+ const rows = await executor.select().from(plan.targetTable).where(conditionOf(plan, op["connect"], "connect"));
4240
+ if (rows.length !== 1) {
4241
+ throw new GraphQLError6(
4242
+ `Drizzle-GraphQL Error: 'connect' on '${relationName}' matched ${rows.length} rows \u2014 it attaches a single row, so its filter must match exactly one.`
4243
+ );
4244
+ }
4245
+ patch[plan.localColPropName] = rows[0][plan.foreignColPropName];
4246
+ } else if (op["disconnect"] === true) {
4247
+ patch[plan.localColPropName] = null;
4248
+ }
4249
+ }
4250
+ return patch;
4251
+ },
4252
+ applyChildSide: async (executor, tableName, ops, parentRows) => {
4253
+ const tablePlans = plans[tableName];
4254
+ if (!tablePlans) {
4255
+ return;
4256
+ }
4257
+ for (const [relationName, op] of Object.entries(ops)) {
4258
+ const plan = tablePlans[relationName];
4259
+ if (!plan || plan.fkSide !== "child") {
4260
+ continue;
4261
+ }
4262
+ if (plan.isOne) {
4263
+ assertSingleOperation(plan, op);
4264
+ }
4265
+ for (const parentRow of parentRows) {
4266
+ const key = parentRow?.[plan.localColPropName];
4267
+ if (key === void 0 || key === null) {
4268
+ throw new GraphQLError6(
4269
+ `Drizzle-GraphQL Error: cannot write through '${relationName}': the ${tableName} row has no '${plan.localColPropName}' value to attach to.`
4270
+ );
4271
+ }
4272
+ if (op["set"] !== void 0) {
4273
+ await detachAll(executor, plan, key);
4274
+ for (const filter of asArray(op["set"])) {
4275
+ await executor.update(plan.targetTable).set({ [plan.foreignColPropName]: key }).where(conditionOf(plan, filter, "set"));
4276
+ }
4277
+ }
4278
+ if (op["disconnect"] !== void 0) {
4279
+ if (plan.isOne) {
4280
+ if (op["disconnect"] === true) {
4281
+ await detachAll(executor, plan, key);
4282
+ }
4283
+ } else {
4284
+ for (const filter of asArray(op["disconnect"])) {
4285
+ await executor.update(plan.targetTable).set({ [plan.foreignColPropName]: null }).where(and3(eq3(plan.foreignCol, key), conditionOf(plan, filter, "disconnect")));
4286
+ }
4287
+ }
4288
+ }
4289
+ const attaches = op["connect"] !== void 0 || op["create"] !== void 0;
4290
+ if (plan.isOne && attaches && plan.canDetach && op["set"] === void 0) {
4291
+ await detachAll(executor, plan, key);
4292
+ }
4293
+ if (op["connect"] !== void 0) {
4294
+ for (const filter of asArray(op["connect"])) {
4295
+ await executor.update(plan.targetTable).set({ [plan.foreignColPropName]: key }).where(conditionOf(plan, filter, "connect"));
4296
+ }
4297
+ }
4298
+ if (op["create"] !== void 0) {
4299
+ const rows = asArray(op["create"]).map((row) => ({
4300
+ ...remapFromGraphQLSingleInput({ ...row }, plan.targetTable),
4301
+ [plan.foreignColPropName]: key
4302
+ }));
4303
+ if (rows.length) {
4304
+ await executor.insert(plan.targetTable).values(rows);
4305
+ }
4306
+ }
4307
+ }
3758
4308
  }
3759
4309
  }
3760
- if (Object.keys(relResolvers).length > 0) {
3761
- fieldResolvers[tableName] = relResolvers;
4310
+ };
4311
+ };
4312
+ var writeWithNestedOps = async (params) => {
4313
+ const { executor, runtime, tableName, entries, remapValues, write } = params;
4314
+ return executor.transaction(async (tx) => {
4315
+ const rows = [];
4316
+ for (const entry of entries) {
4317
+ const patch = await runtime.applyParentSide(tx, tableName, entry.ops);
4318
+ const written = await write(tx, { ...remapValues(entry.columns), ...patch });
4319
+ await runtime.applyChildSide(tx, tableName, entry.ops, written);
4320
+ rows.push(...written);
3762
4321
  }
3763
- }
3764
- return { queries, mutations, inputs, types: outputs, fieldResolvers };
4322
+ return rows;
4323
+ });
4324
+ };
4325
+ var updateWithNestedOps = async (params) => {
4326
+ const { executor, runtime, tableName, columns, ops, remapValues, write } = params;
4327
+ return executor.transaction(async (tx) => {
4328
+ const patch = await runtime.applyParentSide(tx, tableName, ops);
4329
+ const rows = await write(tx, { ...remapValues(columns), ...patch });
4330
+ await runtime.applyChildSide(tx, tableName, ops, rows);
4331
+ return rows;
4332
+ });
3765
4333
  };
3766
4334
 
3767
4335
  // src/util/builders/pg.ts
3768
- import { and as and3, getColumns as getColumns3, is as is5, One as One4 } from "drizzle-orm";
3769
- import { getTableConfig as getTableConfig2, PgTable } from "drizzle-orm/pg-core";
3770
- import {
3771
- GraphQLError as GraphQLError6,
3772
- GraphQLList as GraphQLList5,
3773
- GraphQLNonNull as GraphQLNonNull5
3774
- } from "graphql";
3775
- import { parseResolveInfo as parseResolveInfo3 } from "graphql-parse-resolve-info";
3776
4336
  var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
3777
4337
  const queryBase = db.query[tableName];
3778
4338
  const table = tables[tableName];
@@ -3817,24 +4377,24 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
3817
4377
  let cursorEntries;
3818
4378
  if (after != null || cursorSelected) {
3819
4379
  if (after != null && distinct?.length) {
3820
- throw new GraphQLError6("'after' cannot be combined with 'distinct'.");
4380
+ throw new GraphQLError7("'after' cannot be combined with 'distinct'.");
3821
4381
  }
3822
4382
  if (orderByHasRelationEntry(orderBy)) {
3823
4383
  if (after != null) {
3824
- throw new GraphQLError6(
4384
+ throw new GraphQLError7(
3825
4385
  "'after' cannot be combined with an orderBy that orders through a relation \u2014 a related row's value cannot be encoded into a cursor."
3826
4386
  );
3827
4387
  }
3828
4388
  } else if (!pkNames.length) {
3829
4389
  if (after != null) {
3830
- throw new GraphQLError6(
4390
+ throw new GraphQLError7(
3831
4391
  `Table ${tableName} has no primary key, so cursor pagination cannot be used on it.`
3832
4392
  );
3833
4393
  }
3834
4394
  } else {
3835
4395
  cursorEntries = cursorOrderingEntries(orderBy, pkNames);
3836
4396
  if (cursorSelected) {
3837
- const allColumns = getColumns3(table);
4397
+ const allColumns = getColumns4(table);
3838
4398
  for (const [column] of cursorEntries) {
3839
4399
  selectedColumnsSql[column] ??= allColumns[column];
3840
4400
  }
@@ -3843,7 +4403,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
3843
4403
  }
3844
4404
  const cursorCondition = after != null && cursorEntries ? buildCursorCondition(table, cursorEntries, decodeCursor(after, cursorEntries), "nulls-largest") : void 0;
3845
4405
  const baseWhereSql = where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0;
3846
- const whereSql = cursorCondition ? and3(baseWhereSql, cursorCondition) : baseWhereSql;
4406
+ const whereSql = cursorCondition ? and4(baseWhereSql, cursorCondition) : baseWhereSql;
3847
4407
  let distinctKeys;
3848
4408
  if (distinct?.length) {
3849
4409
  distinctKeys = await selectDistinctKeys({
@@ -3954,10 +4514,10 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
3954
4514
  };
3955
4515
  };
3956
4516
  var pgPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig2);
3957
- var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
4517
+ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
3958
4518
  const queryArgs = {
3959
4519
  values: {
3960
- type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(baseType)))
4520
+ type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(baseType)))
3961
4521
  }
3962
4522
  };
3963
4523
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -3966,10 +4526,12 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
3966
4526
  resolver: async (_source, args, context, info) => {
3967
4527
  try {
3968
4528
  return await runMutation(db, context, info, txCtx, async (executor) => {
3969
- const input = remapFromGraphQLArrayInput(args.values, table);
3970
- if (!input.length) {
3971
- throw new GraphQLError6("No values were provided!");
4529
+ if (!args.values.length) {
4530
+ throw new GraphQLError7("No values were provided!");
3972
4531
  }
4532
+ const entries = nested?.enabled(tableName) ? args.values.map((values) => nested.split(tableName, values)) : void 0;
4533
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
4534
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : args.values, table);
3973
4535
  const parsedInfo = parseResolveInfo3(info, {
3974
4536
  deep: true
3975
4537
  });
@@ -3983,11 +4545,22 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
3983
4545
  pkNames,
3984
4546
  parsedInfo
3985
4547
  });
3986
- let query = executor.insert(table).values(input).returning(columns);
3987
- if (conflictDoNothing) {
3988
- query = query.onConflictDoNothing();
3989
- }
3990
- const result = await query;
4548
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
4549
+ const runInsert = async (target, values) => {
4550
+ let query = target.insert(table).values(values).returning(returning);
4551
+ if (conflictDoNothing) {
4552
+ query = query.onConflictDoNothing();
4553
+ }
4554
+ return await query;
4555
+ };
4556
+ const result = nestedEntries ? await writeWithNestedOps({
4557
+ executor,
4558
+ runtime: nested,
4559
+ tableName,
4560
+ entries: nestedEntries,
4561
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
4562
+ write: (tx, values) => runInsert(tx, [values])
4563
+ }) : await runInsert(executor, input);
3991
4564
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
3992
4565
  return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
3993
4566
  });
@@ -3998,10 +4571,10 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
3998
4571
  args: queryArgs
3999
4572
  };
4000
4573
  };
4001
- var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
4574
+ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4002
4575
  const queryArgs = {
4003
4576
  values: {
4004
- type: new GraphQLNonNull5(baseType)
4577
+ type: new GraphQLNonNull6(baseType)
4005
4578
  }
4006
4579
  };
4007
4580
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4010,7 +4583,9 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
4010
4583
  resolver: async (_source, args, context, info) => {
4011
4584
  try {
4012
4585
  return await runMutation(db, context, info, txCtx, async (executor) => {
4013
- const input = remapFromGraphQLSingleInput(args.values, table);
4586
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, args.values) : void 0;
4587
+ const nestedEntry = entry && nested.hasOps(entry.ops) ? entry : void 0;
4588
+ const input = nestedEntry ? {} : remapFromGraphQLSingleInput(entry ? entry.columns : args.values, table);
4014
4589
  const parsedInfo = parseResolveInfo3(info, {
4015
4590
  deep: true
4016
4591
  });
@@ -4024,11 +4599,22 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
4024
4599
  pkNames,
4025
4600
  parsedInfo
4026
4601
  });
4027
- let query = executor.insert(table).values(input).returning(columns);
4028
- if (conflictDoNothing) {
4029
- query = query.onConflictDoNothing();
4030
- }
4031
- const result = await query;
4602
+ const returning = nestedEntry ? nested.withJoinColumns(tableName, nestedEntry.ops, { ...columns }, table) : columns;
4603
+ const runInsert = async (target, values) => {
4604
+ let query = target.insert(table).values(values).returning(returning);
4605
+ if (conflictDoNothing) {
4606
+ query = query.onConflictDoNothing();
4607
+ }
4608
+ return await query;
4609
+ };
4610
+ const result = nestedEntry ? await writeWithNestedOps({
4611
+ executor,
4612
+ runtime: nested,
4613
+ tableName,
4614
+ entries: [nestedEntry],
4615
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
4616
+ write: runInsert
4617
+ }) : await runInsert(executor, input);
4032
4618
  if (!result[0]) {
4033
4619
  return void 0;
4034
4620
  }
@@ -4042,10 +4628,10 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
4042
4628
  args: queryArgs
4043
4629
  };
4044
4630
  };
4045
- var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx) => {
4631
+ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx, nested) => {
4046
4632
  const queryArgs = {
4047
4633
  values: {
4048
- type: single ? new GraphQLNonNull5(baseType) : new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(baseType)))
4634
+ type: single ? new GraphQLNonNull6(baseType) : new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(baseType)))
4049
4635
  },
4050
4636
  onConflict: {
4051
4637
  type: onConflictType,
@@ -4058,10 +4644,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
4058
4644
  resolver: async (_source, args, context, info) => {
4059
4645
  try {
4060
4646
  return await runMutation(db, context, info, txCtx, async (executor) => {
4061
- const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
4062
- if (!input.length) {
4063
- throw new GraphQLError6("No values were provided!");
4647
+ const supplied = single ? [args.values] : args.values;
4648
+ if (!supplied.length) {
4649
+ throw new GraphQLError7("No values were provided!");
4064
4650
  }
4651
+ const entries = nested?.enabled(tableName) ? supplied.map((values) => nested.split(tableName, values)) : void 0;
4652
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
4653
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : supplied, table);
4065
4654
  const parsedInfo = parseResolveInfo3(info, { deep: true });
4066
4655
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
4067
4656
  relationMap,
@@ -4073,19 +4662,30 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
4073
4662
  pkNames,
4074
4663
  parsedInfo
4075
4664
  });
4076
- const plan = resolveConflictPlan({
4077
- table,
4078
- values: input,
4079
- onConflict: args.onConflict,
4080
- pkNames,
4081
- uniqueSets,
4082
- excludedRef: excludedColumnRef,
4083
- withTarget: true,
4084
- buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
4085
- });
4086
- let query = executor.insert(table).values(input).returning(columns);
4087
- query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
4088
- const result = await query;
4665
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
4666
+ const runUpsert = async (target, values) => {
4667
+ const plan = resolveConflictPlan({
4668
+ table,
4669
+ values,
4670
+ onConflict: args.onConflict,
4671
+ pkNames,
4672
+ uniqueSets,
4673
+ excludedRef: excludedColumnRef,
4674
+ withTarget: true,
4675
+ buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
4676
+ });
4677
+ let query = target.insert(table).values(values).returning(returning);
4678
+ query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
4679
+ return await query;
4680
+ };
4681
+ const result = nestedEntries ? await writeWithNestedOps({
4682
+ executor,
4683
+ runtime: nested,
4684
+ tableName,
4685
+ entries: nestedEntries,
4686
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
4687
+ write: (tx, values) => runUpsert(tx, [values])
4688
+ }) : await runUpsert(executor, input);
4089
4689
  if (single && !result[0]) {
4090
4690
  return void 0;
4091
4691
  }
@@ -4099,13 +4699,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
4099
4699
  args: queryArgs
4100
4700
  };
4101
4701
  };
4102
- var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx) => {
4702
+ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx, nested) => {
4103
4703
  const queryArgs = {
4104
4704
  set: {
4105
- type: new GraphQLNonNull5(setArgs)
4705
+ type: new GraphQLNonNull6(setArgs)
4106
4706
  },
4107
4707
  where: {
4108
- type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
4708
+ type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
4109
4709
  }
4110
4710
  };
4111
4711
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4128,23 +4728,37 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
4128
4728
  pkNames,
4129
4729
  parsedInfo
4130
4730
  });
4131
- const input = remapFromGraphQLSingleInput(set, table);
4132
- if (!Object.keys(input).length) {
4133
- throw new GraphQLError6("Unable to update with no values specified!");
4731
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
4732
+ const nestedOps = entry && nested.hasOps(entry.ops) ? entry.ops : void 0;
4733
+ const input = remapFromGraphQLSingleInput(entry ? entry.columns : set, table);
4734
+ if (!Object.keys(input).length && !nestedOps) {
4735
+ throw new GraphQLError7("Unable to update with no values specified!");
4134
4736
  }
4135
4737
  const relationCtx = relationFilterCtx(filterCtx, tableName);
4136
4738
  const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
4137
4739
  if (single) {
4138
4740
  await assertSingleMatch(executor, table, filters, fieldName);
4139
4741
  }
4140
- let query = executor.update(table).set(input);
4141
- if (filters) {
4142
- query = query.where(filters);
4143
- }
4144
- query = query.returning(columns);
4145
- const result = await query;
4742
+ const returning = nestedOps ? nested.withJoinColumns(tableName, nestedOps, { ...columns }, table) : columns;
4743
+ const runUpdate = async (target, values) => {
4744
+ const writes = Object.keys(values).length > 0;
4745
+ let query = writes ? target.update(table).set(values) : target.select(returning).from(table);
4746
+ if (filters) {
4747
+ query = query.where(filters);
4748
+ }
4749
+ return await (writes ? query.returning(returning) : query);
4750
+ };
4751
+ const result = nestedOps ? await updateWithNestedOps({
4752
+ executor,
4753
+ runtime: nested,
4754
+ tableName,
4755
+ columns: input,
4756
+ ops: nestedOps,
4757
+ remapValues: (values) => values,
4758
+ write: runUpdate
4759
+ }) : await runUpdate(executor, input);
4146
4760
  if (single && result.length > 1) {
4147
- throw new GraphQLError6(`${fieldName}: 'where' matched more than one row!`);
4761
+ throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
4148
4762
  }
4149
4763
  if (single && !result[0]) {
4150
4764
  return void 0;
@@ -4159,10 +4773,10 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
4159
4773
  args: queryArgs
4160
4774
  };
4161
4775
  };
4162
- var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx) => {
4776
+ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx, nested) => {
4163
4777
  const queryArgs = {
4164
4778
  updates: {
4165
- type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(updateManyInput)))
4779
+ type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(updateManyInput)))
4166
4780
  }
4167
4781
  };
4168
4782
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4173,7 +4787,7 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
4173
4787
  return await runMutation(db, context, info, txCtx, async (executor) => {
4174
4788
  const { updates } = args;
4175
4789
  if (!updates.length) {
4176
- throw new GraphQLError6("No updates were provided!");
4790
+ throw new GraphQLError7("No updates were provided!");
4177
4791
  }
4178
4792
  const parsedInfo = parseResolveInfo3(info, {
4179
4793
  deep: true
@@ -4189,23 +4803,40 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
4189
4803
  parsedInfo
4190
4804
  });
4191
4805
  const entries = updates.map(({ where, set }) => {
4192
- const input = remapFromGraphQLSingleInput(set, table);
4193
- if (!Object.keys(input).length) {
4194
- throw new GraphQLError6("Unable to update with no values specified!");
4806
+ const split = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
4807
+ const ops = split && nested.hasOps(split.ops) ? split.ops : void 0;
4808
+ const input = remapFromGraphQLSingleInput(split ? split.columns : set, table);
4809
+ if (!Object.keys(input).length && !ops) {
4810
+ throw new GraphQLError7("Unable to update with no values specified!");
4195
4811
  }
4196
4812
  return {
4197
4813
  set: input,
4814
+ ops,
4198
4815
  filters: where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
4199
4816
  };
4200
4817
  });
4818
+ const returning = entries.some((entry) => entry.ops) ? nested.withJoinColumns(
4819
+ tableName,
4820
+ mergedOps(entries.map((entry) => ({ ops: entry.ops ?? {} }))),
4821
+ {
4822
+ ...columns
4823
+ },
4824
+ table
4825
+ ) : columns;
4201
4826
  const perEntry = await executor.transaction(async (tx) => {
4202
4827
  const results = [];
4203
4828
  for (const entry of entries) {
4204
- let query = tx.update(table).set(entry.set);
4829
+ const values = entry.ops ? { ...entry.set, ...await nested.applyParentSide(tx, tableName, entry.ops) } : entry.set;
4830
+ const writes = Object.keys(values).length > 0;
4831
+ let query = writes ? tx.update(table).set(values) : tx.select(returning).from(table);
4205
4832
  if (entry.filters) {
4206
4833
  query = query.where(entry.filters);
4207
4834
  }
4208
- results.push(await query.returning(columns));
4835
+ const rows = await (writes ? query.returning(returning) : query);
4836
+ if (entry.ops) {
4837
+ await nested.applyChildSide(tx, tableName, entry.ops, rows);
4838
+ }
4839
+ results.push(rows);
4209
4840
  }
4210
4841
  return results;
4211
4842
  });
@@ -4235,7 +4866,7 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
4235
4866
  var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx) => {
4236
4867
  const queryArgs = {
4237
4868
  where: {
4238
- type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
4869
+ type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
4239
4870
  }
4240
4871
  };
4241
4872
  return {
@@ -4264,7 +4895,7 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, si
4264
4895
  query = query.returning(columns);
4265
4896
  const result = await query;
4266
4897
  if (single && result.length > 1) {
4267
- throw new GraphQLError6(`${fieldName}: 'where' matched more than one row!`);
4898
+ throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
4268
4899
  }
4269
4900
  if (single) {
4270
4901
  return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
@@ -4290,13 +4921,15 @@ function generateSchemaData2(db, schema, relations, options) {
4290
4921
  complexity
4291
4922
  } = options;
4292
4923
  const schemaEntries = Object.entries(schema);
4293
- const tableEntries = schemaEntries.filter(([_key, value]) => is5(value, PgTable));
4924
+ const tableEntries = schemaEntries.filter(([_key, value]) => is6(value, PgTable));
4294
4925
  const tables = Object.fromEntries(tableEntries);
4295
4926
  if (!tableEntries.length) {
4296
4927
  throw new Error(
4297
4928
  "Drizzle-GraphQL Error: No tables detected in Drizzle-ORM's database instance. Did you forget to pass schema to drizzle constructor?"
4298
4929
  );
4299
4930
  }
4931
+ registerScalarOverrides(tables, options);
4932
+ registerEnumConfig(options);
4300
4933
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
4301
4934
  attachTargetPrimaryKeys(namedRelations, tables, pgPrimaryKeyPropNames);
4302
4935
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
@@ -4308,12 +4941,24 @@ function generateSchemaData2(db, schema, relations, options) {
4308
4941
  relationFieldContainers: /* @__PURE__ */ new Map(),
4309
4942
  fullyBuiltTables: /* @__PURE__ */ new Set(),
4310
4943
  relationTypeCache: /* @__PURE__ */ new Map(),
4944
+ selectFieldCache: /* @__PURE__ */ new WeakMap(),
4945
+ filterFieldCache: /* @__PURE__ */ new WeakMap(),
4311
4946
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
4312
4947
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
4313
4948
  listRelationFilterCache: /* @__PURE__ */ new Map(),
4314
4949
  aggregateTypeCache: /* @__PURE__ */ new Map(),
4315
- complexity
4950
+ complexity,
4951
+ docs: options.docs ?? {}
4316
4952
  };
4953
+ const nestedPlans = features.nestedWrites ? buildNestedWritePlans(
4954
+ tables,
4955
+ namedRelations,
4956
+ (target) => getUniqueColumnSets(target, getTableConfig2),
4957
+ (target) => pgPrimaryKeyPropNames(target),
4958
+ extractRelationJoinColumns
4959
+ ) : void 0;
4960
+ const nestedTypes = nestedPlans ? createNestedWriteTypes({ plans: nestedPlans, cacheCtx, typeNameMapper, insertPrefix: prefixes.insert }) : void 0;
4961
+ const nestedRuntime = nestedPlans ? createNestedWriteRuntime({ plans: nestedPlans, filterCtx }) : void 0;
4317
4962
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
4318
4963
  const queries = {};
4319
4964
  const mutations = {};
@@ -4332,7 +4977,8 @@ function generateSchemaData2(db, schema, relations, options) {
4332
4977
  prefixes.insert,
4333
4978
  prefixes.update,
4334
4979
  resolverFactory,
4335
- relationAggregateFactory
4980
+ relationAggregateFactory,
4981
+ nestedTypes
4336
4982
  )
4337
4983
  ])
4338
4984
  );
@@ -4393,7 +5039,8 @@ function generateSchemaData2(db, schema, relations, options) {
4393
5039
  typeName,
4394
5040
  typeNameMapper,
4395
5041
  conflictDoNothing,
4396
- mutationTxCtx
5042
+ mutationTxCtx,
5043
+ nestedRuntime
4397
5044
  ) : void 0;
4398
5045
  const insertSingleGenerated = features.insert ? generateInsertSingle2(
4399
5046
  db,
@@ -4406,7 +5053,8 @@ function generateSchemaData2(db, schema, relations, options) {
4406
5053
  typeName,
4407
5054
  typeNameMapper,
4408
5055
  conflictDoNothing,
4409
- mutationTxCtx
5056
+ mutationTxCtx,
5057
+ nestedRuntime
4410
5058
  ) : void 0;
4411
5059
  const uniqueSets = features.upsert ? getUniqueColumnSets(schema[tableName], getTableConfig2) : [];
4412
5060
  const onConflictInput = features.upsert ? generateOnConflictInput({
@@ -4430,7 +5078,8 @@ function generateSchemaData2(db, schema, relations, options) {
4430
5078
  false,
4431
5079
  typeNameMapper,
4432
5080
  filterCtx,
4433
- mutationTxCtx
5081
+ mutationTxCtx,
5082
+ nestedRuntime
4434
5083
  ) : void 0;
4435
5084
  const upsertSingleGenerated = onConflictInput ? generateUpsert2(
4436
5085
  db,
@@ -4446,7 +5095,8 @@ function generateSchemaData2(db, schema, relations, options) {
4446
5095
  true,
4447
5096
  typeNameMapper,
4448
5097
  filterCtx,
4449
- mutationTxCtx
5098
+ mutationTxCtx,
5099
+ nestedRuntime
4450
5100
  ) : void 0;
4451
5101
  const updateGenerated = features.update ? generateUpdate2(
4452
5102
  db,
@@ -4462,7 +5112,8 @@ function generateSchemaData2(db, schema, relations, options) {
4462
5112
  features.requireWhere,
4463
5113
  typeNameMapper,
4464
5114
  filterCtx,
4465
- mutationTxCtx
5115
+ mutationTxCtx,
5116
+ nestedRuntime
4466
5117
  ) : void 0;
4467
5118
  const updateSingleGenerated = features.update ? generateUpdate2(
4468
5119
  db,
@@ -4478,7 +5129,8 @@ function generateSchemaData2(db, schema, relations, options) {
4478
5129
  features.requireWhere,
4479
5130
  typeNameMapper,
4480
5131
  filterCtx,
4481
- mutationTxCtx
5132
+ mutationTxCtx,
5133
+ nestedRuntime
4482
5134
  ) : void 0;
4483
5135
  const updateManyInput = features.update && features.updateMany ? generateUpdateManyInput({ typeName, updatePrefix: prefixes.update, updateInput, tableFilters }) : void 0;
4484
5136
  const updateManyGenerated = updateManyInput ? generateUpdateMany2(
@@ -4492,7 +5144,8 @@ function generateSchemaData2(db, schema, relations, options) {
4492
5144
  typeName,
4493
5145
  typeNameMapper,
4494
5146
  filterCtx,
4495
- mutationTxCtx
5147
+ mutationTxCtx,
5148
+ nestedRuntime
4496
5149
  ) : void 0;
4497
5150
  const deleteGenerated = features.delete ? generateDelete2(
4498
5151
  db,
@@ -4557,7 +5210,7 @@ function generateSchemaData2(db, schema, relations, options) {
4557
5210
  };
4558
5211
  if (aggregateGenerated && aggregateType) {
4559
5212
  queries[aggregateGenerated.name] = {
4560
- type: new GraphQLNonNull5(aggregateType),
5213
+ type: new GraphQLNonNull6(aggregateType),
4561
5214
  args: aggregateGenerated.args,
4562
5215
  resolve: aggregateGenerated.resolver,
4563
5216
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -4565,7 +5218,7 @@ function generateSchemaData2(db, schema, relations, options) {
4565
5218
  }
4566
5219
  if (groupByGenerated && groupByType) {
4567
5220
  queries[groupByGenerated.name] = {
4568
- type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(groupByType))),
5221
+ type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(groupByType))),
4569
5222
  args: groupByGenerated.args,
4570
5223
  resolve: groupByGenerated.resolver,
4571
5224
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -4609,7 +5262,7 @@ function generateSchemaData2(db, schema, relations, options) {
4609
5262
  if (updateManyGenerated) {
4610
5263
  mutations[updateManyGenerated.name] = {
4611
5264
  // Nullable items: a no-match entry yields `null` in its slot.
4612
- type: new GraphQLNonNull5(new GraphQLList5(singleTableItemOutput)),
5265
+ type: new GraphQLNonNull6(new GraphQLList6(singleTableItemOutput)),
4613
5266
  args: updateManyGenerated.args,
4614
5267
  resolve: updateManyGenerated.resolver
4615
5268
  };
@@ -4666,7 +5319,7 @@ function generateSchemaData2(db, schema, relations, options) {
4666
5319
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
4667
5320
  const relResolvers = {};
4668
5321
  for (const [relName, relEntry] of Object.entries(tableRelations)) {
4669
- const isOne = is5(relEntry.relation ?? relEntry, One4);
5322
+ const isOne = is6(relEntry.relation ?? relEntry, One5);
4670
5323
  const resolver = resolverFactory({ tableName, relationName: relName, relEntry, isOne });
4671
5324
  if (resolver) {
4672
5325
  relResolvers[relName] = resolver;
@@ -4680,12 +5333,12 @@ function generateSchemaData2(db, schema, relations, options) {
4680
5333
  }
4681
5334
 
4682
5335
  // src/util/builders/sqlite.ts
4683
- import { is as is6, One as One5 } from "drizzle-orm";
5336
+ import { is as is7, One as One6 } from "drizzle-orm";
4684
5337
  import { getTableConfig as getTableConfig3, SQLiteTable } from "drizzle-orm/sqlite-core";
4685
5338
  import {
4686
- GraphQLError as GraphQLError7,
4687
- GraphQLList as GraphQLList6,
4688
- GraphQLNonNull as GraphQLNonNull6
5339
+ GraphQLError as GraphQLError8,
5340
+ GraphQLList as GraphQLList7,
5341
+ GraphQLNonNull as GraphQLNonNull7
4689
5342
  } from "graphql";
4690
5343
  import { parseResolveInfo as parseResolveInfo4 } from "graphql-parse-resolve-info";
4691
5344
  var generateSelectArray3 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
@@ -4771,10 +5424,10 @@ var generateSelectSingle3 = (db, tableName, tables, relationMap, orderArgs, filt
4771
5424
  };
4772
5425
  };
4773
5426
  var sqlitePrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig3);
4774
- var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
5427
+ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4775
5428
  const queryArgs = {
4776
5429
  values: {
4777
- type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(baseType)))
5430
+ type: new GraphQLNonNull7(new GraphQLList7(new GraphQLNonNull7(baseType)))
4778
5431
  }
4779
5432
  };
4780
5433
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -4783,10 +5436,12 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
4783
5436
  resolver: async (_source, args, context, info) => {
4784
5437
  try {
4785
5438
  return await runMutation(db, context, info, txCtx, async (executor) => {
4786
- const input = remapFromGraphQLArrayInput(args.values, table);
4787
- if (!input.length) {
4788
- throw new GraphQLError7("No values were provided!");
5439
+ if (!args.values.length) {
5440
+ throw new GraphQLError8("No values were provided!");
4789
5441
  }
5442
+ const entries = nested?.enabled(tableName) ? args.values.map((values) => nested.split(tableName, values)) : void 0;
5443
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
5444
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : args.values, table);
4790
5445
  const parsedInfo = parseResolveInfo4(info, {
4791
5446
  deep: true
4792
5447
  });
@@ -4800,11 +5455,22 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
4800
5455
  pkNames,
4801
5456
  parsedInfo
4802
5457
  });
4803
- let query = executor.insert(table).values(input).returning(columns);
4804
- if (conflictDoNothing) {
4805
- query = query.onConflictDoNothing();
4806
- }
4807
- const result = await query;
5458
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
5459
+ const runInsert = async (target, values) => {
5460
+ let query = target.insert(table).values(values).returning(returning);
5461
+ if (conflictDoNothing) {
5462
+ query = query.onConflictDoNothing();
5463
+ }
5464
+ return await query;
5465
+ };
5466
+ const result = nestedEntries ? await writeWithNestedOps({
5467
+ executor,
5468
+ runtime: nested,
5469
+ tableName,
5470
+ entries: nestedEntries,
5471
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
5472
+ write: (tx, values) => runInsert(tx, [values])
5473
+ }) : await runInsert(executor, input);
4808
5474
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
4809
5475
  return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
4810
5476
  });
@@ -4815,10 +5481,10 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
4815
5481
  args: queryArgs
4816
5482
  };
4817
5483
  };
4818
- var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
5484
+ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4819
5485
  const queryArgs = {
4820
5486
  values: {
4821
- type: new GraphQLNonNull6(baseType)
5487
+ type: new GraphQLNonNull7(baseType)
4822
5488
  }
4823
5489
  };
4824
5490
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -4827,7 +5493,9 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
4827
5493
  resolver: async (_source, args, context, info) => {
4828
5494
  try {
4829
5495
  return await runMutation(db, context, info, txCtx, async (executor) => {
4830
- const input = remapFromGraphQLSingleInput(args.values, table);
5496
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, args.values) : void 0;
5497
+ const nestedEntry = entry && nested.hasOps(entry.ops) ? entry : void 0;
5498
+ const input = nestedEntry ? {} : remapFromGraphQLSingleInput(entry ? entry.columns : args.values, table);
4831
5499
  const parsedInfo = parseResolveInfo4(info, {
4832
5500
  deep: true
4833
5501
  });
@@ -4841,11 +5509,22 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
4841
5509
  pkNames,
4842
5510
  parsedInfo
4843
5511
  });
4844
- let query = executor.insert(table).values(input).returning(columns);
4845
- if (conflictDoNothing) {
4846
- query = query.onConflictDoNothing();
4847
- }
4848
- const result = await query;
5512
+ const returning = nestedEntry ? nested.withJoinColumns(tableName, nestedEntry.ops, { ...columns }, table) : columns;
5513
+ const runInsert = async (target, values) => {
5514
+ let query = target.insert(table).values(values).returning(returning);
5515
+ if (conflictDoNothing) {
5516
+ query = query.onConflictDoNothing();
5517
+ }
5518
+ return await query;
5519
+ };
5520
+ const result = nestedEntry ? await writeWithNestedOps({
5521
+ executor,
5522
+ runtime: nested,
5523
+ tableName,
5524
+ entries: [nestedEntry],
5525
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
5526
+ write: runInsert
5527
+ }) : await runInsert(executor, input);
4849
5528
  if (!result[0]) {
4850
5529
  return void 0;
4851
5530
  }
@@ -4859,10 +5538,10 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
4859
5538
  args: queryArgs
4860
5539
  };
4861
5540
  };
4862
- var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx) => {
5541
+ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx, nested) => {
4863
5542
  const queryArgs = {
4864
5543
  values: {
4865
- type: single ? new GraphQLNonNull6(baseType) : new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(baseType)))
5544
+ type: single ? new GraphQLNonNull7(baseType) : new GraphQLNonNull7(new GraphQLList7(new GraphQLNonNull7(baseType)))
4866
5545
  },
4867
5546
  onConflict: {
4868
5547
  type: onConflictType,
@@ -4875,10 +5554,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
4875
5554
  resolver: async (_source, args, context, info) => {
4876
5555
  try {
4877
5556
  return await runMutation(db, context, info, txCtx, async (executor) => {
4878
- const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
4879
- if (!input.length) {
4880
- throw new GraphQLError7("No values were provided!");
5557
+ const supplied = single ? [args.values] : args.values;
5558
+ if (!supplied.length) {
5559
+ throw new GraphQLError8("No values were provided!");
4881
5560
  }
5561
+ const entries = nested?.enabled(tableName) ? supplied.map((values) => nested.split(tableName, values)) : void 0;
5562
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
5563
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : supplied, table);
4882
5564
  const parsedInfo = parseResolveInfo4(info, { deep: true });
4883
5565
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
4884
5566
  relationMap,
@@ -4890,19 +5572,30 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
4890
5572
  pkNames,
4891
5573
  parsedInfo
4892
5574
  });
4893
- const plan = resolveConflictPlan({
4894
- table,
4895
- values: input,
4896
- onConflict: args.onConflict,
4897
- pkNames,
4898
- uniqueSets,
4899
- excludedRef: excludedColumnRef,
4900
- withTarget: true,
4901
- buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
4902
- });
4903
- let query = executor.insert(table).values(input).returning(columns);
4904
- query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
4905
- const result = await query;
5575
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
5576
+ const runUpsert = async (target, values) => {
5577
+ const plan = resolveConflictPlan({
5578
+ table,
5579
+ values,
5580
+ onConflict: args.onConflict,
5581
+ pkNames,
5582
+ uniqueSets,
5583
+ excludedRef: excludedColumnRef,
5584
+ withTarget: true,
5585
+ buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
5586
+ });
5587
+ let query = target.insert(table).values(values).returning(returning);
5588
+ query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
5589
+ return await query;
5590
+ };
5591
+ const result = nestedEntries ? await writeWithNestedOps({
5592
+ executor,
5593
+ runtime: nested,
5594
+ tableName,
5595
+ entries: nestedEntries,
5596
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
5597
+ write: (tx, values) => runUpsert(tx, [values])
5598
+ }) : await runUpsert(executor, input);
4906
5599
  if (single && !result[0]) {
4907
5600
  return void 0;
4908
5601
  }
@@ -4916,13 +5609,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
4916
5609
  args: queryArgs
4917
5610
  };
4918
5611
  };
4919
- var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx) => {
5612
+ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx, nested) => {
4920
5613
  const queryArgs = {
4921
5614
  set: {
4922
- type: new GraphQLNonNull6(setArgs)
5615
+ type: new GraphQLNonNull7(setArgs)
4923
5616
  },
4924
5617
  where: {
4925
- type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
5618
+ type: single || requireWhere ? new GraphQLNonNull7(filterArgs) : filterArgs
4926
5619
  }
4927
5620
  };
4928
5621
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -4945,23 +5638,37 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
4945
5638
  pkNames,
4946
5639
  parsedInfo
4947
5640
  });
4948
- const input = remapFromGraphQLSingleInput(set, table);
4949
- if (!Object.keys(input).length) {
4950
- throw new GraphQLError7("Unable to update with no values specified!");
5641
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
5642
+ const nestedOps = entry && nested.hasOps(entry.ops) ? entry.ops : void 0;
5643
+ const input = remapFromGraphQLSingleInput(entry ? entry.columns : set, table);
5644
+ if (!Object.keys(input).length && !nestedOps) {
5645
+ throw new GraphQLError8("Unable to update with no values specified!");
4951
5646
  }
4952
5647
  const relationCtx = relationFilterCtx(filterCtx, tableName);
4953
5648
  const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
4954
5649
  if (single) {
4955
5650
  await assertSingleMatch(executor, table, filters, fieldName);
4956
5651
  }
4957
- let query = executor.update(table).set(input);
4958
- if (filters) {
4959
- query = query.where(filters);
4960
- }
4961
- query = query.returning(columns);
4962
- const result = await query;
5652
+ const returning = nestedOps ? nested.withJoinColumns(tableName, nestedOps, { ...columns }, table) : columns;
5653
+ const runUpdate = async (target, values) => {
5654
+ const writes = Object.keys(values).length > 0;
5655
+ let query = writes ? target.update(table).set(values) : target.select(returning).from(table);
5656
+ if (filters) {
5657
+ query = query.where(filters);
5658
+ }
5659
+ return await (writes ? query.returning(returning) : query);
5660
+ };
5661
+ const result = nestedOps ? await updateWithNestedOps({
5662
+ executor,
5663
+ runtime: nested,
5664
+ tableName,
5665
+ columns: input,
5666
+ ops: nestedOps,
5667
+ remapValues: (values) => values,
5668
+ write: runUpdate
5669
+ }) : await runUpdate(executor, input);
4963
5670
  if (single && result.length > 1) {
4964
- throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
5671
+ throw new GraphQLError8(`${fieldName}: 'where' matched more than one row!`);
4965
5672
  }
4966
5673
  if (single && !result[0]) {
4967
5674
  return void 0;
@@ -4976,10 +5683,10 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
4976
5683
  args: queryArgs
4977
5684
  };
4978
5685
  };
4979
- var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx) => {
5686
+ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx, nested) => {
4980
5687
  const queryArgs = {
4981
5688
  updates: {
4982
- type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(updateManyInput)))
5689
+ type: new GraphQLNonNull7(new GraphQLList7(new GraphQLNonNull7(updateManyInput)))
4983
5690
  }
4984
5691
  };
4985
5692
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -4990,7 +5697,7 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
4990
5697
  return await runMutation(db, context, info, txCtx, async (executor) => {
4991
5698
  const { updates } = args;
4992
5699
  if (!updates.length) {
4993
- throw new GraphQLError7("No updates were provided!");
5700
+ throw new GraphQLError8("No updates were provided!");
4994
5701
  }
4995
5702
  const parsedInfo = parseResolveInfo4(info, {
4996
5703
  deep: true
@@ -5006,23 +5713,55 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
5006
5713
  parsedInfo
5007
5714
  });
5008
5715
  const entries = updates.map(({ where, set }) => {
5009
- const input = remapFromGraphQLSingleInput(set, table);
5010
- if (!Object.keys(input).length) {
5011
- throw new GraphQLError7("Unable to update with no values specified!");
5716
+ const split = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
5717
+ const ops = split && nested.hasOps(split.ops) ? split.ops : void 0;
5718
+ const input = remapFromGraphQLSingleInput(split ? split.columns : set, table);
5719
+ if (!Object.keys(input).length && !ops) {
5720
+ throw new GraphQLError8("Unable to update with no values specified!");
5012
5721
  }
5013
5722
  return {
5014
5723
  set: input,
5724
+ ops,
5015
5725
  filters: where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
5016
5726
  };
5017
5727
  });
5728
+ const anyNested = entries.some((entry) => entry.ops);
5729
+ const returning = anyNested ? nested.withJoinColumns(
5730
+ tableName,
5731
+ mergedOps(entries.map((entry) => ({ ops: entry.ops ?? {} }))),
5732
+ { ...columns },
5733
+ table
5734
+ ) : columns;
5018
5735
  const runEntry = (tx, entry) => {
5019
5736
  let query = tx.update(table).set(entry.set);
5020
5737
  if (entry.filters) {
5021
5738
  query = query.where(entry.filters);
5022
5739
  }
5023
- return query.returning(columns).all();
5740
+ return query.returning(returning).all();
5741
+ };
5742
+ const runNestedEntry = async (tx, entry) => {
5743
+ const values = entry.ops ? { ...entry.set, ...await nested.applyParentSide(tx, tableName, entry.ops) } : entry.set;
5744
+ const writes = Object.keys(values).length > 0;
5745
+ let query = writes ? tx.update(table).set(values) : tx.select(returning).from(table);
5746
+ if (entry.filters) {
5747
+ query = query.where(entry.filters);
5748
+ }
5749
+ const rows = await (writes ? query.returning(returning) : query);
5750
+ if (entry.ops) {
5751
+ await nested.applyChildSide(tx, tableName, entry.ops, rows);
5752
+ }
5753
+ return rows;
5024
5754
  };
5025
5755
  const perEntry = await executor.transaction((tx) => {
5756
+ if (anyNested) {
5757
+ return (async () => {
5758
+ const results2 = [];
5759
+ for (const entry of entries) {
5760
+ results2.push(await runNestedEntry(tx, entry));
5761
+ }
5762
+ return results2;
5763
+ })();
5764
+ }
5026
5765
  const first = runEntry(tx, entries[0]);
5027
5766
  if (typeof first?.then === "function") {
5028
5767
  return (async () => {
@@ -5065,7 +5804,7 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
5065
5804
  var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx) => {
5066
5805
  const queryArgs = {
5067
5806
  where: {
5068
- type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
5807
+ type: single || requireWhere ? new GraphQLNonNull7(filterArgs) : filterArgs
5069
5808
  }
5070
5809
  };
5071
5810
  return {
@@ -5094,7 +5833,7 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, si
5094
5833
  query = query.returning(columns);
5095
5834
  const result = await query;
5096
5835
  if (single && result.length > 1) {
5097
- throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
5836
+ throw new GraphQLError8(`${fieldName}: 'where' matched more than one row!`);
5098
5837
  }
5099
5838
  if (single) {
5100
5839
  return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
@@ -5121,13 +5860,15 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5121
5860
  } = options;
5122
5861
  const rawSchema = schema;
5123
5862
  const schemaEntries = Object.entries(rawSchema);
5124
- const tableEntries = schemaEntries.filter(([_key, value]) => is6(value, SQLiteTable));
5863
+ const tableEntries = schemaEntries.filter(([_key, value]) => is7(value, SQLiteTable));
5125
5864
  const tables = Object.fromEntries(tableEntries);
5126
5865
  if (!tableEntries.length) {
5127
5866
  throw new Error(
5128
5867
  "Drizzle-GraphQL Error: No tables detected in Drizzle-ORM's database instance. Did you forget to pass schema to drizzle constructor?"
5129
5868
  );
5130
5869
  }
5870
+ registerScalarOverrides(tables, options);
5871
+ registerEnumConfig(options);
5131
5872
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
5132
5873
  attachTargetPrimaryKeys(namedRelations, tables, sqlitePrimaryKeyPropNames);
5133
5874
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
@@ -5139,12 +5880,29 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5139
5880
  relationFieldContainers: /* @__PURE__ */ new Map(),
5140
5881
  fullyBuiltTables: /* @__PURE__ */ new Set(),
5141
5882
  relationTypeCache: /* @__PURE__ */ new Map(),
5883
+ selectFieldCache: /* @__PURE__ */ new WeakMap(),
5884
+ filterFieldCache: /* @__PURE__ */ new WeakMap(),
5142
5885
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
5143
5886
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
5144
5887
  listRelationFilterCache: /* @__PURE__ */ new Map(),
5145
5888
  aggregateTypeCache: /* @__PURE__ */ new Map(),
5146
- complexity
5889
+ complexity,
5890
+ docs: options.docs ?? {}
5147
5891
  };
5892
+ if (features.nestedWrites && db.resultKind === "sync") {
5893
+ throw new Error(
5894
+ "Drizzle-GraphQL Error: features.nestedWrites requires an asynchronous SQLite driver (e.g. libsql). Synchronous drivers cannot run the multi-statement transaction a nested write needs."
5895
+ );
5896
+ }
5897
+ const nestedPlans = features.nestedWrites ? buildNestedWritePlans(
5898
+ tables,
5899
+ namedRelations,
5900
+ (target) => getUniqueColumnSets(target, getTableConfig3),
5901
+ (target) => sqlitePrimaryKeyPropNames(target),
5902
+ extractRelationJoinColumns
5903
+ ) : void 0;
5904
+ const nestedTypes = nestedPlans ? createNestedWriteTypes({ plans: nestedPlans, cacheCtx, typeNameMapper, insertPrefix: prefixes.insert }) : void 0;
5905
+ const nestedRuntime = nestedPlans ? createNestedWriteRuntime({ plans: nestedPlans, filterCtx }) : void 0;
5148
5906
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
5149
5907
  const queries = {};
5150
5908
  const mutations = {};
@@ -5168,7 +5926,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5168
5926
  prefixes.insert,
5169
5927
  prefixes.update,
5170
5928
  resolverFactory,
5171
- relationAggregateFactory
5929
+ relationAggregateFactory,
5930
+ nestedTypes
5172
5931
  )
5173
5932
  ])
5174
5933
  );
@@ -5229,7 +5988,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5229
5988
  typeName,
5230
5989
  typeNameMapper,
5231
5990
  conflictDoNothing,
5232
- mutationTxCtx
5991
+ mutationTxCtx,
5992
+ nestedRuntime
5233
5993
  ) : void 0;
5234
5994
  const insertSingleGenerated = features.insert ? generateInsertSingle3(
5235
5995
  db,
@@ -5242,7 +6002,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5242
6002
  typeName,
5243
6003
  typeNameMapper,
5244
6004
  conflictDoNothing,
5245
- mutationTxCtx
6005
+ mutationTxCtx,
6006
+ nestedRuntime
5246
6007
  ) : void 0;
5247
6008
  const uniqueSets = features.upsert ? getUniqueColumnSets(schema[tableName], getTableConfig3) : [];
5248
6009
  const onConflictInput = features.upsert ? generateOnConflictInput({
@@ -5266,7 +6027,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5266
6027
  false,
5267
6028
  typeNameMapper,
5268
6029
  filterCtx,
5269
- mutationTxCtx
6030
+ mutationTxCtx,
6031
+ nestedRuntime
5270
6032
  ) : void 0;
5271
6033
  const upsertSingleGenerated = onConflictInput ? generateUpsert3(
5272
6034
  db,
@@ -5282,7 +6044,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5282
6044
  true,
5283
6045
  typeNameMapper,
5284
6046
  filterCtx,
5285
- mutationTxCtx
6047
+ mutationTxCtx,
6048
+ nestedRuntime
5286
6049
  ) : void 0;
5287
6050
  const updateGenerated = features.update ? generateUpdate3(
5288
6051
  db,
@@ -5298,7 +6061,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5298
6061
  features.requireWhere,
5299
6062
  typeNameMapper,
5300
6063
  filterCtx,
5301
- mutationTxCtx
6064
+ mutationTxCtx,
6065
+ nestedRuntime
5302
6066
  ) : void 0;
5303
6067
  const updateSingleGenerated = features.update ? generateUpdate3(
5304
6068
  db,
@@ -5314,7 +6078,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5314
6078
  features.requireWhere,
5315
6079
  typeNameMapper,
5316
6080
  filterCtx,
5317
- mutationTxCtx
6081
+ mutationTxCtx,
6082
+ nestedRuntime
5318
6083
  ) : void 0;
5319
6084
  const updateManyInput = features.update && features.updateMany ? generateUpdateManyInput({ typeName, updatePrefix: prefixes.update, updateInput, tableFilters }) : void 0;
5320
6085
  const updateManyGenerated = updateManyInput ? generateUpdateMany3(
@@ -5328,7 +6093,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5328
6093
  typeName,
5329
6094
  typeNameMapper,
5330
6095
  filterCtx,
5331
- mutationTxCtx
6096
+ mutationTxCtx,
6097
+ nestedRuntime
5332
6098
  ) : void 0;
5333
6099
  const deleteGenerated = features.delete ? generateDelete3(
5334
6100
  db,
@@ -5393,7 +6159,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5393
6159
  };
5394
6160
  if (aggregateGenerated && aggregateType) {
5395
6161
  queries[aggregateGenerated.name] = {
5396
- type: new GraphQLNonNull6(aggregateType),
6162
+ type: new GraphQLNonNull7(aggregateType),
5397
6163
  args: aggregateGenerated.args,
5398
6164
  resolve: aggregateGenerated.resolver,
5399
6165
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -5401,7 +6167,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5401
6167
  }
5402
6168
  if (groupByGenerated && groupByType) {
5403
6169
  queries[groupByGenerated.name] = {
5404
- type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(groupByType))),
6170
+ type: new GraphQLNonNull7(new GraphQLList7(new GraphQLNonNull7(groupByType))),
5405
6171
  args: groupByGenerated.args,
5406
6172
  resolve: groupByGenerated.resolver,
5407
6173
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -5445,7 +6211,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5445
6211
  if (updateManyGenerated) {
5446
6212
  mutations[updateManyGenerated.name] = {
5447
6213
  // Nullable items: a no-match entry yields `null` in its slot.
5448
- type: new GraphQLNonNull6(new GraphQLList6(singleTableItemOutput)),
6214
+ type: new GraphQLNonNull7(new GraphQLList7(singleTableItemOutput)),
5449
6215
  args: updateManyGenerated.args,
5450
6216
  resolve: updateManyGenerated.resolver
5451
6217
  };
@@ -5502,7 +6268,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5502
6268
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
5503
6269
  const relResolvers = {};
5504
6270
  for (const [relName, relEntry] of Object.entries(tableRelations)) {
5505
- const isOne = is6(relEntry.relation ?? relEntry, One5);
6271
+ const isOne = is7(relEntry.relation ?? relEntry, One6);
5506
6272
  const resolver = resolverFactory({ tableName, relationName: relName, relEntry, isOne });
5507
6273
  if (resolver) {
5508
6274
  relResolvers[relName] = resolver;
@@ -5547,6 +6313,7 @@ var buildSchema = (db, config) => {
5547
6313
  updateMany: config?.features?.updateMany ?? true,
5548
6314
  delete: config?.features?.delete ?? true,
5549
6315
  upsert: config?.features?.upsert ?? false,
6316
+ nestedWrites: config?.features?.nestedWrites ?? false,
5550
6317
  requireWhere: config?.features?.requireWhere ?? false
5551
6318
  };
5552
6319
  const complexityConfig = config?.complexity ?? true;
@@ -5584,14 +6351,23 @@ var buildSchema = (db, config) => {
5584
6351
  shouldEagerLoad,
5585
6352
  features,
5586
6353
  complexity,
5587
- transactions
6354
+ scalars: config?.scalars,
6355
+ mapColumnType: config?.mapColumnType,
6356
+ enumNameMapper: config?.enumNameMapper,
6357
+ transactions,
6358
+ docs: {
6359
+ describeColumn: config?.describeColumn,
6360
+ describeTable: config?.describeTable,
6361
+ describeRelation: config?.describeRelation,
6362
+ deprecateColumn: config?.deprecateColumn
6363
+ }
5588
6364
  };
5589
6365
  let generatorOutput;
5590
- if (is7(db, MySqlDatabase)) {
6366
+ if (is8(db, MySqlDatabase)) {
5591
6367
  generatorOutput = generateSchemaData(db, schema, relations, generatorOptions);
5592
- } else if (is7(db, PgAsyncDatabase)) {
6368
+ } else if (is8(db, PgAsyncDatabase)) {
5593
6369
  generatorOutput = generateSchemaData2(db, schema, relations, generatorOptions);
5594
- } else if (is7(db, BaseSQLiteDatabase)) {
6370
+ } else if (is8(db, BaseSQLiteDatabase)) {
5595
6371
  generatorOutput = generateSchemaData3(db, schema, relations, generatorOptions);
5596
6372
  } else {
5597
6373
  throw new Error("Drizzle-GraphQL Error: Unknown database instance type");