@vantreeseba/drizzle-graphql 5.6.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.cjs CHANGED
@@ -45,11 +45,11 @@ __export(index_exports, {
45
45
  extractRelationJoinColumns: () => extractRelationJoinColumns
46
46
  });
47
47
  module.exports = __toCommonJS(index_exports);
48
- var import_drizzle_orm8 = require("drizzle-orm");
48
+ var import_drizzle_orm9 = require("drizzle-orm");
49
49
  var import_mysql_core3 = require("drizzle-orm/mysql-core");
50
50
  var import_pg_core3 = require("drizzle-orm/pg-core");
51
51
  var import_sqlite_core3 = require("drizzle-orm/sqlite-core");
52
- var import_graphql9 = require("graphql");
52
+ var import_graphql10 = require("graphql");
53
53
 
54
54
  // src/util/builders/common.ts
55
55
  var import_drizzle_orm3 = require("drizzle-orm");
@@ -189,15 +189,42 @@ var GraphQLDecimalString = new import_graphql.GraphQLScalarType({
189
189
 
190
190
  // src/util/type-converter/index.ts
191
191
  var allowedNameChars = /^[a-zA-Z0-9_]+$/;
192
- var enumMap = /* @__PURE__ */ new WeakMap();
192
+ var declaredEnum = (column) => {
193
+ const declared = column.enum;
194
+ return typeof declared?.enumName === "string" ? { enumName: declared.enumName, schema: typeof declared.schema === "string" ? declared.schema : void 0 } : void 0;
195
+ };
196
+ var pascalize = (input) => input.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => capitalize(part)).join("");
197
+ var enumValuesKey = (values) => JSON.stringify(values);
198
+ var enumNamesInUse = /* @__PURE__ */ new Map();
199
+ var enumNameMapper;
200
+ var registerEnumConfig = (config) => {
201
+ enumNameMapper = config.enumNameMapper;
202
+ enumNamesInUse = /* @__PURE__ */ new Map();
203
+ };
193
204
  var generateEnumCached = (column, columnName, tableName) => {
194
- if (enumMap.has(column)) {
195
- return enumMap.get(column);
205
+ const declared = declaredEnum(column);
206
+ const values = column.enumValues;
207
+ const name = enumNameMapper?.({
208
+ enumName: declared?.enumName,
209
+ schema: declared?.schema,
210
+ tableName,
211
+ columnName,
212
+ values
213
+ }) ?? (declared ? `${pascalize(declared.enumName)}Enum` : `${capitalize(tableName)}${capitalize(columnName)}Enum`);
214
+ const valuesKey = enumValuesKey(values);
215
+ const claimed = enumNamesInUse.get(name);
216
+ if (claimed) {
217
+ if (claimed.valuesKey !== valuesKey) {
218
+ throw new Error(
219
+ `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.`
220
+ );
221
+ }
222
+ return claimed.type;
196
223
  }
197
224
  const gqlEnum = new import_graphql2.GraphQLEnumType({
198
- name: `${capitalize(tableName)}${capitalize(columnName)}Enum`,
225
+ name,
199
226
  values: Object.fromEntries(
200
- column.enumValues.map((e, index) => [
227
+ values.map((e, index) => [
201
228
  allowedNameChars.test(e) ? e : `Option${index}`,
202
229
  {
203
230
  value: e,
@@ -206,7 +233,7 @@ var generateEnumCached = (column, columnName, tableName) => {
206
233
  ])
207
234
  )
208
235
  });
209
- enumMap.set(column, gqlEnum);
236
+ enumNamesInUse.set(name, { type: gqlEnum, valuesKey });
210
237
  return gqlEnum;
211
238
  };
212
239
  var geoXyType = new import_graphql2.GraphQLObjectType({
@@ -227,14 +254,14 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
227
254
  const dimensions = column.dimensions;
228
255
  if (dimensions !== void 0 && dimensions > 0) {
229
256
  const inner = columnBaseToGraphQLCore(column, columnName, tableName, isInput);
230
- const innerDesc = inner.description ?? inner.type.name;
257
+ const innerLabel = inner.typeLabel ?? inner.type.name;
231
258
  let type = inner.type;
232
- let description = innerDesc;
259
+ let typeLabel = innerLabel;
233
260
  for (let i = 0; i < dimensions; i++) {
234
261
  type = new import_graphql2.GraphQLList(new import_graphql2.GraphQLNonNull(type));
235
- description = `Array<${description}>`;
262
+ typeLabel = `Array<${typeLabel}>`;
236
263
  }
237
- return { type, description };
264
+ return { type, typeLabel };
238
265
  }
239
266
  return columnBaseToGraphQLCore(column, columnName, tableName, isInput);
240
267
  };
@@ -242,51 +269,51 @@ var columnBaseToGraphQLCore = (column, columnName, tableName, isInput) => {
242
269
  const { type: baseType, constraint } = (0, import_drizzle_orm.extractExtendedColumnType)(column);
243
270
  switch (baseType) {
244
271
  case "boolean":
245
- return { type: import_graphql2.GraphQLBoolean, description: "Boolean" };
272
+ return { type: import_graphql2.GraphQLBoolean, typeLabel: "Boolean" };
246
273
  case "object":
247
274
  if (column instanceof import_pg_core.PgTimestamp || column instanceof import_pg_core.PgDate) {
248
- return { type: import_graphql_scalars.GraphQLDateTime, description: "DateTime" };
275
+ return { type: import_graphql_scalars.GraphQLDateTime, typeLabel: "DateTime" };
249
276
  }
250
277
  return column.columnType === "PgGeometryObject" ? {
251
278
  type: isInput ? geoXyInputType : geoXyType,
252
- description: "Geometry points XY"
279
+ typeLabel: "Geometry points XY"
253
280
  } : column.columnType === "PgBytea" ? {
254
281
  type: new import_graphql2.GraphQLList(new import_graphql2.GraphQLNonNull(import_graphql2.GraphQLInt)),
255
- description: "Buffer"
256
- } : { type: import_graphql_scalars.GraphQLJSON, description: "JSON" };
282
+ typeLabel: "Buffer"
283
+ } : { type: import_graphql_scalars.GraphQLJSON, typeLabel: "JSON" };
257
284
  case "string":
258
285
  if (column.enumValues?.length) {
259
286
  return { type: generateEnumCached(column, columnName, tableName) };
260
287
  }
261
288
  if (constraint === "numeric" && !column.dimensions) {
262
- return { type: GraphQLDecimalString, description: "Decimal" };
289
+ return { type: GraphQLDecimalString, typeLabel: "Decimal" };
263
290
  }
264
291
  if (column instanceof import_pg_core.PgTimestamp || column instanceof import_pg_core.PgTimestampString) {
265
- return { type: import_graphql_scalars.GraphQLDateTime, description: "DateTime" };
292
+ return { type: import_graphql_scalars.GraphQLDateTime, typeLabel: "DateTime" };
266
293
  }
267
294
  if (column instanceof import_pg_core.PgUUID) {
268
- return { type: import_graphql_scalars.GraphQLUUID, description: "UUID" };
295
+ return { type: import_graphql_scalars.GraphQLUUID, typeLabel: "UUID" };
269
296
  }
270
297
  if (column instanceof import_pg_core.PgDateString) {
271
- return isInput ? { type: import_graphql2.GraphQLString, description: "Date" } : { type: import_graphql_scalars.GraphQLDate, description: "Date" };
298
+ return isInput ? { type: import_graphql2.GraphQLString, typeLabel: "Date" } : { type: import_graphql_scalars.GraphQLDate, typeLabel: "Date" };
272
299
  }
273
- return { type: import_graphql2.GraphQLString, description: "String" };
300
+ return { type: import_graphql2.GraphQLString, typeLabel: "String" };
274
301
  case "bigint":
275
- return { type: GraphQLBigIntString, description: "BigInt" };
302
+ return { type: GraphQLBigIntString, typeLabel: "BigInt" };
276
303
  case "number": {
277
- return (0, import_drizzle_orm.is)(column, import_pg_core.PgInteger) || (0, import_drizzle_orm.is)(column, import_pg_core.PgSerial) || (0, import_drizzle_orm.is)(column, import_mysql_core.MySqlInt) || (0, import_drizzle_orm.is)(column, import_mysql_core.MySqlSerial) || (0, import_drizzle_orm.is)(column, import_sqlite_core.SQLiteInteger) ? { type: import_graphql2.GraphQLInt, description: "Integer" } : { type: import_graphql2.GraphQLFloat, description: "Float" };
304
+ return (0, import_drizzle_orm.is)(column, import_pg_core.PgInteger) || (0, import_drizzle_orm.is)(column, import_pg_core.PgSerial) || (0, import_drizzle_orm.is)(column, import_mysql_core.MySqlInt) || (0, import_drizzle_orm.is)(column, import_mysql_core.MySqlSerial) || (0, import_drizzle_orm.is)(column, import_sqlite_core.SQLiteInteger) ? { type: import_graphql2.GraphQLInt, typeLabel: "Integer" } : { type: import_graphql2.GraphQLFloat, typeLabel: "Float" };
278
305
  }
279
306
  case "array": {
280
307
  if (column.columnType === "PgVector") {
281
308
  return {
282
309
  type: new import_graphql2.GraphQLList(new import_graphql2.GraphQLNonNull(import_graphql2.GraphQLFloat)),
283
- description: "Array<Float>"
310
+ typeLabel: "Array<Float>"
284
311
  };
285
312
  }
286
313
  if (column.columnType === "PgGeometry") {
287
314
  return {
288
315
  type: new import_graphql2.GraphQLList(new import_graphql2.GraphQLNonNull(import_graphql2.GraphQLFloat)),
289
- description: "Tuple<[Float, Float]>"
316
+ typeLabel: "Tuple<[Float, Float]>"
290
317
  };
291
318
  }
292
319
  const innerType = columnToGraphQLCore(
@@ -297,7 +324,7 @@ var columnBaseToGraphQLCore = (column, columnName, tableName, isInput) => {
297
324
  );
298
325
  return {
299
326
  type: new import_graphql2.GraphQLList(new import_graphql2.GraphQLNonNull(innerType.type)),
300
- description: `Array<${innerType.description}>`
327
+ typeLabel: `Array<${innerType.typeLabel}>`
301
328
  };
302
329
  }
303
330
  default:
@@ -353,24 +380,14 @@ var registerScalarOverrides = (tables, config) => {
353
380
  };
354
381
  var drizzleColumnToGraphQLType = (column, columnName, tableName, forceNullable = false, defaultIsNullable = false, isInput = false) => {
355
382
  const override = getColumnScalarOverride(column, isInput);
356
- let typeDesc;
357
- if (override) {
358
- typeDesc = { type: override, description: override.name };
359
- } else {
360
- typeDesc = columnToGraphQLCore(column, columnName, tableName, isInput);
361
- const noDesc = ["string", "boolean", "number"];
362
- const { type: baseType } = (0, import_drizzle_orm.extractExtendedColumnType)(column);
363
- if (noDesc.find((e) => e === baseType)) {
364
- delete typeDesc.description;
365
- }
366
- }
383
+ const typeDesc = override ? { type: override, typeLabel: override.name } : columnToGraphQLCore(column, columnName, tableName, isInput);
367
384
  if (forceNullable) {
368
385
  return typeDesc;
369
386
  }
370
387
  if (column.notNull && !(defaultIsNullable && (column.hasDefault || column.defaultFn))) {
371
388
  return {
372
389
  type: new import_graphql2.GraphQLNonNull(typeDesc.type),
373
- description: typeDesc.description
390
+ typeLabel: typeDesc.typeLabel
374
391
  };
375
392
  }
376
393
  return typeDesc;
@@ -953,6 +970,22 @@ var createRelationResolverFactory = (db, tables, filterCtx) => ({ tableName, rel
953
970
  return loader.load(localValue);
954
971
  };
955
972
  };
973
+ var columnDocs = (docs, column, tableName, columnName) => {
974
+ const description = docs.describeColumn?.(column, { tableName, columnName });
975
+ const deprecationReason = docs.deprecateColumn?.(column, { tableName, columnName });
976
+ return {
977
+ ...description !== void 0 ? { description } : {},
978
+ ...deprecationReason !== void 0 ? { deprecationReason } : {}
979
+ };
980
+ };
981
+ var inputFieldDocs = (docs, column, tableName, columnName, fieldType) => {
982
+ const resolved = columnDocs(docs, column, tableName, columnName);
983
+ if (resolved.deprecationReason !== void 0 && fieldType instanceof import_graphql4.GraphQLNonNull) {
984
+ const { deprecationReason: _dropped, ...rest } = resolved;
985
+ return rest;
986
+ }
987
+ return resolved;
988
+ };
956
989
  var listFieldComplexity = (options) => ({ args, childComplexity }) => {
957
990
  const limit = args["limit"];
958
991
  const rows = typeof limit === "number" && limit > 0 ? limit : options.defaultListSize;
@@ -960,18 +993,21 @@ var listFieldComplexity = (options) => ({ args, childComplexity }) => {
960
993
  };
961
994
  var aggregateFieldComplexity = (options) => ({ childComplexity }) => options.aggregateCost + childComplexity;
962
995
  var AGGREGATE_FIELD_SUFFIX = "Aggregate";
963
- var relationAggregateJoinColumns = (tree, table, selectionCtx) => {
964
- const relations = selectionCtx?.relationMap[selectionCtx.tableName];
965
- if (!relations || !selectionCtx) {
996
+ var relationJoinColumns = (tree, table, selectionCtx) => {
997
+ if (!selectionCtx) {
998
+ return [];
999
+ }
1000
+ const relations = (selectionCtx.allRelations ?? selectionCtx.relationMap)[selectionCtx.tableName] ?? selectionCtx.relationMap[selectionCtx.tableName];
1001
+ if (!relations) {
966
1002
  return [];
967
1003
  }
968
1004
  const tableColumns = (0, import_drizzle_orm3.getColumns)(table);
969
1005
  const needed = [];
970
1006
  for (const fieldData of Object.values(tree)) {
971
- if (tableColumns[fieldData.name] || !fieldData.name.endsWith(AGGREGATE_FIELD_SUFFIX)) {
1007
+ if (tableColumns[fieldData.name]) {
972
1008
  continue;
973
1009
  }
974
- const relEntry = relations[fieldData.name.slice(0, -AGGREGATE_FIELD_SUFFIX.length)];
1010
+ const relEntry = fieldData.name.endsWith(AGGREGATE_FIELD_SUFFIX) ? relations[fieldData.name.slice(0, -AGGREGATE_FIELD_SUFFIX.length)] : relations[fieldData.name];
975
1011
  const targetTable = relEntry ? selectionCtx.tables[relEntry.targetTableName] : void 0;
976
1012
  if (!relEntry || !targetTable) {
977
1013
  continue;
@@ -993,7 +1029,7 @@ var extractSelectedColumnsFromTree = (tree, table, selectionCtx) => {
993
1029
  }
994
1030
  selectedColumns.push([fieldData.name, true]);
995
1031
  }
996
- for (const columnName of relationAggregateJoinColumns(tree, table, selectionCtx)) {
1032
+ for (const columnName of relationJoinColumns(tree, table, selectionCtx)) {
997
1033
  selectedColumns.push([columnName, true]);
998
1034
  }
999
1035
  if (!selectedColumns.length) {
@@ -1013,7 +1049,7 @@ var extractSelectedColumnsFromTreeSQLFormat = (tree, table, selectionCtx) => {
1013
1049
  }
1014
1050
  selectedColumns.push([fieldData.name, tableColumns[fieldData.name]]);
1015
1051
  }
1016
- for (const columnName of relationAggregateJoinColumns(tree, table, selectionCtx)) {
1052
+ for (const columnName of relationJoinColumns(tree, table, selectionCtx)) {
1017
1053
  selectedColumns.push([columnName, tableColumns[columnName]]);
1018
1054
  }
1019
1055
  if (!selectedColumns.length) {
@@ -1134,21 +1170,23 @@ var jsonFilterFields = (column, colType) => {
1134
1170
  isNotNull: { type: import_graphql4.GraphQLBoolean }
1135
1171
  };
1136
1172
  };
1137
- var arrayFilterFields = (colType, colArr, colDesc) => {
1173
+ var IN_ARRAY_DESCRIPTION = "Matches any one of these values (SQL `IN`)";
1174
+ var NOT_IN_ARRAY_DESCRIPTION = "Matches none of these values (SQL `NOT IN`)";
1175
+ var arrayFilterFields = (colType, colArr) => {
1138
1176
  let element = colType.ofType;
1139
1177
  if (element instanceof import_graphql4.GraphQLNonNull) {
1140
1178
  element = element.ofType;
1141
1179
  }
1142
1180
  const elementList = new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(element));
1143
1181
  return {
1144
- eq: { type: colType, description: colDesc },
1145
- ne: { type: colType, description: colDesc },
1182
+ eq: { type: colType, description: "The whole array equals this array" },
1183
+ ne: { type: colType, description: "The whole array differs from this array" },
1146
1184
  has: { type: element, description: "Array contains this element" },
1147
1185
  hasSome: { type: elementList, description: "Array contains at least one of these elements (overlap, `&&`)" },
1148
1186
  hasEvery: { type: elementList, description: "Array contains every one of these elements (containment, `@>`)" },
1149
1187
  isEmpty: { type: import_graphql4.GraphQLBoolean, description: "When true, matches arrays with no elements" },
1150
- inArray: { type: colArr, description: `Array<${colDesc}>` },
1151
- notInArray: { type: colArr, description: `Array<${colDesc}>` },
1188
+ inArray: { type: colArr, description: IN_ARRAY_DESCRIPTION },
1189
+ notInArray: { type: colArr, description: NOT_IN_ARRAY_DESCRIPTION },
1152
1190
  isNull: { type: import_graphql4.GraphQLBoolean },
1153
1191
  isNotNull: { type: import_graphql4.GraphQLBoolean }
1154
1192
  };
@@ -1184,18 +1222,17 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
1184
1222
  return cached;
1185
1223
  }
1186
1224
  const colType = columnGraphQLType.type;
1187
- const colDesc = columnGraphQLType.description;
1188
1225
  const colArr = new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(colType));
1189
1226
  const customOverrideFilter = inputOverride !== void 0 && !BUILTIN_FILTER_SCALARS.has(inputOverride);
1190
1227
  const underlying = (0, import_drizzle_orm3.extractExtendedColumnType)(column);
1191
1228
  const omitStringOps = customOverrideFilter ? underlying.type !== "string" || underlying.constraint === "numeric" : FILTERS_WITHOUT_STRING_OPS.has(genericName);
1192
- const baseFields = kind === "json" ? jsonFilterFields(column, colType) : kind === "array" ? arrayFilterFields(colType, colArr, colDesc) : {
1193
- eq: { type: colType, description: colDesc },
1194
- ne: { type: colType, description: colDesc },
1195
- lt: { type: colType, description: colDesc },
1196
- lte: { type: colType, description: colDesc },
1197
- gt: { type: colType, description: colDesc },
1198
- gte: { type: colType, description: colDesc },
1229
+ const baseFields = kind === "json" ? jsonFilterFields(column, colType) : kind === "array" ? arrayFilterFields(colType, colArr) : {
1230
+ eq: { type: colType, description: "Equal to" },
1231
+ ne: { type: colType, description: "Not equal to" },
1232
+ lt: { type: colType, description: "Less than" },
1233
+ lte: { type: colType, description: "Less than or equal to" },
1234
+ gt: { type: colType, description: "Greater than" },
1235
+ gte: { type: colType, description: "Greater than or equal to" },
1199
1236
  ...omitStringOps ? {} : {
1200
1237
  like: { type: import_graphql4.GraphQLString },
1201
1238
  notLike: { type: import_graphql4.GraphQLString },
@@ -1226,10 +1263,10 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
1226
1263
  description: "Case-insensitive `contains`."
1227
1264
  }
1228
1265
  },
1229
- inArray: { type: colArr, description: `Array<${colDesc}>` },
1230
- notInArray: { type: colArr, description: `Array<${colDesc}>` },
1231
- isNull: { type: import_graphql4.GraphQLBoolean },
1232
- isNotNull: { type: import_graphql4.GraphQLBoolean }
1266
+ inArray: { type: colArr, description: IN_ARRAY_DESCRIPTION },
1267
+ notInArray: { type: colArr, description: NOT_IN_ARRAY_DESCRIPTION },
1268
+ isNull: { type: import_graphql4.GraphQLBoolean, description: "When true, matches rows where the column is NULL" },
1269
+ isNotNull: { type: import_graphql4.GraphQLBoolean, description: "When true, matches rows where the column is not NULL" }
1233
1270
  };
1234
1271
  const mainType = new import_graphql4.GraphQLInputObjectType({
1235
1272
  name: `${genericName}Filter`,
@@ -1276,10 +1313,14 @@ var generateTableFilterValuesCached = (table, tableName, cacheCtx) => {
1276
1313
  const columns = (0, import_drizzle_orm3.getColumns)(table);
1277
1314
  const columnEntries = Object.entries(columns);
1278
1315
  const remapped = Object.fromEntries(
1279
- columnEntries.map(([columnName, columnDescription]) => [
1316
+ columnEntries.map(([columnName, column]) => [
1280
1317
  columnName,
1281
1318
  {
1282
- type: generateColumnFilterValues(columnDescription, tableName, columnName, cacheCtx)
1319
+ type: generateColumnFilterValues(column, tableName, columnName, cacheCtx),
1320
+ // A filter field is the same column, so it carries the same documentation. Deprecation
1321
+ // is not propagated: filtering on a deprecated column is how a caller finds the rows
1322
+ // that still use it.
1323
+ ...cacheCtx.docs.describeColumn ? { description: cacheCtx.docs.describeColumn(column, { tableName, columnName }) } : {}
1283
1324
  }
1284
1325
  ])
1285
1326
  );
@@ -1293,9 +1334,12 @@ var generateTableSelectTypeFieldsCached = (table, tableName, cacheCtx) => {
1293
1334
  const columns = (0, import_drizzle_orm3.getColumns)(table);
1294
1335
  const columnEntries = Object.entries(columns);
1295
1336
  const remapped = Object.fromEntries(
1296
- columnEntries.map(([columnName, columnDescription]) => [
1337
+ columnEntries.map(([columnName, column]) => [
1297
1338
  columnName,
1298
- drizzleColumnToGraphQLType(columnDescription, columnName, tableName)
1339
+ {
1340
+ ...drizzleColumnToGraphQLType(column, columnName, tableName),
1341
+ ...columnDocs(cacheCtx.docs, column, tableName, columnName)
1342
+ }
1299
1343
  ])
1300
1344
  );
1301
1345
  if (!remapped[CURSOR_FIELD_NAME]) {
@@ -1492,6 +1536,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1492
1536
  const typeName = resolveTypeName(tableName, typeNameMapper);
1493
1537
  const shell = new import_graphql4.GraphQLObjectType({
1494
1538
  name: typeName,
1539
+ description: cacheCtx.docs.describeTable?.(tableName),
1495
1540
  fields: () => ({ ...tableFields, ...container.fields })
1496
1541
  });
1497
1542
  cacheCtx.objectTypeCache.set(tableName, shell);
@@ -1533,11 +1578,14 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1533
1578
  const capturedTargetContainer = targetContainer;
1534
1579
  relType = new import_graphql4.GraphQLObjectType({
1535
1580
  name: resolveTypeName(targetTableName, typeNameMapper),
1581
+ description: cacheCtx.docs.describeTable?.(targetTableName),
1536
1582
  fields: () => ({ ...targetTableFields, ...capturedTargetContainer.fields })
1537
1583
  });
1538
1584
  cacheCtx.objectTypeCache.set(targetTableName, relType);
1539
1585
  }
1540
1586
  const resolve = resolverFactory?.({ tableName, relationName, relEntry, isOne });
1587
+ const relationDescription = cacheCtx.docs.describeRelation?.(tableName, relationName);
1588
+ const relationDocs = relationDescription !== void 0 ? { description: relationDescription } : {};
1541
1589
  if (isOne) {
1542
1590
  const isRequired = relation.optional === false;
1543
1591
  rawRelationFields.push([
@@ -1547,7 +1595,8 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1547
1595
  args: {
1548
1596
  where: { type: relSelectData.filters }
1549
1597
  },
1550
- resolve
1598
+ resolve,
1599
+ ...relationDocs
1551
1600
  }
1552
1601
  ]);
1553
1602
  continue;
@@ -1563,6 +1612,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1563
1612
  limit: { type: import_graphql4.GraphQLInt }
1564
1613
  },
1565
1614
  resolve,
1615
+ ...relationDocs,
1566
1616
  ...cacheCtx.complexity ? { extensions: { complexity: listFieldComplexity(cacheCtx.complexity) } } : {}
1567
1617
  }
1568
1618
  ]);
@@ -1610,7 +1660,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1610
1660
  relationFields: {}
1611
1661
  };
1612
1662
  };
1613
- var generateTableTypes = (tableName, tables, relationMap, withReturning, relationsDepthLimit, cacheCtx, typeNameMapper = void 0, insertPrefix = "create", updatePrefix = "update", resolverFactory, relationAggregateFactory) => {
1663
+ var generateTableTypes = (tableName, tables, relationMap, withReturning, relationsDepthLimit, cacheCtx, typeNameMapper = void 0, insertPrefix = "create", updatePrefix = "update", resolverFactory, relationAggregateFactory, nestedWrites) => {
1614
1664
  const { tableFields, relationFields, filters, order } = generateSelectFields(
1615
1665
  tables,
1616
1666
  tableName,
@@ -1631,28 +1681,44 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
1631
1681
  const table = tables[tableName];
1632
1682
  const columns = (0, import_drizzle_orm3.getColumns)(table);
1633
1683
  const columnEntries = Object.entries(columns);
1684
+ const relaxedColumns = nestedWrites?.relaxedColumns(tableName);
1634
1685
  const insertFields = Object.fromEntries(
1635
- columnEntries.map(([columnName, columnDescription]) => [
1636
- columnName,
1637
- drizzleColumnToGraphQLType(columnDescription, columnName, tableName, false, true, true)
1638
- ])
1686
+ columnEntries.map(([columnName, column]) => {
1687
+ const converted = drizzleColumnToGraphQLType(
1688
+ column,
1689
+ columnName,
1690
+ tableName,
1691
+ !!relaxedColumns?.has(columnName),
1692
+ true,
1693
+ true
1694
+ );
1695
+ return [
1696
+ columnName,
1697
+ { ...converted, ...inputFieldDocs(cacheCtx.docs, column, tableName, columnName, converted.type) }
1698
+ ];
1699
+ })
1639
1700
  );
1640
1701
  const updateFields = Object.fromEntries(
1641
- columnEntries.map(([columnName, columnDescription]) => [
1642
- columnName,
1643
- drizzleColumnToGraphQLType(columnDescription, columnName, tableName, true, false, true)
1644
- ])
1702
+ columnEntries.map(([columnName, column]) => {
1703
+ const converted = drizzleColumnToGraphQLType(column, columnName, tableName, true, false, true);
1704
+ return [
1705
+ columnName,
1706
+ { ...converted, ...inputFieldDocs(cacheCtx.docs, column, tableName, columnName, converted.type) }
1707
+ ];
1708
+ })
1645
1709
  );
1710
+ const typeName = resolveTypeName(tableName, typeNameMapper);
1646
1711
  const insertInput = new import_graphql4.GraphQLInputObjectType({
1647
- name: `${capitalize(insertPrefix)}${resolveTypeName(tableName, typeNameMapper)}Input`,
1648
- fields: insertFields
1712
+ name: `${capitalize(insertPrefix)}${typeName}Input`,
1713
+ fields: nestedWrites ? () => ({ ...insertFields, ...nestedWrites.createFields(tableName, typeName) }) : insertFields
1649
1714
  });
1650
1715
  const updateInput = new import_graphql4.GraphQLInputObjectType({
1651
- name: `${capitalize(updatePrefix)}${resolveTypeName(tableName, typeNameMapper)}Input`,
1652
- fields: updateFields
1716
+ name: `${capitalize(updatePrefix)}${typeName}Input`,
1717
+ fields: nestedWrites ? () => ({ ...updateFields, ...nestedWrites.updateFields(tableName, typeName) }) : updateFields
1653
1718
  });
1654
1719
  const selectSingleOutput = cacheCtx.objectTypeCache.get(tableName) ?? new import_graphql4.GraphQLObjectType({
1655
1720
  name: resolveTypeName(tableName, typeNameMapper),
1721
+ description: cacheCtx.docs.describeTable?.(tableName),
1656
1722
  fields: { ...tableFields, ...relationFields }
1657
1723
  });
1658
1724
  const selectArrOutput = new import_graphql4.GraphQLNonNull(new import_graphql4.GraphQLList(new import_graphql4.GraphQLNonNull(selectSingleOutput)));
@@ -2044,6 +2110,13 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
2044
2110
  if (!field) {
2045
2111
  continue;
2046
2112
  }
2113
+ const selectionCount = Object.values(baseField).reduce(
2114
+ (n, f) => n + (f.name === relName ? 1 : 0),
2115
+ 0
2116
+ );
2117
+ if (selectionCount > 1) {
2118
+ continue;
2119
+ }
2047
2120
  const relField = field?.fieldsByTypeName;
2048
2121
  const relFieldSelection = relField?.[relTypeName];
2049
2122
  if (!relFieldSelection) {
@@ -2052,7 +2125,8 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
2052
2125
  const columns = extractSelectedColumnsFromTree(relFieldSelection, tables[targetTableName], {
2053
2126
  tableName: targetTableName,
2054
2127
  relationMap,
2055
- tables
2128
+ tables,
2129
+ allRelations: filterCtx?.relationMap
2056
2130
  });
2057
2131
  const thisRecord = {};
2058
2132
  thisRecord.columns = columns;
@@ -2658,7 +2732,8 @@ var runRelationalSelect = async (opts) => {
2658
2732
  columns: extractSelectedColumnsFromTree(parsedInfo.fieldsByTypeName[typeName], table, {
2659
2733
  tableName,
2660
2734
  relationMap,
2661
- tables
2735
+ tables,
2736
+ allRelations: filterCtx?.relationMap
2662
2737
  }),
2663
2738
  offset: distinctKeys ? void 0 : offset,
2664
2739
  // drizzle-orm v1 RQB calls orderBy/where with the aliased table proxy — use it
@@ -2839,9 +2914,9 @@ var generateAggregateTypes = (table, tableName, typeName, cacheCtx) => {
2839
2914
  type: new import_graphql5.GraphQLObjectType({
2840
2915
  name: `${typeName}${capitalize(op)}Aggregate`,
2841
2916
  fields: Object.fromEntries(
2842
- Object.entries(orderable).map(([columnName, { converted }]) => [
2917
+ Object.entries(orderable).map(([columnName, { column, converted }]) => [
2843
2918
  columnName,
2844
- { type: converted.type, description: converted.description }
2919
+ { type: converted.type, ...columnDocs(cacheCtx?.docs ?? {}, column, tableName, columnName) }
2845
2920
  ])
2846
2921
  )
2847
2922
  })
@@ -2888,7 +2963,7 @@ var aggregateTarget = (table, tableName, typeName) => {
2888
2963
  typeName,
2889
2964
  columns: (0, import_drizzle_orm4.getColumns)(table),
2890
2965
  dateTimeColumns: new Set(
2891
- Object.entries(orderable).filter(([, { converted }]) => converted.description === "DateTime").map(([columnName]) => columnName)
2966
+ Object.entries(orderable).filter(([, { converted }]) => converted.typeLabel === "DateTime").map(([columnName]) => columnName)
2892
2967
  )
2893
2968
  };
2894
2969
  };
@@ -3106,9 +3181,9 @@ var generateGroupByType = (table, tableName, typeName, cacheCtx) => {
3106
3181
  name: `${typeName}GroupKeys`,
3107
3182
  description: `The grouped column values of one ${typeName} group. A column the query did not group by is null.`,
3108
3183
  fields: Object.fromEntries(
3109
- Object.entries(groupable).map(([columnName, { converted }]) => [
3184
+ Object.entries(groupable).map(([columnName, { column, converted }]) => [
3110
3185
  columnName,
3111
- { type: converted.type, description: converted.description }
3186
+ { type: converted.type, ...columnDocs(cacheCtx?.docs ?? {}, column, tableName, columnName) }
3112
3187
  ])
3113
3188
  )
3114
3189
  });
@@ -3508,7 +3583,13 @@ var generateSchemaData = (db, schema, relations, options) => {
3508
3583
  "Drizzle-GraphQL Error: No tables detected in Drizzle-ORM's database instance. Did you forget to pass schema to drizzle constructor?"
3509
3584
  );
3510
3585
  }
3586
+ if (features.nestedWrites) {
3587
+ throw new Error(
3588
+ "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."
3589
+ );
3590
+ }
3511
3591
  registerScalarOverrides(tables, options);
3592
+ registerEnumConfig(options);
3512
3593
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
3513
3594
  attachTargetPrimaryKeys(namedRelations, tables, mysqlPrimaryKeyPropNames);
3514
3595
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
@@ -3526,7 +3607,8 @@ var generateSchemaData = (db, schema, relations, options) => {
3526
3607
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
3527
3608
  listRelationFilterCache: /* @__PURE__ */ new Map(),
3528
3609
  aggregateTypeCache: /* @__PURE__ */ new Map(),
3529
- complexity
3610
+ complexity,
3611
+ docs: options.docs ?? {}
3530
3612
  };
3531
3613
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
3532
3614
  const queries = {};
@@ -3818,10 +3900,389 @@ var generateSchemaData = (db, schema, relations, options) => {
3818
3900
  };
3819
3901
 
3820
3902
  // src/util/builders/pg.ts
3821
- var import_drizzle_orm6 = require("drizzle-orm");
3903
+ var import_drizzle_orm7 = require("drizzle-orm");
3822
3904
  var import_pg_core2 = require("drizzle-orm/pg-core");
3823
- var import_graphql7 = require("graphql");
3905
+ var import_graphql8 = require("graphql");
3824
3906
  var import_graphql_parse_resolve_info3 = require("graphql-parse-resolve-info");
3907
+
3908
+ // src/util/builders/nested-writes.ts
3909
+ var import_drizzle_orm6 = require("drizzle-orm");
3910
+ var import_graphql7 = require("graphql");
3911
+ var isOptionalOnInsert = (column) => !column.notNull || !!column.hasDefault || !!column.defaultFn;
3912
+ var buildNestedWritePlans = (tables, relationMap, resolveUniqueSets, resolvePrimaryKeys, extractJoinColumns) => {
3913
+ const uniqueCache = /* @__PURE__ */ new Map();
3914
+ const singleColumnUniques = (tableName, table) => {
3915
+ let cached = uniqueCache.get(tableName);
3916
+ if (!cached) {
3917
+ cached = new Set(
3918
+ resolveUniqueSets(table).filter((set) => set.length === 1).map((set) => set[0])
3919
+ );
3920
+ uniqueCache.set(tableName, cached);
3921
+ }
3922
+ return cached;
3923
+ };
3924
+ const pkCache = /* @__PURE__ */ new Map();
3925
+ const singleColumnPk = (tableName, table) => {
3926
+ if (!pkCache.has(tableName)) {
3927
+ const pk = resolvePrimaryKeys(table);
3928
+ pkCache.set(tableName, pk.length === 1 ? pk[0] : void 0);
3929
+ }
3930
+ return pkCache.get(tableName);
3931
+ };
3932
+ const plans = {};
3933
+ for (const [tableName, relations] of Object.entries(relationMap)) {
3934
+ const table = tables[tableName];
3935
+ if (!table) {
3936
+ continue;
3937
+ }
3938
+ const tablePlans = {};
3939
+ for (const [relationName, relEntry] of Object.entries(relations)) {
3940
+ const relation = relEntry.relation;
3941
+ if (relation.through) {
3942
+ continue;
3943
+ }
3944
+ const targetTableName = relEntry.targetTableName;
3945
+ const targetTable = tables[targetTableName];
3946
+ if (!targetTable) {
3947
+ continue;
3948
+ }
3949
+ const joinColumns = extractJoinColumns(relEntry, table, targetTable);
3950
+ if (!joinColumns) {
3951
+ continue;
3952
+ }
3953
+ const { localColPropName, foreignCol, foreignColPropName } = joinColumns;
3954
+ const localCol = (0, import_drizzle_orm6.getColumns)(table)[localColPropName];
3955
+ if (!localCol) {
3956
+ continue;
3957
+ }
3958
+ const isOne = (0, import_drizzle_orm6.is)(relation, import_drizzle_orm6.One);
3959
+ const localIsPk = singleColumnPk(tableName, table) === localColPropName;
3960
+ const foreignIsPk = singleColumnPk(targetTableName, targetTable) === foreignColPropName;
3961
+ const localIsUnique = singleColumnUniques(tableName, table).has(localColPropName);
3962
+ const foreignIsUnique = singleColumnUniques(targetTableName, targetTable).has(foreignColPropName);
3963
+ let fkSide;
3964
+ if (!isOne) {
3965
+ fkSide = "child";
3966
+ } else if (foreignIsPk && !localIsPk) {
3967
+ fkSide = "parent";
3968
+ } else if (localIsPk) {
3969
+ fkSide = "child";
3970
+ } else if (foreignIsUnique) {
3971
+ fkSide = "parent";
3972
+ } else if (localIsUnique) {
3973
+ fkSide = "child";
3974
+ } else {
3975
+ continue;
3976
+ }
3977
+ const fkColumn = fkSide === "child" ? foreignCol : localCol;
3978
+ tablePlans[relationName] = {
3979
+ relationName,
3980
+ targetTableName,
3981
+ targetTable,
3982
+ localColPropName,
3983
+ foreignColPropName,
3984
+ foreignCol,
3985
+ localCol,
3986
+ isOne,
3987
+ fkSide,
3988
+ canDetach: !fkColumn.notNull
3989
+ };
3990
+ }
3991
+ if (Object.keys(tablePlans).length) {
3992
+ plans[tableName] = tablePlans;
3993
+ }
3994
+ }
3995
+ return plans;
3996
+ };
3997
+ var NO_COLUMNS = /* @__PURE__ */ new Set();
3998
+ var createNestedWriteTypes = (params) => {
3999
+ const { plans, cacheCtx, typeNameMapper, insertPrefix } = params;
4000
+ const wrapperCache = /* @__PURE__ */ new Map();
4001
+ const payloadCache = /* @__PURE__ */ new Map();
4002
+ const payloadType = (tableName, typeName, plan) => {
4003
+ const key = `${tableName}.${plan.relationName}`;
4004
+ const cached = payloadCache.get(key);
4005
+ if (cached) {
4006
+ return cached;
4007
+ }
4008
+ const omitted = plan.fkSide === "child" ? plan.foreignColPropName : void 0;
4009
+ const fields = Object.fromEntries(
4010
+ Object.entries((0, import_drizzle_orm6.getColumns)(plan.targetTable)).filter(([columnName]) => columnName !== omitted).map(([columnName, column]) => [
4011
+ columnName,
4012
+ drizzleColumnToGraphQLType(column, columnName, plan.targetTableName, false, true, true)
4013
+ ])
4014
+ );
4015
+ const type = new import_graphql7.GraphQLInputObjectType({
4016
+ name: `${capitalize(insertPrefix)}${typeName}${capitalize(plan.relationName)}Input`,
4017
+ 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.`,
4018
+ fields
4019
+ });
4020
+ payloadCache.set(key, type);
4021
+ return type;
4022
+ };
4023
+ const targetFilters = (plan) => cacheCtx.filterTypeCache.get(plan.targetTable);
4024
+ const listOf = (type) => new import_graphql7.GraphQLList(new import_graphql7.GraphQLNonNull(type));
4025
+ const wrapperType = (tableName, typeName, plan, forUpdate) => {
4026
+ const key = `${tableName}.${plan.relationName}.${forUpdate ? "update" : "create"}`;
4027
+ const cached = wrapperCache.get(key);
4028
+ if (cached) {
4029
+ return cached;
4030
+ }
4031
+ const filters = targetFilters(plan);
4032
+ const payload = payloadType(tableName, typeName, plan);
4033
+ const targetTypeName = resolveTypeName(plan.targetTableName, typeNameMapper);
4034
+ const fields = {};
4035
+ if (plan.isOne) {
4036
+ fields["create"] = { type: payload, description: `Insert a ${targetTypeName} row and attach it` };
4037
+ if (filters) {
4038
+ fields["connect"] = {
4039
+ type: filters,
4040
+ description: `Attach the existing ${targetTypeName} row this matches. Must match exactly one row.`
4041
+ };
4042
+ }
4043
+ if (forUpdate && plan.canDetach) {
4044
+ fields["disconnect"] = {
4045
+ type: import_graphql7.GraphQLBoolean,
4046
+ description: `Detach the currently attached ${targetTypeName} row, leaving it in place`
4047
+ };
4048
+ }
4049
+ } else {
4050
+ fields["create"] = { type: listOf(payload), description: `Insert these ${targetTypeName} rows and attach them` };
4051
+ if (filters) {
4052
+ fields["connect"] = {
4053
+ type: listOf(filters),
4054
+ description: `Attach every existing ${targetTypeName} row these match`
4055
+ };
4056
+ if (forUpdate && plan.canDetach) {
4057
+ fields["disconnect"] = {
4058
+ type: listOf(filters),
4059
+ description: `Detach every attached ${targetTypeName} row these match, leaving the rows in place`
4060
+ };
4061
+ fields["set"] = {
4062
+ type: listOf(filters),
4063
+ description: `Replace the whole set: detach everything attached, then attach every ${targetTypeName} row these match. Applied before \`disconnect\`, \`connect\` and \`create\`.`
4064
+ };
4065
+ }
4066
+ }
4067
+ }
4068
+ const type = new import_graphql7.GraphQLInputObjectType({
4069
+ name: `${typeName}${capitalize(plan.relationName)}Nested${forUpdate ? "Update" : "Create"}Input`,
4070
+ description: `Writes through ${typeName}.${plan.relationName}`,
4071
+ fields
4072
+ });
4073
+ wrapperCache.set(key, type);
4074
+ return type;
4075
+ };
4076
+ const relationFields = (tableName, typeName, forUpdate) => {
4077
+ const tablePlans = plans[tableName];
4078
+ if (!tablePlans) {
4079
+ return {};
4080
+ }
4081
+ return Object.fromEntries(
4082
+ Object.values(tablePlans).flatMap((plan) => {
4083
+ const wrapper = wrapperType(tableName, typeName, plan, forUpdate);
4084
+ return wrapper ? [[plan.relationName, { type: wrapper, description: `Writes through ${typeName}.${plan.relationName}` }]] : [];
4085
+ })
4086
+ );
4087
+ };
4088
+ return {
4089
+ createFields: (tableName, typeName) => relationFields(tableName, typeName, false),
4090
+ updateFields: (tableName, typeName) => relationFields(tableName, typeName, true),
4091
+ relaxedColumns: (tableName) => {
4092
+ const tablePlans = plans[tableName];
4093
+ if (!tablePlans) {
4094
+ return NO_COLUMNS;
4095
+ }
4096
+ const relaxed = /* @__PURE__ */ new Set();
4097
+ for (const plan of Object.values(tablePlans)) {
4098
+ if (plan.fkSide === "parent" && !isOptionalOnInsert(plan.localCol)) {
4099
+ relaxed.add(plan.localColPropName);
4100
+ }
4101
+ }
4102
+ return relaxed.size ? relaxed : NO_COLUMNS;
4103
+ }
4104
+ };
4105
+ };
4106
+ var mergedOps = (entries) => Object.assign({}, ...entries.map((entry) => entry.ops));
4107
+ var asArray = (value) => Array.isArray(value) ? value : value === void 0 ? [] : [value];
4108
+ var createNestedWriteRuntime = (params) => {
4109
+ const { plans, filterCtx } = params;
4110
+ const conditionOf = (plan, filter, operation) => {
4111
+ const condition = extractFilters(
4112
+ plan.targetTable,
4113
+ plan.targetTableName,
4114
+ filter,
4115
+ relationFilterCtx(filterCtx, plan.targetTableName)
4116
+ );
4117
+ if (!condition) {
4118
+ throw new import_graphql7.GraphQLError(
4119
+ `Drizzle-GraphQL Error: '${operation}' on '${plan.relationName}' needs a filter that selects rows \u2014 it was given one that matches everything.`
4120
+ );
4121
+ }
4122
+ return condition;
4123
+ };
4124
+ const assertSingleOperation = (plan, op) => {
4125
+ const supplied = ["create", "connect", "disconnect"].filter((key) => op[key] !== void 0 && op[key] !== null);
4126
+ if (supplied.length > 1) {
4127
+ throw new import_graphql7.GraphQLError(
4128
+ `Drizzle-GraphQL Error: '${plan.relationName}' takes one of ${supplied.join(", ")} at a time \u2014 it holds a single row.`
4129
+ );
4130
+ }
4131
+ };
4132
+ const detachAll = async (executor, plan, key) => executor.update(plan.targetTable).set({ [plan.foreignColPropName]: null }).where((0, import_drizzle_orm6.eq)(plan.foreignCol, key));
4133
+ return {
4134
+ enabled: (tableName) => !!plans[tableName],
4135
+ split: (tableName, values) => {
4136
+ const tablePlans = plans[tableName];
4137
+ if (!tablePlans) {
4138
+ return { columns: values, ops: {} };
4139
+ }
4140
+ const columns = {};
4141
+ const ops = {};
4142
+ for (const [key, value] of Object.entries(values)) {
4143
+ if (tablePlans[key] && value !== void 0 && value !== null) {
4144
+ ops[key] = value;
4145
+ } else if (!tablePlans[key]) {
4146
+ columns[key] = value;
4147
+ }
4148
+ }
4149
+ return { columns, ops };
4150
+ },
4151
+ hasOps: (ops) => Object.keys(ops).length > 0,
4152
+ withJoinColumns: (tableName, ops, columns, table) => {
4153
+ const tablePlans = plans[tableName];
4154
+ if (!tablePlans) {
4155
+ return columns;
4156
+ }
4157
+ const allColumns = (0, import_drizzle_orm6.getColumns)(table);
4158
+ for (const relationName of Object.keys(ops)) {
4159
+ const plan = tablePlans[relationName];
4160
+ if (plan?.fkSide === "child" && !(plan.localColPropName in columns) && allColumns[plan.localColPropName]) {
4161
+ columns[plan.localColPropName] = allColumns[plan.localColPropName];
4162
+ }
4163
+ }
4164
+ return columns;
4165
+ },
4166
+ applyParentSide: async (executor, tableName, ops) => {
4167
+ const tablePlans = plans[tableName];
4168
+ const patch = {};
4169
+ if (!tablePlans) {
4170
+ return patch;
4171
+ }
4172
+ for (const [relationName, op] of Object.entries(ops)) {
4173
+ const plan = tablePlans[relationName];
4174
+ if (!plan || plan.fkSide !== "parent") {
4175
+ continue;
4176
+ }
4177
+ assertSingleOperation(plan, op);
4178
+ if (op["create"] !== void 0) {
4179
+ const values = remapFromGraphQLSingleInput({ ...op["create"] }, plan.targetTable);
4180
+ const inserted = await executor.insert(plan.targetTable).values(values).returning();
4181
+ const created = inserted[0];
4182
+ if (!created) {
4183
+ throw new import_graphql7.GraphQLError(
4184
+ `Drizzle-GraphQL Error: 'create' on '${relationName}' inserted no row, so there is nothing to attach.`
4185
+ );
4186
+ }
4187
+ patch[plan.localColPropName] = created[plan.foreignColPropName];
4188
+ } else if (op["connect"] !== void 0) {
4189
+ const rows = await executor.select().from(plan.targetTable).where(conditionOf(plan, op["connect"], "connect"));
4190
+ if (rows.length !== 1) {
4191
+ throw new import_graphql7.GraphQLError(
4192
+ `Drizzle-GraphQL Error: 'connect' on '${relationName}' matched ${rows.length} rows \u2014 it attaches a single row, so its filter must match exactly one.`
4193
+ );
4194
+ }
4195
+ patch[plan.localColPropName] = rows[0][plan.foreignColPropName];
4196
+ } else if (op["disconnect"] === true) {
4197
+ patch[plan.localColPropName] = null;
4198
+ }
4199
+ }
4200
+ return patch;
4201
+ },
4202
+ applyChildSide: async (executor, tableName, ops, parentRows) => {
4203
+ const tablePlans = plans[tableName];
4204
+ if (!tablePlans) {
4205
+ return;
4206
+ }
4207
+ for (const [relationName, op] of Object.entries(ops)) {
4208
+ const plan = tablePlans[relationName];
4209
+ if (!plan || plan.fkSide !== "child") {
4210
+ continue;
4211
+ }
4212
+ if (plan.isOne) {
4213
+ assertSingleOperation(plan, op);
4214
+ }
4215
+ for (const parentRow of parentRows) {
4216
+ const key = parentRow?.[plan.localColPropName];
4217
+ if (key === void 0 || key === null) {
4218
+ throw new import_graphql7.GraphQLError(
4219
+ `Drizzle-GraphQL Error: cannot write through '${relationName}': the ${tableName} row has no '${plan.localColPropName}' value to attach to.`
4220
+ );
4221
+ }
4222
+ if (op["set"] !== void 0) {
4223
+ await detachAll(executor, plan, key);
4224
+ for (const filter of asArray(op["set"])) {
4225
+ await executor.update(plan.targetTable).set({ [plan.foreignColPropName]: key }).where(conditionOf(plan, filter, "set"));
4226
+ }
4227
+ }
4228
+ if (op["disconnect"] !== void 0) {
4229
+ if (plan.isOne) {
4230
+ if (op["disconnect"] === true) {
4231
+ await detachAll(executor, plan, key);
4232
+ }
4233
+ } else {
4234
+ for (const filter of asArray(op["disconnect"])) {
4235
+ await executor.update(plan.targetTable).set({ [plan.foreignColPropName]: null }).where((0, import_drizzle_orm6.and)((0, import_drizzle_orm6.eq)(plan.foreignCol, key), conditionOf(plan, filter, "disconnect")));
4236
+ }
4237
+ }
4238
+ }
4239
+ const attaches = op["connect"] !== void 0 || op["create"] !== void 0;
4240
+ if (plan.isOne && attaches && plan.canDetach && op["set"] === void 0) {
4241
+ await detachAll(executor, plan, key);
4242
+ }
4243
+ if (op["connect"] !== void 0) {
4244
+ for (const filter of asArray(op["connect"])) {
4245
+ await executor.update(plan.targetTable).set({ [plan.foreignColPropName]: key }).where(conditionOf(plan, filter, "connect"));
4246
+ }
4247
+ }
4248
+ if (op["create"] !== void 0) {
4249
+ const rows = asArray(op["create"]).map((row) => ({
4250
+ ...remapFromGraphQLSingleInput({ ...row }, plan.targetTable),
4251
+ [plan.foreignColPropName]: key
4252
+ }));
4253
+ if (rows.length) {
4254
+ await executor.insert(plan.targetTable).values(rows);
4255
+ }
4256
+ }
4257
+ }
4258
+ }
4259
+ }
4260
+ };
4261
+ };
4262
+ var writeWithNestedOps = async (params) => {
4263
+ const { executor, runtime, tableName, entries, remapValues, write } = params;
4264
+ return executor.transaction(async (tx) => {
4265
+ const rows = [];
4266
+ for (const entry of entries) {
4267
+ const patch = await runtime.applyParentSide(tx, tableName, entry.ops);
4268
+ const written = await write(tx, { ...remapValues(entry.columns), ...patch });
4269
+ await runtime.applyChildSide(tx, tableName, entry.ops, written);
4270
+ rows.push(...written);
4271
+ }
4272
+ return rows;
4273
+ });
4274
+ };
4275
+ var updateWithNestedOps = async (params) => {
4276
+ const { executor, runtime, tableName, columns, ops, remapValues, write } = params;
4277
+ return executor.transaction(async (tx) => {
4278
+ const patch = await runtime.applyParentSide(tx, tableName, ops);
4279
+ const rows = await write(tx, { ...remapValues(columns), ...patch });
4280
+ await runtime.applyChildSide(tx, tableName, ops, rows);
4281
+ return rows;
4282
+ });
4283
+ };
4284
+
4285
+ // src/util/builders/pg.ts
3825
4286
  var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
3826
4287
  const queryBase = db.query[tableName];
3827
4288
  const table = tables[tableName];
@@ -3866,24 +4327,24 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
3866
4327
  let cursorEntries;
3867
4328
  if (after != null || cursorSelected) {
3868
4329
  if (after != null && distinct?.length) {
3869
- throw new import_graphql7.GraphQLError("'after' cannot be combined with 'distinct'.");
4330
+ throw new import_graphql8.GraphQLError("'after' cannot be combined with 'distinct'.");
3870
4331
  }
3871
4332
  if (orderByHasRelationEntry(orderBy)) {
3872
4333
  if (after != null) {
3873
- throw new import_graphql7.GraphQLError(
4334
+ throw new import_graphql8.GraphQLError(
3874
4335
  "'after' cannot be combined with an orderBy that orders through a relation \u2014 a related row's value cannot be encoded into a cursor."
3875
4336
  );
3876
4337
  }
3877
4338
  } else if (!pkNames.length) {
3878
4339
  if (after != null) {
3879
- throw new import_graphql7.GraphQLError(
4340
+ throw new import_graphql8.GraphQLError(
3880
4341
  `Table ${tableName} has no primary key, so cursor pagination cannot be used on it.`
3881
4342
  );
3882
4343
  }
3883
4344
  } else {
3884
4345
  cursorEntries = cursorOrderingEntries(orderBy, pkNames);
3885
4346
  if (cursorSelected) {
3886
- const allColumns = (0, import_drizzle_orm6.getColumns)(table);
4347
+ const allColumns = (0, import_drizzle_orm7.getColumns)(table);
3887
4348
  for (const [column] of cursorEntries) {
3888
4349
  selectedColumnsSql[column] ??= allColumns[column];
3889
4350
  }
@@ -3892,7 +4353,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
3892
4353
  }
3893
4354
  const cursorCondition = after != null && cursorEntries ? buildCursorCondition(table, cursorEntries, decodeCursor(after, cursorEntries), "nulls-largest") : void 0;
3894
4355
  const baseWhereSql = where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0;
3895
- const whereSql = cursorCondition ? (0, import_drizzle_orm6.and)(baseWhereSql, cursorCondition) : baseWhereSql;
4356
+ const whereSql = cursorCondition ? (0, import_drizzle_orm7.and)(baseWhereSql, cursorCondition) : baseWhereSql;
3896
4357
  let distinctKeys;
3897
4358
  if (distinct?.length) {
3898
4359
  distinctKeys = await selectDistinctKeys({
@@ -4003,10 +4464,10 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
4003
4464
  };
4004
4465
  };
4005
4466
  var pgPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, import_pg_core2.getTableConfig);
4006
- var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
4467
+ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4007
4468
  const queryArgs = {
4008
4469
  values: {
4009
- type: new import_graphql7.GraphQLNonNull(new import_graphql7.GraphQLList(new import_graphql7.GraphQLNonNull(baseType)))
4470
+ type: new import_graphql8.GraphQLNonNull(new import_graphql8.GraphQLList(new import_graphql8.GraphQLNonNull(baseType)))
4010
4471
  }
4011
4472
  };
4012
4473
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4015,10 +4476,12 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
4015
4476
  resolver: async (_source, args, context, info) => {
4016
4477
  try {
4017
4478
  return await runMutation(db, context, info, txCtx, async (executor) => {
4018
- const input = remapFromGraphQLArrayInput(args.values, table);
4019
- if (!input.length) {
4020
- throw new import_graphql7.GraphQLError("No values were provided!");
4479
+ if (!args.values.length) {
4480
+ throw new import_graphql8.GraphQLError("No values were provided!");
4021
4481
  }
4482
+ const entries = nested?.enabled(tableName) ? args.values.map((values) => nested.split(tableName, values)) : void 0;
4483
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
4484
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : args.values, table);
4022
4485
  const parsedInfo = (0, import_graphql_parse_resolve_info3.parseResolveInfo)(info, {
4023
4486
  deep: true
4024
4487
  });
@@ -4032,11 +4495,22 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
4032
4495
  pkNames,
4033
4496
  parsedInfo
4034
4497
  });
4035
- let query = executor.insert(table).values(input).returning(columns);
4036
- if (conflictDoNothing) {
4037
- query = query.onConflictDoNothing();
4038
- }
4039
- const result = await query;
4498
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
4499
+ const runInsert = async (target, values) => {
4500
+ let query = target.insert(table).values(values).returning(returning);
4501
+ if (conflictDoNothing) {
4502
+ query = query.onConflictDoNothing();
4503
+ }
4504
+ return await query;
4505
+ };
4506
+ const result = nestedEntries ? await writeWithNestedOps({
4507
+ executor,
4508
+ runtime: nested,
4509
+ tableName,
4510
+ entries: nestedEntries,
4511
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
4512
+ write: (tx, values) => runInsert(tx, [values])
4513
+ }) : await runInsert(executor, input);
4040
4514
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
4041
4515
  return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
4042
4516
  });
@@ -4047,10 +4521,10 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
4047
4521
  args: queryArgs
4048
4522
  };
4049
4523
  };
4050
- var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
4524
+ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4051
4525
  const queryArgs = {
4052
4526
  values: {
4053
- type: new import_graphql7.GraphQLNonNull(baseType)
4527
+ type: new import_graphql8.GraphQLNonNull(baseType)
4054
4528
  }
4055
4529
  };
4056
4530
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4059,7 +4533,9 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
4059
4533
  resolver: async (_source, args, context, info) => {
4060
4534
  try {
4061
4535
  return await runMutation(db, context, info, txCtx, async (executor) => {
4062
- const input = remapFromGraphQLSingleInput(args.values, table);
4536
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, args.values) : void 0;
4537
+ const nestedEntry = entry && nested.hasOps(entry.ops) ? entry : void 0;
4538
+ const input = nestedEntry ? {} : remapFromGraphQLSingleInput(entry ? entry.columns : args.values, table);
4063
4539
  const parsedInfo = (0, import_graphql_parse_resolve_info3.parseResolveInfo)(info, {
4064
4540
  deep: true
4065
4541
  });
@@ -4073,11 +4549,22 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
4073
4549
  pkNames,
4074
4550
  parsedInfo
4075
4551
  });
4076
- let query = executor.insert(table).values(input).returning(columns);
4077
- if (conflictDoNothing) {
4078
- query = query.onConflictDoNothing();
4079
- }
4080
- const result = await query;
4552
+ const returning = nestedEntry ? nested.withJoinColumns(tableName, nestedEntry.ops, { ...columns }, table) : columns;
4553
+ const runInsert = async (target, values) => {
4554
+ let query = target.insert(table).values(values).returning(returning);
4555
+ if (conflictDoNothing) {
4556
+ query = query.onConflictDoNothing();
4557
+ }
4558
+ return await query;
4559
+ };
4560
+ const result = nestedEntry ? await writeWithNestedOps({
4561
+ executor,
4562
+ runtime: nested,
4563
+ tableName,
4564
+ entries: [nestedEntry],
4565
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
4566
+ write: runInsert
4567
+ }) : await runInsert(executor, input);
4081
4568
  if (!result[0]) {
4082
4569
  return void 0;
4083
4570
  }
@@ -4091,10 +4578,10 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
4091
4578
  args: queryArgs
4092
4579
  };
4093
4580
  };
4094
- var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx) => {
4581
+ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx, nested) => {
4095
4582
  const queryArgs = {
4096
4583
  values: {
4097
- type: single ? new import_graphql7.GraphQLNonNull(baseType) : new import_graphql7.GraphQLNonNull(new import_graphql7.GraphQLList(new import_graphql7.GraphQLNonNull(baseType)))
4584
+ type: single ? new import_graphql8.GraphQLNonNull(baseType) : new import_graphql8.GraphQLNonNull(new import_graphql8.GraphQLList(new import_graphql8.GraphQLNonNull(baseType)))
4098
4585
  },
4099
4586
  onConflict: {
4100
4587
  type: onConflictType,
@@ -4107,10 +4594,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
4107
4594
  resolver: async (_source, args, context, info) => {
4108
4595
  try {
4109
4596
  return await runMutation(db, context, info, txCtx, async (executor) => {
4110
- const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
4111
- if (!input.length) {
4112
- throw new import_graphql7.GraphQLError("No values were provided!");
4597
+ const supplied = single ? [args.values] : args.values;
4598
+ if (!supplied.length) {
4599
+ throw new import_graphql8.GraphQLError("No values were provided!");
4113
4600
  }
4601
+ const entries = nested?.enabled(tableName) ? supplied.map((values) => nested.split(tableName, values)) : void 0;
4602
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
4603
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : supplied, table);
4114
4604
  const parsedInfo = (0, import_graphql_parse_resolve_info3.parseResolveInfo)(info, { deep: true });
4115
4605
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
4116
4606
  relationMap,
@@ -4122,19 +4612,30 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
4122
4612
  pkNames,
4123
4613
  parsedInfo
4124
4614
  });
4125
- const plan = resolveConflictPlan({
4126
- table,
4127
- values: input,
4128
- onConflict: args.onConflict,
4129
- pkNames,
4130
- uniqueSets,
4131
- excludedRef: excludedColumnRef,
4132
- withTarget: true,
4133
- buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
4134
- });
4135
- let query = executor.insert(table).values(input).returning(columns);
4136
- query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
4137
- const result = await query;
4615
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
4616
+ const runUpsert = async (target, values) => {
4617
+ const plan = resolveConflictPlan({
4618
+ table,
4619
+ values,
4620
+ onConflict: args.onConflict,
4621
+ pkNames,
4622
+ uniqueSets,
4623
+ excludedRef: excludedColumnRef,
4624
+ withTarget: true,
4625
+ buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
4626
+ });
4627
+ let query = target.insert(table).values(values).returning(returning);
4628
+ query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
4629
+ return await query;
4630
+ };
4631
+ const result = nestedEntries ? await writeWithNestedOps({
4632
+ executor,
4633
+ runtime: nested,
4634
+ tableName,
4635
+ entries: nestedEntries,
4636
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
4637
+ write: (tx, values) => runUpsert(tx, [values])
4638
+ }) : await runUpsert(executor, input);
4138
4639
  if (single && !result[0]) {
4139
4640
  return void 0;
4140
4641
  }
@@ -4148,13 +4649,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
4148
4649
  args: queryArgs
4149
4650
  };
4150
4651
  };
4151
- var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx) => {
4652
+ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx, nested) => {
4152
4653
  const queryArgs = {
4153
4654
  set: {
4154
- type: new import_graphql7.GraphQLNonNull(setArgs)
4655
+ type: new import_graphql8.GraphQLNonNull(setArgs)
4155
4656
  },
4156
4657
  where: {
4157
- type: single || requireWhere ? new import_graphql7.GraphQLNonNull(filterArgs) : filterArgs
4658
+ type: single || requireWhere ? new import_graphql8.GraphQLNonNull(filterArgs) : filterArgs
4158
4659
  }
4159
4660
  };
4160
4661
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4177,23 +4678,37 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
4177
4678
  pkNames,
4178
4679
  parsedInfo
4179
4680
  });
4180
- const input = remapFromGraphQLSingleInput(set, table);
4181
- if (!Object.keys(input).length) {
4182
- throw new import_graphql7.GraphQLError("Unable to update with no values specified!");
4681
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
4682
+ const nestedOps = entry && nested.hasOps(entry.ops) ? entry.ops : void 0;
4683
+ const input = remapFromGraphQLSingleInput(entry ? entry.columns : set, table);
4684
+ if (!Object.keys(input).length && !nestedOps) {
4685
+ throw new import_graphql8.GraphQLError("Unable to update with no values specified!");
4183
4686
  }
4184
4687
  const relationCtx = relationFilterCtx(filterCtx, tableName);
4185
4688
  const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
4186
4689
  if (single) {
4187
4690
  await assertSingleMatch(executor, table, filters, fieldName);
4188
4691
  }
4189
- let query = executor.update(table).set(input);
4190
- if (filters) {
4191
- query = query.where(filters);
4192
- }
4193
- query = query.returning(columns);
4194
- const result = await query;
4692
+ const returning = nestedOps ? nested.withJoinColumns(tableName, nestedOps, { ...columns }, table) : columns;
4693
+ const runUpdate = async (target, values) => {
4694
+ const writes = Object.keys(values).length > 0;
4695
+ let query = writes ? target.update(table).set(values) : target.select(returning).from(table);
4696
+ if (filters) {
4697
+ query = query.where(filters);
4698
+ }
4699
+ return await (writes ? query.returning(returning) : query);
4700
+ };
4701
+ const result = nestedOps ? await updateWithNestedOps({
4702
+ executor,
4703
+ runtime: nested,
4704
+ tableName,
4705
+ columns: input,
4706
+ ops: nestedOps,
4707
+ remapValues: (values) => values,
4708
+ write: runUpdate
4709
+ }) : await runUpdate(executor, input);
4195
4710
  if (single && result.length > 1) {
4196
- throw new import_graphql7.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
4711
+ throw new import_graphql8.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
4197
4712
  }
4198
4713
  if (single && !result[0]) {
4199
4714
  return void 0;
@@ -4208,10 +4723,10 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
4208
4723
  args: queryArgs
4209
4724
  };
4210
4725
  };
4211
- var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx) => {
4726
+ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx, nested) => {
4212
4727
  const queryArgs = {
4213
4728
  updates: {
4214
- type: new import_graphql7.GraphQLNonNull(new import_graphql7.GraphQLList(new import_graphql7.GraphQLNonNull(updateManyInput)))
4729
+ type: new import_graphql8.GraphQLNonNull(new import_graphql8.GraphQLList(new import_graphql8.GraphQLNonNull(updateManyInput)))
4215
4730
  }
4216
4731
  };
4217
4732
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4222,7 +4737,7 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
4222
4737
  return await runMutation(db, context, info, txCtx, async (executor) => {
4223
4738
  const { updates } = args;
4224
4739
  if (!updates.length) {
4225
- throw new import_graphql7.GraphQLError("No updates were provided!");
4740
+ throw new import_graphql8.GraphQLError("No updates were provided!");
4226
4741
  }
4227
4742
  const parsedInfo = (0, import_graphql_parse_resolve_info3.parseResolveInfo)(info, {
4228
4743
  deep: true
@@ -4238,23 +4753,40 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
4238
4753
  parsedInfo
4239
4754
  });
4240
4755
  const entries = updates.map(({ where, set }) => {
4241
- const input = remapFromGraphQLSingleInput(set, table);
4242
- if (!Object.keys(input).length) {
4243
- throw new import_graphql7.GraphQLError("Unable to update with no values specified!");
4756
+ const split = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
4757
+ const ops = split && nested.hasOps(split.ops) ? split.ops : void 0;
4758
+ const input = remapFromGraphQLSingleInput(split ? split.columns : set, table);
4759
+ if (!Object.keys(input).length && !ops) {
4760
+ throw new import_graphql8.GraphQLError("Unable to update with no values specified!");
4244
4761
  }
4245
4762
  return {
4246
4763
  set: input,
4764
+ ops,
4247
4765
  filters: where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
4248
4766
  };
4249
4767
  });
4768
+ const returning = entries.some((entry) => entry.ops) ? nested.withJoinColumns(
4769
+ tableName,
4770
+ mergedOps(entries.map((entry) => ({ ops: entry.ops ?? {} }))),
4771
+ {
4772
+ ...columns
4773
+ },
4774
+ table
4775
+ ) : columns;
4250
4776
  const perEntry = await executor.transaction(async (tx) => {
4251
4777
  const results = [];
4252
4778
  for (const entry of entries) {
4253
- let query = tx.update(table).set(entry.set);
4779
+ const values = entry.ops ? { ...entry.set, ...await nested.applyParentSide(tx, tableName, entry.ops) } : entry.set;
4780
+ const writes = Object.keys(values).length > 0;
4781
+ let query = writes ? tx.update(table).set(values) : tx.select(returning).from(table);
4254
4782
  if (entry.filters) {
4255
4783
  query = query.where(entry.filters);
4256
4784
  }
4257
- results.push(await query.returning(columns));
4785
+ const rows = await (writes ? query.returning(returning) : query);
4786
+ if (entry.ops) {
4787
+ await nested.applyChildSide(tx, tableName, entry.ops, rows);
4788
+ }
4789
+ results.push(rows);
4258
4790
  }
4259
4791
  return results;
4260
4792
  });
@@ -4284,7 +4816,7 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
4284
4816
  var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx) => {
4285
4817
  const queryArgs = {
4286
4818
  where: {
4287
- type: single || requireWhere ? new import_graphql7.GraphQLNonNull(filterArgs) : filterArgs
4819
+ type: single || requireWhere ? new import_graphql8.GraphQLNonNull(filterArgs) : filterArgs
4288
4820
  }
4289
4821
  };
4290
4822
  return {
@@ -4313,7 +4845,7 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, si
4313
4845
  query = query.returning(columns);
4314
4846
  const result = await query;
4315
4847
  if (single && result.length > 1) {
4316
- throw new import_graphql7.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
4848
+ throw new import_graphql8.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
4317
4849
  }
4318
4850
  if (single) {
4319
4851
  return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
@@ -4339,7 +4871,7 @@ function generateSchemaData2(db, schema, relations, options) {
4339
4871
  complexity
4340
4872
  } = options;
4341
4873
  const schemaEntries = Object.entries(schema);
4342
- const tableEntries = schemaEntries.filter(([_key, value]) => (0, import_drizzle_orm6.is)(value, import_pg_core2.PgTable));
4874
+ const tableEntries = schemaEntries.filter(([_key, value]) => (0, import_drizzle_orm7.is)(value, import_pg_core2.PgTable));
4343
4875
  const tables = Object.fromEntries(tableEntries);
4344
4876
  if (!tableEntries.length) {
4345
4877
  throw new Error(
@@ -4347,6 +4879,7 @@ function generateSchemaData2(db, schema, relations, options) {
4347
4879
  );
4348
4880
  }
4349
4881
  registerScalarOverrides(tables, options);
4882
+ registerEnumConfig(options);
4350
4883
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
4351
4884
  attachTargetPrimaryKeys(namedRelations, tables, pgPrimaryKeyPropNames);
4352
4885
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
@@ -4364,8 +4897,18 @@ function generateSchemaData2(db, schema, relations, options) {
4364
4897
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
4365
4898
  listRelationFilterCache: /* @__PURE__ */ new Map(),
4366
4899
  aggregateTypeCache: /* @__PURE__ */ new Map(),
4367
- complexity
4900
+ complexity,
4901
+ docs: options.docs ?? {}
4368
4902
  };
4903
+ const nestedPlans = features.nestedWrites ? buildNestedWritePlans(
4904
+ tables,
4905
+ namedRelations,
4906
+ (target) => getUniqueColumnSets(target, import_pg_core2.getTableConfig),
4907
+ (target) => pgPrimaryKeyPropNames(target),
4908
+ extractRelationJoinColumns
4909
+ ) : void 0;
4910
+ const nestedTypes = nestedPlans ? createNestedWriteTypes({ plans: nestedPlans, cacheCtx, typeNameMapper, insertPrefix: prefixes.insert }) : void 0;
4911
+ const nestedRuntime = nestedPlans ? createNestedWriteRuntime({ plans: nestedPlans, filterCtx }) : void 0;
4369
4912
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
4370
4913
  const queries = {};
4371
4914
  const mutations = {};
@@ -4384,7 +4927,8 @@ function generateSchemaData2(db, schema, relations, options) {
4384
4927
  prefixes.insert,
4385
4928
  prefixes.update,
4386
4929
  resolverFactory,
4387
- relationAggregateFactory
4930
+ relationAggregateFactory,
4931
+ nestedTypes
4388
4932
  )
4389
4933
  ])
4390
4934
  );
@@ -4445,7 +4989,8 @@ function generateSchemaData2(db, schema, relations, options) {
4445
4989
  typeName,
4446
4990
  typeNameMapper,
4447
4991
  conflictDoNothing,
4448
- mutationTxCtx
4992
+ mutationTxCtx,
4993
+ nestedRuntime
4449
4994
  ) : void 0;
4450
4995
  const insertSingleGenerated = features.insert ? generateInsertSingle2(
4451
4996
  db,
@@ -4458,7 +5003,8 @@ function generateSchemaData2(db, schema, relations, options) {
4458
5003
  typeName,
4459
5004
  typeNameMapper,
4460
5005
  conflictDoNothing,
4461
- mutationTxCtx
5006
+ mutationTxCtx,
5007
+ nestedRuntime
4462
5008
  ) : void 0;
4463
5009
  const uniqueSets = features.upsert ? getUniqueColumnSets(schema[tableName], import_pg_core2.getTableConfig) : [];
4464
5010
  const onConflictInput = features.upsert ? generateOnConflictInput({
@@ -4482,7 +5028,8 @@ function generateSchemaData2(db, schema, relations, options) {
4482
5028
  false,
4483
5029
  typeNameMapper,
4484
5030
  filterCtx,
4485
- mutationTxCtx
5031
+ mutationTxCtx,
5032
+ nestedRuntime
4486
5033
  ) : void 0;
4487
5034
  const upsertSingleGenerated = onConflictInput ? generateUpsert2(
4488
5035
  db,
@@ -4498,7 +5045,8 @@ function generateSchemaData2(db, schema, relations, options) {
4498
5045
  true,
4499
5046
  typeNameMapper,
4500
5047
  filterCtx,
4501
- mutationTxCtx
5048
+ mutationTxCtx,
5049
+ nestedRuntime
4502
5050
  ) : void 0;
4503
5051
  const updateGenerated = features.update ? generateUpdate2(
4504
5052
  db,
@@ -4514,7 +5062,8 @@ function generateSchemaData2(db, schema, relations, options) {
4514
5062
  features.requireWhere,
4515
5063
  typeNameMapper,
4516
5064
  filterCtx,
4517
- mutationTxCtx
5065
+ mutationTxCtx,
5066
+ nestedRuntime
4518
5067
  ) : void 0;
4519
5068
  const updateSingleGenerated = features.update ? generateUpdate2(
4520
5069
  db,
@@ -4530,7 +5079,8 @@ function generateSchemaData2(db, schema, relations, options) {
4530
5079
  features.requireWhere,
4531
5080
  typeNameMapper,
4532
5081
  filterCtx,
4533
- mutationTxCtx
5082
+ mutationTxCtx,
5083
+ nestedRuntime
4534
5084
  ) : void 0;
4535
5085
  const updateManyInput = features.update && features.updateMany ? generateUpdateManyInput({ typeName, updatePrefix: prefixes.update, updateInput, tableFilters }) : void 0;
4536
5086
  const updateManyGenerated = updateManyInput ? generateUpdateMany2(
@@ -4544,7 +5094,8 @@ function generateSchemaData2(db, schema, relations, options) {
4544
5094
  typeName,
4545
5095
  typeNameMapper,
4546
5096
  filterCtx,
4547
- mutationTxCtx
5097
+ mutationTxCtx,
5098
+ nestedRuntime
4548
5099
  ) : void 0;
4549
5100
  const deleteGenerated = features.delete ? generateDelete2(
4550
5101
  db,
@@ -4609,7 +5160,7 @@ function generateSchemaData2(db, schema, relations, options) {
4609
5160
  };
4610
5161
  if (aggregateGenerated && aggregateType) {
4611
5162
  queries[aggregateGenerated.name] = {
4612
- type: new import_graphql7.GraphQLNonNull(aggregateType),
5163
+ type: new import_graphql8.GraphQLNonNull(aggregateType),
4613
5164
  args: aggregateGenerated.args,
4614
5165
  resolve: aggregateGenerated.resolver,
4615
5166
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -4617,7 +5168,7 @@ function generateSchemaData2(db, schema, relations, options) {
4617
5168
  }
4618
5169
  if (groupByGenerated && groupByType) {
4619
5170
  queries[groupByGenerated.name] = {
4620
- type: new import_graphql7.GraphQLNonNull(new import_graphql7.GraphQLList(new import_graphql7.GraphQLNonNull(groupByType))),
5171
+ type: new import_graphql8.GraphQLNonNull(new import_graphql8.GraphQLList(new import_graphql8.GraphQLNonNull(groupByType))),
4621
5172
  args: groupByGenerated.args,
4622
5173
  resolve: groupByGenerated.resolver,
4623
5174
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -4661,7 +5212,7 @@ function generateSchemaData2(db, schema, relations, options) {
4661
5212
  if (updateManyGenerated) {
4662
5213
  mutations[updateManyGenerated.name] = {
4663
5214
  // Nullable items: a no-match entry yields `null` in its slot.
4664
- type: new import_graphql7.GraphQLNonNull(new import_graphql7.GraphQLList(singleTableItemOutput)),
5215
+ type: new import_graphql8.GraphQLNonNull(new import_graphql8.GraphQLList(singleTableItemOutput)),
4665
5216
  args: updateManyGenerated.args,
4666
5217
  resolve: updateManyGenerated.resolver
4667
5218
  };
@@ -4718,7 +5269,7 @@ function generateSchemaData2(db, schema, relations, options) {
4718
5269
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
4719
5270
  const relResolvers = {};
4720
5271
  for (const [relName, relEntry] of Object.entries(tableRelations)) {
4721
- const isOne = (0, import_drizzle_orm6.is)(relEntry.relation ?? relEntry, import_drizzle_orm6.One);
5272
+ const isOne = (0, import_drizzle_orm7.is)(relEntry.relation ?? relEntry, import_drizzle_orm7.One);
4722
5273
  const resolver = resolverFactory({ tableName, relationName: relName, relEntry, isOne });
4723
5274
  if (resolver) {
4724
5275
  relResolvers[relName] = resolver;
@@ -4732,9 +5283,9 @@ function generateSchemaData2(db, schema, relations, options) {
4732
5283
  }
4733
5284
 
4734
5285
  // src/util/builders/sqlite.ts
4735
- var import_drizzle_orm7 = require("drizzle-orm");
5286
+ var import_drizzle_orm8 = require("drizzle-orm");
4736
5287
  var import_sqlite_core2 = require("drizzle-orm/sqlite-core");
4737
- var import_graphql8 = require("graphql");
5288
+ var import_graphql9 = require("graphql");
4738
5289
  var import_graphql_parse_resolve_info4 = require("graphql-parse-resolve-info");
4739
5290
  var generateSelectArray3 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
4740
5291
  const queryBase = db.query[tableName];
@@ -4819,10 +5370,10 @@ var generateSelectSingle3 = (db, tableName, tables, relationMap, orderArgs, filt
4819
5370
  };
4820
5371
  };
4821
5372
  var sqlitePrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, import_sqlite_core2.getTableConfig);
4822
- var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
5373
+ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4823
5374
  const queryArgs = {
4824
5375
  values: {
4825
- type: new import_graphql8.GraphQLNonNull(new import_graphql8.GraphQLList(new import_graphql8.GraphQLNonNull(baseType)))
5376
+ type: new import_graphql9.GraphQLNonNull(new import_graphql9.GraphQLList(new import_graphql9.GraphQLNonNull(baseType)))
4826
5377
  }
4827
5378
  };
4828
5379
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -4831,10 +5382,12 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
4831
5382
  resolver: async (_source, args, context, info) => {
4832
5383
  try {
4833
5384
  return await runMutation(db, context, info, txCtx, async (executor) => {
4834
- const input = remapFromGraphQLArrayInput(args.values, table);
4835
- if (!input.length) {
4836
- throw new import_graphql8.GraphQLError("No values were provided!");
5385
+ if (!args.values.length) {
5386
+ throw new import_graphql9.GraphQLError("No values were provided!");
4837
5387
  }
5388
+ const entries = nested?.enabled(tableName) ? args.values.map((values) => nested.split(tableName, values)) : void 0;
5389
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
5390
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : args.values, table);
4838
5391
  const parsedInfo = (0, import_graphql_parse_resolve_info4.parseResolveInfo)(info, {
4839
5392
  deep: true
4840
5393
  });
@@ -4848,11 +5401,22 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
4848
5401
  pkNames,
4849
5402
  parsedInfo
4850
5403
  });
4851
- let query = executor.insert(table).values(input).returning(columns);
4852
- if (conflictDoNothing) {
4853
- query = query.onConflictDoNothing();
4854
- }
4855
- const result = await query;
5404
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
5405
+ const runInsert = async (target, values) => {
5406
+ let query = target.insert(table).values(values).returning(returning);
5407
+ if (conflictDoNothing) {
5408
+ query = query.onConflictDoNothing();
5409
+ }
5410
+ return await query;
5411
+ };
5412
+ const result = nestedEntries ? await writeWithNestedOps({
5413
+ executor,
5414
+ runtime: nested,
5415
+ tableName,
5416
+ entries: nestedEntries,
5417
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
5418
+ write: (tx, values) => runInsert(tx, [values])
5419
+ }) : await runInsert(executor, input);
4856
5420
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
4857
5421
  return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
4858
5422
  });
@@ -4863,10 +5427,10 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
4863
5427
  args: queryArgs
4864
5428
  };
4865
5429
  };
4866
- var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
5430
+ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4867
5431
  const queryArgs = {
4868
5432
  values: {
4869
- type: new import_graphql8.GraphQLNonNull(baseType)
5433
+ type: new import_graphql9.GraphQLNonNull(baseType)
4870
5434
  }
4871
5435
  };
4872
5436
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -4875,7 +5439,9 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
4875
5439
  resolver: async (_source, args, context, info) => {
4876
5440
  try {
4877
5441
  return await runMutation(db, context, info, txCtx, async (executor) => {
4878
- const input = remapFromGraphQLSingleInput(args.values, table);
5442
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, args.values) : void 0;
5443
+ const nestedEntry = entry && nested.hasOps(entry.ops) ? entry : void 0;
5444
+ const input = nestedEntry ? {} : remapFromGraphQLSingleInput(entry ? entry.columns : args.values, table);
4879
5445
  const parsedInfo = (0, import_graphql_parse_resolve_info4.parseResolveInfo)(info, {
4880
5446
  deep: true
4881
5447
  });
@@ -4889,11 +5455,22 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
4889
5455
  pkNames,
4890
5456
  parsedInfo
4891
5457
  });
4892
- let query = executor.insert(table).values(input).returning(columns);
4893
- if (conflictDoNothing) {
4894
- query = query.onConflictDoNothing();
4895
- }
4896
- const result = await query;
5458
+ const returning = nestedEntry ? nested.withJoinColumns(tableName, nestedEntry.ops, { ...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 = nestedEntry ? await writeWithNestedOps({
5467
+ executor,
5468
+ runtime: nested,
5469
+ tableName,
5470
+ entries: [nestedEntry],
5471
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
5472
+ write: runInsert
5473
+ }) : await runInsert(executor, input);
4897
5474
  if (!result[0]) {
4898
5475
  return void 0;
4899
5476
  }
@@ -4907,10 +5484,10 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
4907
5484
  args: queryArgs
4908
5485
  };
4909
5486
  };
4910
- var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx) => {
5487
+ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx, nested) => {
4911
5488
  const queryArgs = {
4912
5489
  values: {
4913
- type: single ? new import_graphql8.GraphQLNonNull(baseType) : new import_graphql8.GraphQLNonNull(new import_graphql8.GraphQLList(new import_graphql8.GraphQLNonNull(baseType)))
5490
+ type: single ? new import_graphql9.GraphQLNonNull(baseType) : new import_graphql9.GraphQLNonNull(new import_graphql9.GraphQLList(new import_graphql9.GraphQLNonNull(baseType)))
4914
5491
  },
4915
5492
  onConflict: {
4916
5493
  type: onConflictType,
@@ -4923,10 +5500,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
4923
5500
  resolver: async (_source, args, context, info) => {
4924
5501
  try {
4925
5502
  return await runMutation(db, context, info, txCtx, async (executor) => {
4926
- const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
4927
- if (!input.length) {
4928
- throw new import_graphql8.GraphQLError("No values were provided!");
5503
+ const supplied = single ? [args.values] : args.values;
5504
+ if (!supplied.length) {
5505
+ throw new import_graphql9.GraphQLError("No values were provided!");
4929
5506
  }
5507
+ const entries = nested?.enabled(tableName) ? supplied.map((values) => nested.split(tableName, values)) : void 0;
5508
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
5509
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : supplied, table);
4930
5510
  const parsedInfo = (0, import_graphql_parse_resolve_info4.parseResolveInfo)(info, { deep: true });
4931
5511
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
4932
5512
  relationMap,
@@ -4938,19 +5518,30 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
4938
5518
  pkNames,
4939
5519
  parsedInfo
4940
5520
  });
4941
- const plan = resolveConflictPlan({
4942
- table,
4943
- values: input,
4944
- onConflict: args.onConflict,
4945
- pkNames,
4946
- uniqueSets,
4947
- excludedRef: excludedColumnRef,
4948
- withTarget: true,
4949
- buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
4950
- });
4951
- let query = executor.insert(table).values(input).returning(columns);
4952
- query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
4953
- const result = await query;
5521
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
5522
+ const runUpsert = async (target, values) => {
5523
+ const plan = resolveConflictPlan({
5524
+ table,
5525
+ values,
5526
+ onConflict: args.onConflict,
5527
+ pkNames,
5528
+ uniqueSets,
5529
+ excludedRef: excludedColumnRef,
5530
+ withTarget: true,
5531
+ buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
5532
+ });
5533
+ let query = target.insert(table).values(values).returning(returning);
5534
+ query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
5535
+ return await query;
5536
+ };
5537
+ const result = nestedEntries ? await writeWithNestedOps({
5538
+ executor,
5539
+ runtime: nested,
5540
+ tableName,
5541
+ entries: nestedEntries,
5542
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
5543
+ write: (tx, values) => runUpsert(tx, [values])
5544
+ }) : await runUpsert(executor, input);
4954
5545
  if (single && !result[0]) {
4955
5546
  return void 0;
4956
5547
  }
@@ -4964,13 +5555,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
4964
5555
  args: queryArgs
4965
5556
  };
4966
5557
  };
4967
- var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx) => {
5558
+ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx, nested) => {
4968
5559
  const queryArgs = {
4969
5560
  set: {
4970
- type: new import_graphql8.GraphQLNonNull(setArgs)
5561
+ type: new import_graphql9.GraphQLNonNull(setArgs)
4971
5562
  },
4972
5563
  where: {
4973
- type: single || requireWhere ? new import_graphql8.GraphQLNonNull(filterArgs) : filterArgs
5564
+ type: single || requireWhere ? new import_graphql9.GraphQLNonNull(filterArgs) : filterArgs
4974
5565
  }
4975
5566
  };
4976
5567
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -4993,23 +5584,37 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
4993
5584
  pkNames,
4994
5585
  parsedInfo
4995
5586
  });
4996
- const input = remapFromGraphQLSingleInput(set, table);
4997
- if (!Object.keys(input).length) {
4998
- throw new import_graphql8.GraphQLError("Unable to update with no values specified!");
5587
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
5588
+ const nestedOps = entry && nested.hasOps(entry.ops) ? entry.ops : void 0;
5589
+ const input = remapFromGraphQLSingleInput(entry ? entry.columns : set, table);
5590
+ if (!Object.keys(input).length && !nestedOps) {
5591
+ throw new import_graphql9.GraphQLError("Unable to update with no values specified!");
4999
5592
  }
5000
5593
  const relationCtx = relationFilterCtx(filterCtx, tableName);
5001
5594
  const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
5002
5595
  if (single) {
5003
5596
  await assertSingleMatch(executor, table, filters, fieldName);
5004
5597
  }
5005
- let query = executor.update(table).set(input);
5006
- if (filters) {
5007
- query = query.where(filters);
5008
- }
5009
- query = query.returning(columns);
5010
- const result = await query;
5598
+ const returning = nestedOps ? nested.withJoinColumns(tableName, nestedOps, { ...columns }, table) : columns;
5599
+ const runUpdate = async (target, values) => {
5600
+ const writes = Object.keys(values).length > 0;
5601
+ let query = writes ? target.update(table).set(values) : target.select(returning).from(table);
5602
+ if (filters) {
5603
+ query = query.where(filters);
5604
+ }
5605
+ return await (writes ? query.returning(returning) : query);
5606
+ };
5607
+ const result = nestedOps ? await updateWithNestedOps({
5608
+ executor,
5609
+ runtime: nested,
5610
+ tableName,
5611
+ columns: input,
5612
+ ops: nestedOps,
5613
+ remapValues: (values) => values,
5614
+ write: runUpdate
5615
+ }) : await runUpdate(executor, input);
5011
5616
  if (single && result.length > 1) {
5012
- throw new import_graphql8.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
5617
+ throw new import_graphql9.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
5013
5618
  }
5014
5619
  if (single && !result[0]) {
5015
5620
  return void 0;
@@ -5024,10 +5629,10 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
5024
5629
  args: queryArgs
5025
5630
  };
5026
5631
  };
5027
- var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx) => {
5632
+ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx, nested) => {
5028
5633
  const queryArgs = {
5029
5634
  updates: {
5030
- type: new import_graphql8.GraphQLNonNull(new import_graphql8.GraphQLList(new import_graphql8.GraphQLNonNull(updateManyInput)))
5635
+ type: new import_graphql9.GraphQLNonNull(new import_graphql9.GraphQLList(new import_graphql9.GraphQLNonNull(updateManyInput)))
5031
5636
  }
5032
5637
  };
5033
5638
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -5038,7 +5643,7 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
5038
5643
  return await runMutation(db, context, info, txCtx, async (executor) => {
5039
5644
  const { updates } = args;
5040
5645
  if (!updates.length) {
5041
- throw new import_graphql8.GraphQLError("No updates were provided!");
5646
+ throw new import_graphql9.GraphQLError("No updates were provided!");
5042
5647
  }
5043
5648
  const parsedInfo = (0, import_graphql_parse_resolve_info4.parseResolveInfo)(info, {
5044
5649
  deep: true
@@ -5054,23 +5659,55 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
5054
5659
  parsedInfo
5055
5660
  });
5056
5661
  const entries = updates.map(({ where, set }) => {
5057
- const input = remapFromGraphQLSingleInput(set, table);
5058
- if (!Object.keys(input).length) {
5059
- throw new import_graphql8.GraphQLError("Unable to update with no values specified!");
5662
+ const split = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
5663
+ const ops = split && nested.hasOps(split.ops) ? split.ops : void 0;
5664
+ const input = remapFromGraphQLSingleInput(split ? split.columns : set, table);
5665
+ if (!Object.keys(input).length && !ops) {
5666
+ throw new import_graphql9.GraphQLError("Unable to update with no values specified!");
5060
5667
  }
5061
5668
  return {
5062
5669
  set: input,
5670
+ ops,
5063
5671
  filters: where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
5064
5672
  };
5065
5673
  });
5674
+ const anyNested = entries.some((entry) => entry.ops);
5675
+ const returning = anyNested ? nested.withJoinColumns(
5676
+ tableName,
5677
+ mergedOps(entries.map((entry) => ({ ops: entry.ops ?? {} }))),
5678
+ { ...columns },
5679
+ table
5680
+ ) : columns;
5066
5681
  const runEntry = (tx, entry) => {
5067
5682
  let query = tx.update(table).set(entry.set);
5068
5683
  if (entry.filters) {
5069
5684
  query = query.where(entry.filters);
5070
5685
  }
5071
- return query.returning(columns).all();
5686
+ return query.returning(returning).all();
5687
+ };
5688
+ const runNestedEntry = async (tx, entry) => {
5689
+ const values = entry.ops ? { ...entry.set, ...await nested.applyParentSide(tx, tableName, entry.ops) } : entry.set;
5690
+ const writes = Object.keys(values).length > 0;
5691
+ let query = writes ? tx.update(table).set(values) : tx.select(returning).from(table);
5692
+ if (entry.filters) {
5693
+ query = query.where(entry.filters);
5694
+ }
5695
+ const rows = await (writes ? query.returning(returning) : query);
5696
+ if (entry.ops) {
5697
+ await nested.applyChildSide(tx, tableName, entry.ops, rows);
5698
+ }
5699
+ return rows;
5072
5700
  };
5073
5701
  const perEntry = await executor.transaction((tx) => {
5702
+ if (anyNested) {
5703
+ return (async () => {
5704
+ const results2 = [];
5705
+ for (const entry of entries) {
5706
+ results2.push(await runNestedEntry(tx, entry));
5707
+ }
5708
+ return results2;
5709
+ })();
5710
+ }
5074
5711
  const first = runEntry(tx, entries[0]);
5075
5712
  if (typeof first?.then === "function") {
5076
5713
  return (async () => {
@@ -5113,7 +5750,7 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
5113
5750
  var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx) => {
5114
5751
  const queryArgs = {
5115
5752
  where: {
5116
- type: single || requireWhere ? new import_graphql8.GraphQLNonNull(filterArgs) : filterArgs
5753
+ type: single || requireWhere ? new import_graphql9.GraphQLNonNull(filterArgs) : filterArgs
5117
5754
  }
5118
5755
  };
5119
5756
  return {
@@ -5142,7 +5779,7 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, si
5142
5779
  query = query.returning(columns);
5143
5780
  const result = await query;
5144
5781
  if (single && result.length > 1) {
5145
- throw new import_graphql8.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
5782
+ throw new import_graphql9.GraphQLError(`${fieldName}: 'where' matched more than one row!`);
5146
5783
  }
5147
5784
  if (single) {
5148
5785
  return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
@@ -5169,7 +5806,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5169
5806
  } = options;
5170
5807
  const rawSchema = schema;
5171
5808
  const schemaEntries = Object.entries(rawSchema);
5172
- const tableEntries = schemaEntries.filter(([_key, value]) => (0, import_drizzle_orm7.is)(value, import_sqlite_core2.SQLiteTable));
5809
+ const tableEntries = schemaEntries.filter(([_key, value]) => (0, import_drizzle_orm8.is)(value, import_sqlite_core2.SQLiteTable));
5173
5810
  const tables = Object.fromEntries(tableEntries);
5174
5811
  if (!tableEntries.length) {
5175
5812
  throw new Error(
@@ -5177,6 +5814,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5177
5814
  );
5178
5815
  }
5179
5816
  registerScalarOverrides(tables, options);
5817
+ registerEnumConfig(options);
5180
5818
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
5181
5819
  attachTargetPrimaryKeys(namedRelations, tables, sqlitePrimaryKeyPropNames);
5182
5820
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
@@ -5194,8 +5832,23 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5194
5832
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
5195
5833
  listRelationFilterCache: /* @__PURE__ */ new Map(),
5196
5834
  aggregateTypeCache: /* @__PURE__ */ new Map(),
5197
- complexity
5835
+ complexity,
5836
+ docs: options.docs ?? {}
5198
5837
  };
5838
+ if (features.nestedWrites && db.resultKind === "sync") {
5839
+ throw new Error(
5840
+ "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."
5841
+ );
5842
+ }
5843
+ const nestedPlans = features.nestedWrites ? buildNestedWritePlans(
5844
+ tables,
5845
+ namedRelations,
5846
+ (target) => getUniqueColumnSets(target, import_sqlite_core2.getTableConfig),
5847
+ (target) => sqlitePrimaryKeyPropNames(target),
5848
+ extractRelationJoinColumns
5849
+ ) : void 0;
5850
+ const nestedTypes = nestedPlans ? createNestedWriteTypes({ plans: nestedPlans, cacheCtx, typeNameMapper, insertPrefix: prefixes.insert }) : void 0;
5851
+ const nestedRuntime = nestedPlans ? createNestedWriteRuntime({ plans: nestedPlans, filterCtx }) : void 0;
5199
5852
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
5200
5853
  const queries = {};
5201
5854
  const mutations = {};
@@ -5219,7 +5872,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5219
5872
  prefixes.insert,
5220
5873
  prefixes.update,
5221
5874
  resolverFactory,
5222
- relationAggregateFactory
5875
+ relationAggregateFactory,
5876
+ nestedTypes
5223
5877
  )
5224
5878
  ])
5225
5879
  );
@@ -5280,7 +5934,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5280
5934
  typeName,
5281
5935
  typeNameMapper,
5282
5936
  conflictDoNothing,
5283
- mutationTxCtx
5937
+ mutationTxCtx,
5938
+ nestedRuntime
5284
5939
  ) : void 0;
5285
5940
  const insertSingleGenerated = features.insert ? generateInsertSingle3(
5286
5941
  db,
@@ -5293,7 +5948,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5293
5948
  typeName,
5294
5949
  typeNameMapper,
5295
5950
  conflictDoNothing,
5296
- mutationTxCtx
5951
+ mutationTxCtx,
5952
+ nestedRuntime
5297
5953
  ) : void 0;
5298
5954
  const uniqueSets = features.upsert ? getUniqueColumnSets(schema[tableName], import_sqlite_core2.getTableConfig) : [];
5299
5955
  const onConflictInput = features.upsert ? generateOnConflictInput({
@@ -5317,7 +5973,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5317
5973
  false,
5318
5974
  typeNameMapper,
5319
5975
  filterCtx,
5320
- mutationTxCtx
5976
+ mutationTxCtx,
5977
+ nestedRuntime
5321
5978
  ) : void 0;
5322
5979
  const upsertSingleGenerated = onConflictInput ? generateUpsert3(
5323
5980
  db,
@@ -5333,7 +5990,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5333
5990
  true,
5334
5991
  typeNameMapper,
5335
5992
  filterCtx,
5336
- mutationTxCtx
5993
+ mutationTxCtx,
5994
+ nestedRuntime
5337
5995
  ) : void 0;
5338
5996
  const updateGenerated = features.update ? generateUpdate3(
5339
5997
  db,
@@ -5349,7 +6007,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5349
6007
  features.requireWhere,
5350
6008
  typeNameMapper,
5351
6009
  filterCtx,
5352
- mutationTxCtx
6010
+ mutationTxCtx,
6011
+ nestedRuntime
5353
6012
  ) : void 0;
5354
6013
  const updateSingleGenerated = features.update ? generateUpdate3(
5355
6014
  db,
@@ -5365,7 +6024,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5365
6024
  features.requireWhere,
5366
6025
  typeNameMapper,
5367
6026
  filterCtx,
5368
- mutationTxCtx
6027
+ mutationTxCtx,
6028
+ nestedRuntime
5369
6029
  ) : void 0;
5370
6030
  const updateManyInput = features.update && features.updateMany ? generateUpdateManyInput({ typeName, updatePrefix: prefixes.update, updateInput, tableFilters }) : void 0;
5371
6031
  const updateManyGenerated = updateManyInput ? generateUpdateMany3(
@@ -5379,7 +6039,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5379
6039
  typeName,
5380
6040
  typeNameMapper,
5381
6041
  filterCtx,
5382
- mutationTxCtx
6042
+ mutationTxCtx,
6043
+ nestedRuntime
5383
6044
  ) : void 0;
5384
6045
  const deleteGenerated = features.delete ? generateDelete3(
5385
6046
  db,
@@ -5444,7 +6105,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5444
6105
  };
5445
6106
  if (aggregateGenerated && aggregateType) {
5446
6107
  queries[aggregateGenerated.name] = {
5447
- type: new import_graphql8.GraphQLNonNull(aggregateType),
6108
+ type: new import_graphql9.GraphQLNonNull(aggregateType),
5448
6109
  args: aggregateGenerated.args,
5449
6110
  resolve: aggregateGenerated.resolver,
5450
6111
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -5452,7 +6113,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5452
6113
  }
5453
6114
  if (groupByGenerated && groupByType) {
5454
6115
  queries[groupByGenerated.name] = {
5455
- type: new import_graphql8.GraphQLNonNull(new import_graphql8.GraphQLList(new import_graphql8.GraphQLNonNull(groupByType))),
6116
+ type: new import_graphql9.GraphQLNonNull(new import_graphql9.GraphQLList(new import_graphql9.GraphQLNonNull(groupByType))),
5456
6117
  args: groupByGenerated.args,
5457
6118
  resolve: groupByGenerated.resolver,
5458
6119
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -5496,7 +6157,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5496
6157
  if (updateManyGenerated) {
5497
6158
  mutations[updateManyGenerated.name] = {
5498
6159
  // Nullable items: a no-match entry yields `null` in its slot.
5499
- type: new import_graphql8.GraphQLNonNull(new import_graphql8.GraphQLList(singleTableItemOutput)),
6160
+ type: new import_graphql9.GraphQLNonNull(new import_graphql9.GraphQLList(singleTableItemOutput)),
5500
6161
  args: updateManyGenerated.args,
5501
6162
  resolve: updateManyGenerated.resolver
5502
6163
  };
@@ -5553,7 +6214,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5553
6214
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
5554
6215
  const relResolvers = {};
5555
6216
  for (const [relName, relEntry] of Object.entries(tableRelations)) {
5556
- const isOne = (0, import_drizzle_orm7.is)(relEntry.relation ?? relEntry, import_drizzle_orm7.One);
6217
+ const isOne = (0, import_drizzle_orm8.is)(relEntry.relation ?? relEntry, import_drizzle_orm8.One);
5557
6218
  const resolver = resolverFactory({ tableName, relationName: relName, relEntry, isOne });
5558
6219
  if (resolver) {
5559
6220
  relResolvers[relName] = resolver;
@@ -5598,6 +6259,7 @@ var buildSchema = (db, config) => {
5598
6259
  updateMany: config?.features?.updateMany ?? true,
5599
6260
  delete: config?.features?.delete ?? true,
5600
6261
  upsert: config?.features?.upsert ?? false,
6262
+ nestedWrites: config?.features?.nestedWrites ?? false,
5601
6263
  requireWhere: config?.features?.requireWhere ?? false
5602
6264
  };
5603
6265
  const complexityConfig = config?.complexity ?? true;
@@ -5637,14 +6299,21 @@ var buildSchema = (db, config) => {
5637
6299
  complexity,
5638
6300
  scalars: config?.scalars,
5639
6301
  mapColumnType: config?.mapColumnType,
5640
- transactions
6302
+ enumNameMapper: config?.enumNameMapper,
6303
+ transactions,
6304
+ docs: {
6305
+ describeColumn: config?.describeColumn,
6306
+ describeTable: config?.describeTable,
6307
+ describeRelation: config?.describeRelation,
6308
+ deprecateColumn: config?.deprecateColumn
6309
+ }
5641
6310
  };
5642
6311
  let generatorOutput;
5643
- if ((0, import_drizzle_orm8.is)(db, import_mysql_core3.MySqlDatabase)) {
6312
+ if ((0, import_drizzle_orm9.is)(db, import_mysql_core3.MySqlDatabase)) {
5644
6313
  generatorOutput = generateSchemaData(db, schema, relations, generatorOptions);
5645
- } else if ((0, import_drizzle_orm8.is)(db, import_pg_core3.PgAsyncDatabase)) {
6314
+ } else if ((0, import_drizzle_orm9.is)(db, import_pg_core3.PgAsyncDatabase)) {
5646
6315
  generatorOutput = generateSchemaData2(db, schema, relations, generatorOptions);
5647
- } else if ((0, import_drizzle_orm8.is)(db, import_sqlite_core3.BaseSQLiteDatabase)) {
6316
+ } else if ((0, import_drizzle_orm9.is)(db, import_sqlite_core3.BaseSQLiteDatabase)) {
5648
6317
  generatorOutput = generateSchemaData3(db, schema, relations, generatorOptions);
5649
6318
  } else {
5650
6319
  throw new Error("Drizzle-GraphQL Error: Unknown database instance type");
@@ -5657,19 +6326,19 @@ var buildSchema = (db, config) => {
5657
6326
  const { queries, mutations, inputs, types } = generatorOutput;
5658
6327
  const graphQLSchemaConfig = {
5659
6328
  types: [...Object.values(inputs), ...Object.values(types)],
5660
- query: new import_graphql9.GraphQLObjectType({
6329
+ query: new import_graphql10.GraphQLObjectType({
5661
6330
  name: "Query",
5662
6331
  fields: queries
5663
6332
  })
5664
6333
  };
5665
6334
  if (config?.mutations !== false && Object.keys(mutations).length) {
5666
- const mutation = new import_graphql9.GraphQLObjectType({
6335
+ const mutation = new import_graphql10.GraphQLObjectType({
5667
6336
  name: "Mutation",
5668
6337
  fields: mutations
5669
6338
  });
5670
6339
  graphQLSchemaConfig.mutation = mutation;
5671
6340
  }
5672
- const outputSchema = new import_graphql9.GraphQLSchema(graphQLSchemaConfig);
6341
+ const outputSchema = new import_graphql10.GraphQLSchema(graphQLSchemaConfig);
5673
6342
  return { schema: outputSchema, entities: generatorOutput };
5674
6343
  };
5675
6344
  // Annotate the CommonJS export names for ESM import in node: