@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.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/index.ts
2
- import { is as is7 } from "drizzle-orm";
2
+ import { is as is8 } from "drizzle-orm";
3
3
  import { MySqlDatabase } from "drizzle-orm/mysql-core";
4
4
  import { PgAsyncDatabase } from "drizzle-orm/pg-core";
5
5
  import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core";
@@ -198,15 +198,42 @@ var GraphQLDecimalString = new GraphQLScalarType({
198
198
 
199
199
  // src/util/type-converter/index.ts
200
200
  var allowedNameChars = /^[a-zA-Z0-9_]+$/;
201
- var enumMap = /* @__PURE__ */ new WeakMap();
201
+ var declaredEnum = (column) => {
202
+ const declared = column.enum;
203
+ return typeof declared?.enumName === "string" ? { enumName: declared.enumName, schema: typeof declared.schema === "string" ? declared.schema : void 0 } : void 0;
204
+ };
205
+ var pascalize = (input) => input.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => capitalize(part)).join("");
206
+ var enumValuesKey = (values) => JSON.stringify(values);
207
+ var enumNamesInUse = /* @__PURE__ */ new Map();
208
+ var enumNameMapper;
209
+ var registerEnumConfig = (config) => {
210
+ enumNameMapper = config.enumNameMapper;
211
+ enumNamesInUse = /* @__PURE__ */ new Map();
212
+ };
202
213
  var generateEnumCached = (column, columnName, tableName) => {
203
- if (enumMap.has(column)) {
204
- return enumMap.get(column);
214
+ const declared = declaredEnum(column);
215
+ const values = column.enumValues;
216
+ const name = enumNameMapper?.({
217
+ enumName: declared?.enumName,
218
+ schema: declared?.schema,
219
+ tableName,
220
+ columnName,
221
+ values
222
+ }) ?? (declared ? `${pascalize(declared.enumName)}Enum` : `${capitalize(tableName)}${capitalize(columnName)}Enum`);
223
+ const valuesKey = enumValuesKey(values);
224
+ const claimed = enumNamesInUse.get(name);
225
+ if (claimed) {
226
+ if (claimed.valuesKey !== valuesKey) {
227
+ throw new Error(
228
+ `Drizzle-GraphQL Error: Two different enums both map to the GraphQL type name '${name}' (most recently '${tableName}.${columnName}'). Give one of them a different name via config.enumNameMapper.`
229
+ );
230
+ }
231
+ return claimed.type;
205
232
  }
206
233
  const gqlEnum = new GraphQLEnumType({
207
- name: `${capitalize(tableName)}${capitalize(columnName)}Enum`,
234
+ name,
208
235
  values: Object.fromEntries(
209
- column.enumValues.map((e, index) => [
236
+ values.map((e, index) => [
210
237
  allowedNameChars.test(e) ? e : `Option${index}`,
211
238
  {
212
239
  value: e,
@@ -215,7 +242,7 @@ var generateEnumCached = (column, columnName, tableName) => {
215
242
  ])
216
243
  )
217
244
  });
218
- enumMap.set(column, gqlEnum);
245
+ enumNamesInUse.set(name, { type: gqlEnum, valuesKey });
219
246
  return gqlEnum;
220
247
  };
221
248
  var geoXyType = new GraphQLObjectType({
@@ -236,14 +263,14 @@ var columnToGraphQLCore = (column, columnName, tableName, isInput) => {
236
263
  const dimensions = column.dimensions;
237
264
  if (dimensions !== void 0 && dimensions > 0) {
238
265
  const inner = columnBaseToGraphQLCore(column, columnName, tableName, isInput);
239
- const innerDesc = inner.description ?? inner.type.name;
266
+ const innerLabel = inner.typeLabel ?? inner.type.name;
240
267
  let type = inner.type;
241
- let description = innerDesc;
268
+ let typeLabel = innerLabel;
242
269
  for (let i = 0; i < dimensions; i++) {
243
270
  type = new GraphQLList(new GraphQLNonNull(type));
244
- description = `Array<${description}>`;
271
+ typeLabel = `Array<${typeLabel}>`;
245
272
  }
246
- return { type, description };
273
+ return { type, typeLabel };
247
274
  }
248
275
  return columnBaseToGraphQLCore(column, columnName, tableName, isInput);
249
276
  };
@@ -251,51 +278,51 @@ var columnBaseToGraphQLCore = (column, columnName, tableName, isInput) => {
251
278
  const { type: baseType, constraint } = extractExtendedColumnType(column);
252
279
  switch (baseType) {
253
280
  case "boolean":
254
- return { type: GraphQLBoolean, description: "Boolean" };
281
+ return { type: GraphQLBoolean, typeLabel: "Boolean" };
255
282
  case "object":
256
283
  if (column instanceof PgTimestamp || column instanceof PgDate) {
257
- return { type: GraphQLDateTime, description: "DateTime" };
284
+ return { type: GraphQLDateTime, typeLabel: "DateTime" };
258
285
  }
259
286
  return column.columnType === "PgGeometryObject" ? {
260
287
  type: isInput ? geoXyInputType : geoXyType,
261
- description: "Geometry points XY"
288
+ typeLabel: "Geometry points XY"
262
289
  } : column.columnType === "PgBytea" ? {
263
290
  type: new GraphQLList(new GraphQLNonNull(GraphQLInt)),
264
- description: "Buffer"
265
- } : { type: GraphQLJSON, description: "JSON" };
291
+ typeLabel: "Buffer"
292
+ } : { type: GraphQLJSON, typeLabel: "JSON" };
266
293
  case "string":
267
294
  if (column.enumValues?.length) {
268
295
  return { type: generateEnumCached(column, columnName, tableName) };
269
296
  }
270
297
  if (constraint === "numeric" && !column.dimensions) {
271
- return { type: GraphQLDecimalString, description: "Decimal" };
298
+ return { type: GraphQLDecimalString, typeLabel: "Decimal" };
272
299
  }
273
300
  if (column instanceof PgTimestamp || column instanceof PgTimestampString) {
274
- return { type: GraphQLDateTime, description: "DateTime" };
301
+ return { type: GraphQLDateTime, typeLabel: "DateTime" };
275
302
  }
276
303
  if (column instanceof PgUUID) {
277
- return { type: GraphQLUUID, description: "UUID" };
304
+ return { type: GraphQLUUID, typeLabel: "UUID" };
278
305
  }
279
306
  if (column instanceof PgDateString) {
280
- return isInput ? { type: GraphQLString, description: "Date" } : { type: GraphQLDate, description: "Date" };
307
+ return isInput ? { type: GraphQLString, typeLabel: "Date" } : { type: GraphQLDate, typeLabel: "Date" };
281
308
  }
282
- return { type: GraphQLString, description: "String" };
309
+ return { type: GraphQLString, typeLabel: "String" };
283
310
  case "bigint":
284
- return { type: GraphQLBigIntString, description: "BigInt" };
311
+ return { type: GraphQLBigIntString, typeLabel: "BigInt" };
285
312
  case "number": {
286
- return is(column, PgInteger) || is(column, PgSerial) || is(column, MySqlInt) || is(column, MySqlSerial) || is(column, SQLiteInteger) ? { type: GraphQLInt, description: "Integer" } : { type: GraphQLFloat, description: "Float" };
313
+ return is(column, PgInteger) || is(column, PgSerial) || is(column, MySqlInt) || is(column, MySqlSerial) || is(column, SQLiteInteger) ? { type: GraphQLInt, typeLabel: "Integer" } : { type: GraphQLFloat, typeLabel: "Float" };
287
314
  }
288
315
  case "array": {
289
316
  if (column.columnType === "PgVector") {
290
317
  return {
291
318
  type: new GraphQLList(new GraphQLNonNull(GraphQLFloat)),
292
- description: "Array<Float>"
319
+ typeLabel: "Array<Float>"
293
320
  };
294
321
  }
295
322
  if (column.columnType === "PgGeometry") {
296
323
  return {
297
324
  type: new GraphQLList(new GraphQLNonNull(GraphQLFloat)),
298
- description: "Tuple<[Float, Float]>"
325
+ typeLabel: "Tuple<[Float, Float]>"
299
326
  };
300
327
  }
301
328
  const innerType = columnToGraphQLCore(
@@ -306,7 +333,7 @@ var columnBaseToGraphQLCore = (column, columnName, tableName, isInput) => {
306
333
  );
307
334
  return {
308
335
  type: new GraphQLList(new GraphQLNonNull(innerType.type)),
309
- description: `Array<${innerType.description}>`
336
+ typeLabel: `Array<${innerType.typeLabel}>`
310
337
  };
311
338
  }
312
339
  default:
@@ -362,24 +389,14 @@ var registerScalarOverrides = (tables, config) => {
362
389
  };
363
390
  var drizzleColumnToGraphQLType = (column, columnName, tableName, forceNullable = false, defaultIsNullable = false, isInput = false) => {
364
391
  const override = getColumnScalarOverride(column, isInput);
365
- let typeDesc;
366
- if (override) {
367
- typeDesc = { type: override, description: override.name };
368
- } else {
369
- typeDesc = columnToGraphQLCore(column, columnName, tableName, isInput);
370
- const noDesc = ["string", "boolean", "number"];
371
- const { type: baseType } = extractExtendedColumnType(column);
372
- if (noDesc.find((e) => e === baseType)) {
373
- delete typeDesc.description;
374
- }
375
- }
392
+ const typeDesc = override ? { type: override, typeLabel: override.name } : columnToGraphQLCore(column, columnName, tableName, isInput);
376
393
  if (forceNullable) {
377
394
  return typeDesc;
378
395
  }
379
396
  if (column.notNull && !(defaultIsNullable && (column.hasDefault || column.defaultFn))) {
380
397
  return {
381
398
  type: new GraphQLNonNull(typeDesc.type),
382
- description: typeDesc.description
399
+ typeLabel: typeDesc.typeLabel
383
400
  };
384
401
  }
385
402
  return typeDesc;
@@ -962,6 +979,22 @@ var createRelationResolverFactory = (db, tables, filterCtx) => ({ tableName, rel
962
979
  return loader.load(localValue);
963
980
  };
964
981
  };
982
+ var columnDocs = (docs, column, tableName, columnName) => {
983
+ const description = docs.describeColumn?.(column, { tableName, columnName });
984
+ const deprecationReason = docs.deprecateColumn?.(column, { tableName, columnName });
985
+ return {
986
+ ...description !== void 0 ? { description } : {},
987
+ ...deprecationReason !== void 0 ? { deprecationReason } : {}
988
+ };
989
+ };
990
+ var inputFieldDocs = (docs, column, tableName, columnName, fieldType) => {
991
+ const resolved = columnDocs(docs, column, tableName, columnName);
992
+ if (resolved.deprecationReason !== void 0 && fieldType instanceof GraphQLNonNull2) {
993
+ const { deprecationReason: _dropped, ...rest } = resolved;
994
+ return rest;
995
+ }
996
+ return resolved;
997
+ };
965
998
  var listFieldComplexity = (options) => ({ args, childComplexity }) => {
966
999
  const limit = args["limit"];
967
1000
  const rows = typeof limit === "number" && limit > 0 ? limit : options.defaultListSize;
@@ -969,18 +1002,21 @@ var listFieldComplexity = (options) => ({ args, childComplexity }) => {
969
1002
  };
970
1003
  var aggregateFieldComplexity = (options) => ({ childComplexity }) => options.aggregateCost + childComplexity;
971
1004
  var AGGREGATE_FIELD_SUFFIX = "Aggregate";
972
- var relationAggregateJoinColumns = (tree, table, selectionCtx) => {
973
- const relations = selectionCtx?.relationMap[selectionCtx.tableName];
974
- if (!relations || !selectionCtx) {
1005
+ var relationJoinColumns = (tree, table, selectionCtx) => {
1006
+ if (!selectionCtx) {
1007
+ return [];
1008
+ }
1009
+ const relations = (selectionCtx.allRelations ?? selectionCtx.relationMap)[selectionCtx.tableName] ?? selectionCtx.relationMap[selectionCtx.tableName];
1010
+ if (!relations) {
975
1011
  return [];
976
1012
  }
977
1013
  const tableColumns = getColumns(table);
978
1014
  const needed = [];
979
1015
  for (const fieldData of Object.values(tree)) {
980
- if (tableColumns[fieldData.name] || !fieldData.name.endsWith(AGGREGATE_FIELD_SUFFIX)) {
1016
+ if (tableColumns[fieldData.name]) {
981
1017
  continue;
982
1018
  }
983
- const relEntry = relations[fieldData.name.slice(0, -AGGREGATE_FIELD_SUFFIX.length)];
1019
+ const relEntry = fieldData.name.endsWith(AGGREGATE_FIELD_SUFFIX) ? relations[fieldData.name.slice(0, -AGGREGATE_FIELD_SUFFIX.length)] : relations[fieldData.name];
984
1020
  const targetTable = relEntry ? selectionCtx.tables[relEntry.targetTableName] : void 0;
985
1021
  if (!relEntry || !targetTable) {
986
1022
  continue;
@@ -1002,7 +1038,7 @@ var extractSelectedColumnsFromTree = (tree, table, selectionCtx) => {
1002
1038
  }
1003
1039
  selectedColumns.push([fieldData.name, true]);
1004
1040
  }
1005
- for (const columnName of relationAggregateJoinColumns(tree, table, selectionCtx)) {
1041
+ for (const columnName of relationJoinColumns(tree, table, selectionCtx)) {
1006
1042
  selectedColumns.push([columnName, true]);
1007
1043
  }
1008
1044
  if (!selectedColumns.length) {
@@ -1022,7 +1058,7 @@ var extractSelectedColumnsFromTreeSQLFormat = (tree, table, selectionCtx) => {
1022
1058
  }
1023
1059
  selectedColumns.push([fieldData.name, tableColumns[fieldData.name]]);
1024
1060
  }
1025
- for (const columnName of relationAggregateJoinColumns(tree, table, selectionCtx)) {
1061
+ for (const columnName of relationJoinColumns(tree, table, selectionCtx)) {
1026
1062
  selectedColumns.push([columnName, tableColumns[columnName]]);
1027
1063
  }
1028
1064
  if (!selectedColumns.length) {
@@ -1143,21 +1179,23 @@ var jsonFilterFields = (column, colType) => {
1143
1179
  isNotNull: { type: GraphQLBoolean2 }
1144
1180
  };
1145
1181
  };
1146
- var arrayFilterFields = (colType, colArr, colDesc) => {
1182
+ var IN_ARRAY_DESCRIPTION = "Matches any one of these values (SQL `IN`)";
1183
+ var NOT_IN_ARRAY_DESCRIPTION = "Matches none of these values (SQL `NOT IN`)";
1184
+ var arrayFilterFields = (colType, colArr) => {
1147
1185
  let element = colType.ofType;
1148
1186
  if (element instanceof GraphQLNonNull2) {
1149
1187
  element = element.ofType;
1150
1188
  }
1151
1189
  const elementList = new GraphQLList2(new GraphQLNonNull2(element));
1152
1190
  return {
1153
- eq: { type: colType, description: colDesc },
1154
- ne: { type: colType, description: colDesc },
1191
+ eq: { type: colType, description: "The whole array equals this array" },
1192
+ ne: { type: colType, description: "The whole array differs from this array" },
1155
1193
  has: { type: element, description: "Array contains this element" },
1156
1194
  hasSome: { type: elementList, description: "Array contains at least one of these elements (overlap, `&&`)" },
1157
1195
  hasEvery: { type: elementList, description: "Array contains every one of these elements (containment, `@>`)" },
1158
1196
  isEmpty: { type: GraphQLBoolean2, description: "When true, matches arrays with no elements" },
1159
- inArray: { type: colArr, description: `Array<${colDesc}>` },
1160
- notInArray: { type: colArr, description: `Array<${colDesc}>` },
1197
+ inArray: { type: colArr, description: IN_ARRAY_DESCRIPTION },
1198
+ notInArray: { type: colArr, description: NOT_IN_ARRAY_DESCRIPTION },
1161
1199
  isNull: { type: GraphQLBoolean2 },
1162
1200
  isNotNull: { type: GraphQLBoolean2 }
1163
1201
  };
@@ -1193,18 +1231,17 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
1193
1231
  return cached;
1194
1232
  }
1195
1233
  const colType = columnGraphQLType.type;
1196
- const colDesc = columnGraphQLType.description;
1197
1234
  const colArr = new GraphQLList2(new GraphQLNonNull2(colType));
1198
1235
  const customOverrideFilter = inputOverride !== void 0 && !BUILTIN_FILTER_SCALARS.has(inputOverride);
1199
1236
  const underlying = extractExtendedColumnType2(column);
1200
1237
  const omitStringOps = customOverrideFilter ? underlying.type !== "string" || underlying.constraint === "numeric" : FILTERS_WITHOUT_STRING_OPS.has(genericName);
1201
- const baseFields = kind === "json" ? jsonFilterFields(column, colType) : kind === "array" ? arrayFilterFields(colType, colArr, colDesc) : {
1202
- eq: { type: colType, description: colDesc },
1203
- ne: { type: colType, description: colDesc },
1204
- lt: { type: colType, description: colDesc },
1205
- lte: { type: colType, description: colDesc },
1206
- gt: { type: colType, description: colDesc },
1207
- gte: { type: colType, description: colDesc },
1238
+ const baseFields = kind === "json" ? jsonFilterFields(column, colType) : kind === "array" ? arrayFilterFields(colType, colArr) : {
1239
+ eq: { type: colType, description: "Equal to" },
1240
+ ne: { type: colType, description: "Not equal to" },
1241
+ lt: { type: colType, description: "Less than" },
1242
+ lte: { type: colType, description: "Less than or equal to" },
1243
+ gt: { type: colType, description: "Greater than" },
1244
+ gte: { type: colType, description: "Greater than or equal to" },
1208
1245
  ...omitStringOps ? {} : {
1209
1246
  like: { type: GraphQLString2 },
1210
1247
  notLike: { type: GraphQLString2 },
@@ -1235,10 +1272,10 @@ var generateColumnFilterValues = (column, tableName, columnName, cacheCtx) => {
1235
1272
  description: "Case-insensitive `contains`."
1236
1273
  }
1237
1274
  },
1238
- inArray: { type: colArr, description: `Array<${colDesc}>` },
1239
- notInArray: { type: colArr, description: `Array<${colDesc}>` },
1240
- isNull: { type: GraphQLBoolean2 },
1241
- isNotNull: { type: GraphQLBoolean2 }
1275
+ inArray: { type: colArr, description: IN_ARRAY_DESCRIPTION },
1276
+ notInArray: { type: colArr, description: NOT_IN_ARRAY_DESCRIPTION },
1277
+ isNull: { type: GraphQLBoolean2, description: "When true, matches rows where the column is NULL" },
1278
+ isNotNull: { type: GraphQLBoolean2, description: "When true, matches rows where the column is not NULL" }
1242
1279
  };
1243
1280
  const mainType = new GraphQLInputObjectType2({
1244
1281
  name: `${genericName}Filter`,
@@ -1285,10 +1322,14 @@ var generateTableFilterValuesCached = (table, tableName, cacheCtx) => {
1285
1322
  const columns = getColumns(table);
1286
1323
  const columnEntries = Object.entries(columns);
1287
1324
  const remapped = Object.fromEntries(
1288
- columnEntries.map(([columnName, columnDescription]) => [
1325
+ columnEntries.map(([columnName, column]) => [
1289
1326
  columnName,
1290
1327
  {
1291
- type: generateColumnFilterValues(columnDescription, tableName, columnName, cacheCtx)
1328
+ type: generateColumnFilterValues(column, tableName, columnName, cacheCtx),
1329
+ // A filter field is the same column, so it carries the same documentation. Deprecation
1330
+ // is not propagated: filtering on a deprecated column is how a caller finds the rows
1331
+ // that still use it.
1332
+ ...cacheCtx.docs.describeColumn ? { description: cacheCtx.docs.describeColumn(column, { tableName, columnName }) } : {}
1292
1333
  }
1293
1334
  ])
1294
1335
  );
@@ -1302,9 +1343,12 @@ var generateTableSelectTypeFieldsCached = (table, tableName, cacheCtx) => {
1302
1343
  const columns = getColumns(table);
1303
1344
  const columnEntries = Object.entries(columns);
1304
1345
  const remapped = Object.fromEntries(
1305
- columnEntries.map(([columnName, columnDescription]) => [
1346
+ columnEntries.map(([columnName, column]) => [
1306
1347
  columnName,
1307
- drizzleColumnToGraphQLType(columnDescription, columnName, tableName)
1348
+ {
1349
+ ...drizzleColumnToGraphQLType(column, columnName, tableName),
1350
+ ...columnDocs(cacheCtx.docs, column, tableName, columnName)
1351
+ }
1308
1352
  ])
1309
1353
  );
1310
1354
  if (!remapped[CURSOR_FIELD_NAME]) {
@@ -1501,6 +1545,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1501
1545
  const typeName = resolveTypeName(tableName, typeNameMapper);
1502
1546
  const shell = new GraphQLObjectType2({
1503
1547
  name: typeName,
1548
+ description: cacheCtx.docs.describeTable?.(tableName),
1504
1549
  fields: () => ({ ...tableFields, ...container.fields })
1505
1550
  });
1506
1551
  cacheCtx.objectTypeCache.set(tableName, shell);
@@ -1542,11 +1587,14 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1542
1587
  const capturedTargetContainer = targetContainer;
1543
1588
  relType = new GraphQLObjectType2({
1544
1589
  name: resolveTypeName(targetTableName, typeNameMapper),
1590
+ description: cacheCtx.docs.describeTable?.(targetTableName),
1545
1591
  fields: () => ({ ...targetTableFields, ...capturedTargetContainer.fields })
1546
1592
  });
1547
1593
  cacheCtx.objectTypeCache.set(targetTableName, relType);
1548
1594
  }
1549
1595
  const resolve = resolverFactory?.({ tableName, relationName, relEntry, isOne });
1596
+ const relationDescription = cacheCtx.docs.describeRelation?.(tableName, relationName);
1597
+ const relationDocs = relationDescription !== void 0 ? { description: relationDescription } : {};
1550
1598
  if (isOne) {
1551
1599
  const isRequired = relation.optional === false;
1552
1600
  rawRelationFields.push([
@@ -1556,7 +1604,8 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1556
1604
  args: {
1557
1605
  where: { type: relSelectData.filters }
1558
1606
  },
1559
- resolve
1607
+ resolve,
1608
+ ...relationDocs
1560
1609
  }
1561
1610
  ]);
1562
1611
  continue;
@@ -1572,6 +1621,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1572
1621
  limit: { type: GraphQLInt2 }
1573
1622
  },
1574
1623
  resolve,
1624
+ ...relationDocs,
1575
1625
  ...cacheCtx.complexity ? { extensions: { complexity: listFieldComplexity(cacheCtx.complexity) } } : {}
1576
1626
  }
1577
1627
  ]);
@@ -1619,7 +1669,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1619
1669
  relationFields: {}
1620
1670
  };
1621
1671
  };
1622
- var generateTableTypes = (tableName, tables, relationMap, withReturning, relationsDepthLimit, cacheCtx, typeNameMapper = void 0, insertPrefix = "create", updatePrefix = "update", resolverFactory, relationAggregateFactory) => {
1672
+ var generateTableTypes = (tableName, tables, relationMap, withReturning, relationsDepthLimit, cacheCtx, typeNameMapper = void 0, insertPrefix = "create", updatePrefix = "update", resolverFactory, relationAggregateFactory, nestedWrites) => {
1623
1673
  const { tableFields, relationFields, filters, order } = generateSelectFields(
1624
1674
  tables,
1625
1675
  tableName,
@@ -1640,28 +1690,44 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
1640
1690
  const table = tables[tableName];
1641
1691
  const columns = getColumns(table);
1642
1692
  const columnEntries = Object.entries(columns);
1693
+ const relaxedColumns = nestedWrites?.relaxedColumns(tableName);
1643
1694
  const insertFields = Object.fromEntries(
1644
- columnEntries.map(([columnName, columnDescription]) => [
1645
- columnName,
1646
- drizzleColumnToGraphQLType(columnDescription, columnName, tableName, false, true, true)
1647
- ])
1695
+ columnEntries.map(([columnName, column]) => {
1696
+ const converted = drizzleColumnToGraphQLType(
1697
+ column,
1698
+ columnName,
1699
+ tableName,
1700
+ !!relaxedColumns?.has(columnName),
1701
+ true,
1702
+ true
1703
+ );
1704
+ return [
1705
+ columnName,
1706
+ { ...converted, ...inputFieldDocs(cacheCtx.docs, column, tableName, columnName, converted.type) }
1707
+ ];
1708
+ })
1648
1709
  );
1649
1710
  const updateFields = Object.fromEntries(
1650
- columnEntries.map(([columnName, columnDescription]) => [
1651
- columnName,
1652
- drizzleColumnToGraphQLType(columnDescription, columnName, tableName, true, false, true)
1653
- ])
1711
+ columnEntries.map(([columnName, column]) => {
1712
+ const converted = drizzleColumnToGraphQLType(column, columnName, tableName, true, false, true);
1713
+ return [
1714
+ columnName,
1715
+ { ...converted, ...inputFieldDocs(cacheCtx.docs, column, tableName, columnName, converted.type) }
1716
+ ];
1717
+ })
1654
1718
  );
1719
+ const typeName = resolveTypeName(tableName, typeNameMapper);
1655
1720
  const insertInput = new GraphQLInputObjectType2({
1656
- name: `${capitalize(insertPrefix)}${resolveTypeName(tableName, typeNameMapper)}Input`,
1657
- fields: insertFields
1721
+ name: `${capitalize(insertPrefix)}${typeName}Input`,
1722
+ fields: nestedWrites ? () => ({ ...insertFields, ...nestedWrites.createFields(tableName, typeName) }) : insertFields
1658
1723
  });
1659
1724
  const updateInput = new GraphQLInputObjectType2({
1660
- name: `${capitalize(updatePrefix)}${resolveTypeName(tableName, typeNameMapper)}Input`,
1661
- fields: updateFields
1725
+ name: `${capitalize(updatePrefix)}${typeName}Input`,
1726
+ fields: nestedWrites ? () => ({ ...updateFields, ...nestedWrites.updateFields(tableName, typeName) }) : updateFields
1662
1727
  });
1663
1728
  const selectSingleOutput = cacheCtx.objectTypeCache.get(tableName) ?? new GraphQLObjectType2({
1664
1729
  name: resolveTypeName(tableName, typeNameMapper),
1730
+ description: cacheCtx.docs.describeTable?.(tableName),
1665
1731
  fields: { ...tableFields, ...relationFields }
1666
1732
  });
1667
1733
  const selectArrOutput = new GraphQLNonNull2(new GraphQLList2(new GraphQLNonNull2(selectSingleOutput)));
@@ -2053,6 +2119,13 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
2053
2119
  if (!field) {
2054
2120
  continue;
2055
2121
  }
2122
+ const selectionCount = Object.values(baseField).reduce(
2123
+ (n, f) => n + (f.name === relName ? 1 : 0),
2124
+ 0
2125
+ );
2126
+ if (selectionCount > 1) {
2127
+ continue;
2128
+ }
2056
2129
  const relField = field?.fieldsByTypeName;
2057
2130
  const relFieldSelection = relField?.[relTypeName];
2058
2131
  if (!relFieldSelection) {
@@ -2061,7 +2134,8 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
2061
2134
  const columns = extractSelectedColumnsFromTree(relFieldSelection, tables[targetTableName], {
2062
2135
  tableName: targetTableName,
2063
2136
  relationMap,
2064
- tables
2137
+ tables,
2138
+ allRelations: filterCtx?.relationMap
2065
2139
  });
2066
2140
  const thisRecord = {};
2067
2141
  thisRecord.columns = columns;
@@ -2667,7 +2741,8 @@ var runRelationalSelect = async (opts) => {
2667
2741
  columns: extractSelectedColumnsFromTree(parsedInfo.fieldsByTypeName[typeName], table, {
2668
2742
  tableName,
2669
2743
  relationMap,
2670
- tables
2744
+ tables,
2745
+ allRelations: filterCtx?.relationMap
2671
2746
  }),
2672
2747
  offset: distinctKeys ? void 0 : offset,
2673
2748
  // drizzle-orm v1 RQB calls orderBy/where with the aliased table proxy — use it
@@ -2879,9 +2954,9 @@ var generateAggregateTypes = (table, tableName, typeName, cacheCtx) => {
2879
2954
  type: new GraphQLObjectType3({
2880
2955
  name: `${typeName}${capitalize(op)}Aggregate`,
2881
2956
  fields: Object.fromEntries(
2882
- Object.entries(orderable).map(([columnName, { converted }]) => [
2957
+ Object.entries(orderable).map(([columnName, { column, converted }]) => [
2883
2958
  columnName,
2884
- { type: converted.type, description: converted.description }
2959
+ { type: converted.type, ...columnDocs(cacheCtx?.docs ?? {}, column, tableName, columnName) }
2885
2960
  ])
2886
2961
  )
2887
2962
  })
@@ -2928,7 +3003,7 @@ var aggregateTarget = (table, tableName, typeName) => {
2928
3003
  typeName,
2929
3004
  columns: getColumns2(table),
2930
3005
  dateTimeColumns: new Set(
2931
- Object.entries(orderable).filter(([, { converted }]) => converted.description === "DateTime").map(([columnName]) => columnName)
3006
+ Object.entries(orderable).filter(([, { converted }]) => converted.typeLabel === "DateTime").map(([columnName]) => columnName)
2932
3007
  )
2933
3008
  };
2934
3009
  };
@@ -3146,9 +3221,9 @@ var generateGroupByType = (table, tableName, typeName, cacheCtx) => {
3146
3221
  name: `${typeName}GroupKeys`,
3147
3222
  description: `The grouped column values of one ${typeName} group. A column the query did not group by is null.`,
3148
3223
  fields: Object.fromEntries(
3149
- Object.entries(groupable).map(([columnName, { converted }]) => [
3224
+ Object.entries(groupable).map(([columnName, { column, converted }]) => [
3150
3225
  columnName,
3151
- { type: converted.type, description: converted.description }
3226
+ { type: converted.type, ...columnDocs(cacheCtx?.docs ?? {}, column, tableName, columnName) }
3152
3227
  ])
3153
3228
  )
3154
3229
  });
@@ -3548,7 +3623,13 @@ var generateSchemaData = (db, schema, relations, options) => {
3548
3623
  "Drizzle-GraphQL Error: No tables detected in Drizzle-ORM's database instance. Did you forget to pass schema to drizzle constructor?"
3549
3624
  );
3550
3625
  }
3626
+ if (features.nestedWrites) {
3627
+ throw new Error(
3628
+ "Drizzle-GraphQL Error: features.nestedWrites is not supported on MySQL \u2014 a nested write needs the parent row it just inserted returned to it, and MySQL has no RETURNING clause."
3629
+ );
3630
+ }
3551
3631
  registerScalarOverrides(tables, options);
3632
+ registerEnumConfig(options);
3552
3633
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
3553
3634
  attachTargetPrimaryKeys(namedRelations, tables, mysqlPrimaryKeyPropNames);
3554
3635
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
@@ -3566,7 +3647,8 @@ var generateSchemaData = (db, schema, relations, options) => {
3566
3647
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
3567
3648
  listRelationFilterCache: /* @__PURE__ */ new Map(),
3568
3649
  aggregateTypeCache: /* @__PURE__ */ new Map(),
3569
- complexity
3650
+ complexity,
3651
+ docs: options.docs ?? {}
3570
3652
  };
3571
3653
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
3572
3654
  const queries = {};
@@ -3858,14 +3940,399 @@ var generateSchemaData = (db, schema, relations, options) => {
3858
3940
  };
3859
3941
 
3860
3942
  // src/util/builders/pg.ts
3861
- import { and as and3, getColumns as getColumns3, is as is5, One as One4 } from "drizzle-orm";
3943
+ import { and as and4, getColumns as getColumns4, is as is6, One as One5 } from "drizzle-orm";
3862
3944
  import { getTableConfig as getTableConfig2, PgTable } from "drizzle-orm/pg-core";
3863
3945
  import {
3946
+ GraphQLError as GraphQLError7,
3947
+ GraphQLList as GraphQLList6,
3948
+ GraphQLNonNull as GraphQLNonNull6
3949
+ } from "graphql";
3950
+ import { parseResolveInfo as parseResolveInfo3 } from "graphql-parse-resolve-info";
3951
+
3952
+ // src/util/builders/nested-writes.ts
3953
+ import { and as and3, eq as eq3, getColumns as getColumns3, is as is5, One as One4 } from "drizzle-orm";
3954
+ import {
3955
+ GraphQLBoolean as GraphQLBoolean4,
3864
3956
  GraphQLError as GraphQLError6,
3957
+ GraphQLInputObjectType as GraphQLInputObjectType4,
3865
3958
  GraphQLList as GraphQLList5,
3866
3959
  GraphQLNonNull as GraphQLNonNull5
3867
3960
  } from "graphql";
3868
- import { parseResolveInfo as parseResolveInfo3 } from "graphql-parse-resolve-info";
3961
+ var isOptionalOnInsert = (column) => !column.notNull || !!column.hasDefault || !!column.defaultFn;
3962
+ var buildNestedWritePlans = (tables, relationMap, resolveUniqueSets, resolvePrimaryKeys, extractJoinColumns) => {
3963
+ const uniqueCache = /* @__PURE__ */ new Map();
3964
+ const singleColumnUniques = (tableName, table) => {
3965
+ let cached = uniqueCache.get(tableName);
3966
+ if (!cached) {
3967
+ cached = new Set(
3968
+ resolveUniqueSets(table).filter((set) => set.length === 1).map((set) => set[0])
3969
+ );
3970
+ uniqueCache.set(tableName, cached);
3971
+ }
3972
+ return cached;
3973
+ };
3974
+ const pkCache = /* @__PURE__ */ new Map();
3975
+ const singleColumnPk = (tableName, table) => {
3976
+ if (!pkCache.has(tableName)) {
3977
+ const pk = resolvePrimaryKeys(table);
3978
+ pkCache.set(tableName, pk.length === 1 ? pk[0] : void 0);
3979
+ }
3980
+ return pkCache.get(tableName);
3981
+ };
3982
+ const plans = {};
3983
+ for (const [tableName, relations] of Object.entries(relationMap)) {
3984
+ const table = tables[tableName];
3985
+ if (!table) {
3986
+ continue;
3987
+ }
3988
+ const tablePlans = {};
3989
+ for (const [relationName, relEntry] of Object.entries(relations)) {
3990
+ const relation = relEntry.relation;
3991
+ if (relation.through) {
3992
+ continue;
3993
+ }
3994
+ const targetTableName = relEntry.targetTableName;
3995
+ const targetTable = tables[targetTableName];
3996
+ if (!targetTable) {
3997
+ continue;
3998
+ }
3999
+ const joinColumns = extractJoinColumns(relEntry, table, targetTable);
4000
+ if (!joinColumns) {
4001
+ continue;
4002
+ }
4003
+ const { localColPropName, foreignCol, foreignColPropName } = joinColumns;
4004
+ const localCol = getColumns3(table)[localColPropName];
4005
+ if (!localCol) {
4006
+ continue;
4007
+ }
4008
+ const isOne = is5(relation, One4);
4009
+ const localIsPk = singleColumnPk(tableName, table) === localColPropName;
4010
+ const foreignIsPk = singleColumnPk(targetTableName, targetTable) === foreignColPropName;
4011
+ const localIsUnique = singleColumnUniques(tableName, table).has(localColPropName);
4012
+ const foreignIsUnique = singleColumnUniques(targetTableName, targetTable).has(foreignColPropName);
4013
+ let fkSide;
4014
+ if (!isOne) {
4015
+ fkSide = "child";
4016
+ } else if (foreignIsPk && !localIsPk) {
4017
+ fkSide = "parent";
4018
+ } else if (localIsPk) {
4019
+ fkSide = "child";
4020
+ } else if (foreignIsUnique) {
4021
+ fkSide = "parent";
4022
+ } else if (localIsUnique) {
4023
+ fkSide = "child";
4024
+ } else {
4025
+ continue;
4026
+ }
4027
+ const fkColumn = fkSide === "child" ? foreignCol : localCol;
4028
+ tablePlans[relationName] = {
4029
+ relationName,
4030
+ targetTableName,
4031
+ targetTable,
4032
+ localColPropName,
4033
+ foreignColPropName,
4034
+ foreignCol,
4035
+ localCol,
4036
+ isOne,
4037
+ fkSide,
4038
+ canDetach: !fkColumn.notNull
4039
+ };
4040
+ }
4041
+ if (Object.keys(tablePlans).length) {
4042
+ plans[tableName] = tablePlans;
4043
+ }
4044
+ }
4045
+ return plans;
4046
+ };
4047
+ var NO_COLUMNS = /* @__PURE__ */ new Set();
4048
+ var createNestedWriteTypes = (params) => {
4049
+ const { plans, cacheCtx, typeNameMapper, insertPrefix } = params;
4050
+ const wrapperCache = /* @__PURE__ */ new Map();
4051
+ const payloadCache = /* @__PURE__ */ new Map();
4052
+ const payloadType = (tableName, typeName, plan) => {
4053
+ const key = `${tableName}.${plan.relationName}`;
4054
+ const cached = payloadCache.get(key);
4055
+ if (cached) {
4056
+ return cached;
4057
+ }
4058
+ const omitted = plan.fkSide === "child" ? plan.foreignColPropName : void 0;
4059
+ const fields = Object.fromEntries(
4060
+ Object.entries(getColumns3(plan.targetTable)).filter(([columnName]) => columnName !== omitted).map(([columnName, column]) => [
4061
+ columnName,
4062
+ drizzleColumnToGraphQLType(column, columnName, plan.targetTableName, false, true, true)
4063
+ ])
4064
+ );
4065
+ const type = new GraphQLInputObjectType4({
4066
+ name: `${capitalize(insertPrefix)}${typeName}${capitalize(plan.relationName)}Input`,
4067
+ description: omitted === void 0 ? `A new ${resolveTypeName(plan.targetTableName, typeNameMapper)} row for ${typeName}.${plan.relationName}` : `A new ${resolveTypeName(plan.targetTableName, typeNameMapper)} row for ${typeName}.${plan.relationName}. \`${omitted}\` is set from the ${typeName} row this is written with.`,
4068
+ fields
4069
+ });
4070
+ payloadCache.set(key, type);
4071
+ return type;
4072
+ };
4073
+ const targetFilters = (plan) => cacheCtx.filterTypeCache.get(plan.targetTable);
4074
+ const listOf = (type) => new GraphQLList5(new GraphQLNonNull5(type));
4075
+ const wrapperType = (tableName, typeName, plan, forUpdate) => {
4076
+ const key = `${tableName}.${plan.relationName}.${forUpdate ? "update" : "create"}`;
4077
+ const cached = wrapperCache.get(key);
4078
+ if (cached) {
4079
+ return cached;
4080
+ }
4081
+ const filters = targetFilters(plan);
4082
+ const payload = payloadType(tableName, typeName, plan);
4083
+ const targetTypeName = resolveTypeName(plan.targetTableName, typeNameMapper);
4084
+ const fields = {};
4085
+ if (plan.isOne) {
4086
+ fields["create"] = { type: payload, description: `Insert a ${targetTypeName} row and attach it` };
4087
+ if (filters) {
4088
+ fields["connect"] = {
4089
+ type: filters,
4090
+ description: `Attach the existing ${targetTypeName} row this matches. Must match exactly one row.`
4091
+ };
4092
+ }
4093
+ if (forUpdate && plan.canDetach) {
4094
+ fields["disconnect"] = {
4095
+ type: GraphQLBoolean4,
4096
+ description: `Detach the currently attached ${targetTypeName} row, leaving it in place`
4097
+ };
4098
+ }
4099
+ } else {
4100
+ fields["create"] = { type: listOf(payload), description: `Insert these ${targetTypeName} rows and attach them` };
4101
+ if (filters) {
4102
+ fields["connect"] = {
4103
+ type: listOf(filters),
4104
+ description: `Attach every existing ${targetTypeName} row these match`
4105
+ };
4106
+ if (forUpdate && plan.canDetach) {
4107
+ fields["disconnect"] = {
4108
+ type: listOf(filters),
4109
+ description: `Detach every attached ${targetTypeName} row these match, leaving the rows in place`
4110
+ };
4111
+ fields["set"] = {
4112
+ type: listOf(filters),
4113
+ description: `Replace the whole set: detach everything attached, then attach every ${targetTypeName} row these match. Applied before \`disconnect\`, \`connect\` and \`create\`.`
4114
+ };
4115
+ }
4116
+ }
4117
+ }
4118
+ const type = new GraphQLInputObjectType4({
4119
+ name: `${typeName}${capitalize(plan.relationName)}Nested${forUpdate ? "Update" : "Create"}Input`,
4120
+ description: `Writes through ${typeName}.${plan.relationName}`,
4121
+ fields
4122
+ });
4123
+ wrapperCache.set(key, type);
4124
+ return type;
4125
+ };
4126
+ const relationFields = (tableName, typeName, forUpdate) => {
4127
+ const tablePlans = plans[tableName];
4128
+ if (!tablePlans) {
4129
+ return {};
4130
+ }
4131
+ return Object.fromEntries(
4132
+ Object.values(tablePlans).flatMap((plan) => {
4133
+ const wrapper = wrapperType(tableName, typeName, plan, forUpdate);
4134
+ return wrapper ? [[plan.relationName, { type: wrapper, description: `Writes through ${typeName}.${plan.relationName}` }]] : [];
4135
+ })
4136
+ );
4137
+ };
4138
+ return {
4139
+ createFields: (tableName, typeName) => relationFields(tableName, typeName, false),
4140
+ updateFields: (tableName, typeName) => relationFields(tableName, typeName, true),
4141
+ relaxedColumns: (tableName) => {
4142
+ const tablePlans = plans[tableName];
4143
+ if (!tablePlans) {
4144
+ return NO_COLUMNS;
4145
+ }
4146
+ const relaxed = /* @__PURE__ */ new Set();
4147
+ for (const plan of Object.values(tablePlans)) {
4148
+ if (plan.fkSide === "parent" && !isOptionalOnInsert(plan.localCol)) {
4149
+ relaxed.add(plan.localColPropName);
4150
+ }
4151
+ }
4152
+ return relaxed.size ? relaxed : NO_COLUMNS;
4153
+ }
4154
+ };
4155
+ };
4156
+ var mergedOps = (entries) => Object.assign({}, ...entries.map((entry) => entry.ops));
4157
+ var asArray = (value) => Array.isArray(value) ? value : value === void 0 ? [] : [value];
4158
+ var createNestedWriteRuntime = (params) => {
4159
+ const { plans, filterCtx } = params;
4160
+ const conditionOf = (plan, filter, operation) => {
4161
+ const condition = extractFilters(
4162
+ plan.targetTable,
4163
+ plan.targetTableName,
4164
+ filter,
4165
+ relationFilterCtx(filterCtx, plan.targetTableName)
4166
+ );
4167
+ if (!condition) {
4168
+ throw new GraphQLError6(
4169
+ `Drizzle-GraphQL Error: '${operation}' on '${plan.relationName}' needs a filter that selects rows \u2014 it was given one that matches everything.`
4170
+ );
4171
+ }
4172
+ return condition;
4173
+ };
4174
+ const assertSingleOperation = (plan, op) => {
4175
+ const supplied = ["create", "connect", "disconnect"].filter((key) => op[key] !== void 0 && op[key] !== null);
4176
+ if (supplied.length > 1) {
4177
+ throw new GraphQLError6(
4178
+ `Drizzle-GraphQL Error: '${plan.relationName}' takes one of ${supplied.join(", ")} at a time \u2014 it holds a single row.`
4179
+ );
4180
+ }
4181
+ };
4182
+ const detachAll = async (executor, plan, key) => executor.update(plan.targetTable).set({ [plan.foreignColPropName]: null }).where(eq3(plan.foreignCol, key));
4183
+ return {
4184
+ enabled: (tableName) => !!plans[tableName],
4185
+ split: (tableName, values) => {
4186
+ const tablePlans = plans[tableName];
4187
+ if (!tablePlans) {
4188
+ return { columns: values, ops: {} };
4189
+ }
4190
+ const columns = {};
4191
+ const ops = {};
4192
+ for (const [key, value] of Object.entries(values)) {
4193
+ if (tablePlans[key] && value !== void 0 && value !== null) {
4194
+ ops[key] = value;
4195
+ } else if (!tablePlans[key]) {
4196
+ columns[key] = value;
4197
+ }
4198
+ }
4199
+ return { columns, ops };
4200
+ },
4201
+ hasOps: (ops) => Object.keys(ops).length > 0,
4202
+ withJoinColumns: (tableName, ops, columns, table) => {
4203
+ const tablePlans = plans[tableName];
4204
+ if (!tablePlans) {
4205
+ return columns;
4206
+ }
4207
+ const allColumns = getColumns3(table);
4208
+ for (const relationName of Object.keys(ops)) {
4209
+ const plan = tablePlans[relationName];
4210
+ if (plan?.fkSide === "child" && !(plan.localColPropName in columns) && allColumns[plan.localColPropName]) {
4211
+ columns[plan.localColPropName] = allColumns[plan.localColPropName];
4212
+ }
4213
+ }
4214
+ return columns;
4215
+ },
4216
+ applyParentSide: async (executor, tableName, ops) => {
4217
+ const tablePlans = plans[tableName];
4218
+ const patch = {};
4219
+ if (!tablePlans) {
4220
+ return patch;
4221
+ }
4222
+ for (const [relationName, op] of Object.entries(ops)) {
4223
+ const plan = tablePlans[relationName];
4224
+ if (!plan || plan.fkSide !== "parent") {
4225
+ continue;
4226
+ }
4227
+ assertSingleOperation(plan, op);
4228
+ if (op["create"] !== void 0) {
4229
+ const values = remapFromGraphQLSingleInput({ ...op["create"] }, plan.targetTable);
4230
+ const inserted = await executor.insert(plan.targetTable).values(values).returning();
4231
+ const created = inserted[0];
4232
+ if (!created) {
4233
+ throw new GraphQLError6(
4234
+ `Drizzle-GraphQL Error: 'create' on '${relationName}' inserted no row, so there is nothing to attach.`
4235
+ );
4236
+ }
4237
+ patch[plan.localColPropName] = created[plan.foreignColPropName];
4238
+ } else if (op["connect"] !== void 0) {
4239
+ const rows = await executor.select().from(plan.targetTable).where(conditionOf(plan, op["connect"], "connect"));
4240
+ if (rows.length !== 1) {
4241
+ throw new GraphQLError6(
4242
+ `Drizzle-GraphQL Error: 'connect' on '${relationName}' matched ${rows.length} rows \u2014 it attaches a single row, so its filter must match exactly one.`
4243
+ );
4244
+ }
4245
+ patch[plan.localColPropName] = rows[0][plan.foreignColPropName];
4246
+ } else if (op["disconnect"] === true) {
4247
+ patch[plan.localColPropName] = null;
4248
+ }
4249
+ }
4250
+ return patch;
4251
+ },
4252
+ applyChildSide: async (executor, tableName, ops, parentRows) => {
4253
+ const tablePlans = plans[tableName];
4254
+ if (!tablePlans) {
4255
+ return;
4256
+ }
4257
+ for (const [relationName, op] of Object.entries(ops)) {
4258
+ const plan = tablePlans[relationName];
4259
+ if (!plan || plan.fkSide !== "child") {
4260
+ continue;
4261
+ }
4262
+ if (plan.isOne) {
4263
+ assertSingleOperation(plan, op);
4264
+ }
4265
+ for (const parentRow of parentRows) {
4266
+ const key = parentRow?.[plan.localColPropName];
4267
+ if (key === void 0 || key === null) {
4268
+ throw new GraphQLError6(
4269
+ `Drizzle-GraphQL Error: cannot write through '${relationName}': the ${tableName} row has no '${plan.localColPropName}' value to attach to.`
4270
+ );
4271
+ }
4272
+ if (op["set"] !== void 0) {
4273
+ await detachAll(executor, plan, key);
4274
+ for (const filter of asArray(op["set"])) {
4275
+ await executor.update(plan.targetTable).set({ [plan.foreignColPropName]: key }).where(conditionOf(plan, filter, "set"));
4276
+ }
4277
+ }
4278
+ if (op["disconnect"] !== void 0) {
4279
+ if (plan.isOne) {
4280
+ if (op["disconnect"] === true) {
4281
+ await detachAll(executor, plan, key);
4282
+ }
4283
+ } else {
4284
+ for (const filter of asArray(op["disconnect"])) {
4285
+ await executor.update(plan.targetTable).set({ [plan.foreignColPropName]: null }).where(and3(eq3(plan.foreignCol, key), conditionOf(plan, filter, "disconnect")));
4286
+ }
4287
+ }
4288
+ }
4289
+ const attaches = op["connect"] !== void 0 || op["create"] !== void 0;
4290
+ if (plan.isOne && attaches && plan.canDetach && op["set"] === void 0) {
4291
+ await detachAll(executor, plan, key);
4292
+ }
4293
+ if (op["connect"] !== void 0) {
4294
+ for (const filter of asArray(op["connect"])) {
4295
+ await executor.update(plan.targetTable).set({ [plan.foreignColPropName]: key }).where(conditionOf(plan, filter, "connect"));
4296
+ }
4297
+ }
4298
+ if (op["create"] !== void 0) {
4299
+ const rows = asArray(op["create"]).map((row) => ({
4300
+ ...remapFromGraphQLSingleInput({ ...row }, plan.targetTable),
4301
+ [plan.foreignColPropName]: key
4302
+ }));
4303
+ if (rows.length) {
4304
+ await executor.insert(plan.targetTable).values(rows);
4305
+ }
4306
+ }
4307
+ }
4308
+ }
4309
+ }
4310
+ };
4311
+ };
4312
+ var writeWithNestedOps = async (params) => {
4313
+ const { executor, runtime, tableName, entries, remapValues, write } = params;
4314
+ return executor.transaction(async (tx) => {
4315
+ const rows = [];
4316
+ for (const entry of entries) {
4317
+ const patch = await runtime.applyParentSide(tx, tableName, entry.ops);
4318
+ const written = await write(tx, { ...remapValues(entry.columns), ...patch });
4319
+ await runtime.applyChildSide(tx, tableName, entry.ops, written);
4320
+ rows.push(...written);
4321
+ }
4322
+ return rows;
4323
+ });
4324
+ };
4325
+ var updateWithNestedOps = async (params) => {
4326
+ const { executor, runtime, tableName, columns, ops, remapValues, write } = params;
4327
+ return executor.transaction(async (tx) => {
4328
+ const patch = await runtime.applyParentSide(tx, tableName, ops);
4329
+ const rows = await write(tx, { ...remapValues(columns), ...patch });
4330
+ await runtime.applyChildSide(tx, tableName, ops, rows);
4331
+ return rows;
4332
+ });
4333
+ };
4334
+
4335
+ // src/util/builders/pg.ts
3869
4336
  var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
3870
4337
  const queryBase = db.query[tableName];
3871
4338
  const table = tables[tableName];
@@ -3910,24 +4377,24 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
3910
4377
  let cursorEntries;
3911
4378
  if (after != null || cursorSelected) {
3912
4379
  if (after != null && distinct?.length) {
3913
- throw new GraphQLError6("'after' cannot be combined with 'distinct'.");
4380
+ throw new GraphQLError7("'after' cannot be combined with 'distinct'.");
3914
4381
  }
3915
4382
  if (orderByHasRelationEntry(orderBy)) {
3916
4383
  if (after != null) {
3917
- throw new GraphQLError6(
4384
+ throw new GraphQLError7(
3918
4385
  "'after' cannot be combined with an orderBy that orders through a relation \u2014 a related row's value cannot be encoded into a cursor."
3919
4386
  );
3920
4387
  }
3921
4388
  } else if (!pkNames.length) {
3922
4389
  if (after != null) {
3923
- throw new GraphQLError6(
4390
+ throw new GraphQLError7(
3924
4391
  `Table ${tableName} has no primary key, so cursor pagination cannot be used on it.`
3925
4392
  );
3926
4393
  }
3927
4394
  } else {
3928
4395
  cursorEntries = cursorOrderingEntries(orderBy, pkNames);
3929
4396
  if (cursorSelected) {
3930
- const allColumns = getColumns3(table);
4397
+ const allColumns = getColumns4(table);
3931
4398
  for (const [column] of cursorEntries) {
3932
4399
  selectedColumnsSql[column] ??= allColumns[column];
3933
4400
  }
@@ -3936,7 +4403,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
3936
4403
  }
3937
4404
  const cursorCondition = after != null && cursorEntries ? buildCursorCondition(table, cursorEntries, decodeCursor(after, cursorEntries), "nulls-largest") : void 0;
3938
4405
  const baseWhereSql = where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0;
3939
- const whereSql = cursorCondition ? and3(baseWhereSql, cursorCondition) : baseWhereSql;
4406
+ const whereSql = cursorCondition ? and4(baseWhereSql, cursorCondition) : baseWhereSql;
3940
4407
  let distinctKeys;
3941
4408
  if (distinct?.length) {
3942
4409
  distinctKeys = await selectDistinctKeys({
@@ -4047,10 +4514,10 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
4047
4514
  };
4048
4515
  };
4049
4516
  var pgPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig2);
4050
- var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
4517
+ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4051
4518
  const queryArgs = {
4052
4519
  values: {
4053
- type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(baseType)))
4520
+ type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(baseType)))
4054
4521
  }
4055
4522
  };
4056
4523
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4059,10 +4526,12 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
4059
4526
  resolver: async (_source, args, context, info) => {
4060
4527
  try {
4061
4528
  return await runMutation(db, context, info, txCtx, async (executor) => {
4062
- const input = remapFromGraphQLArrayInput(args.values, table);
4063
- if (!input.length) {
4064
- throw new GraphQLError6("No values were provided!");
4529
+ if (!args.values.length) {
4530
+ throw new GraphQLError7("No values were provided!");
4065
4531
  }
4532
+ const entries = nested?.enabled(tableName) ? args.values.map((values) => nested.split(tableName, values)) : void 0;
4533
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
4534
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : args.values, table);
4066
4535
  const parsedInfo = parseResolveInfo3(info, {
4067
4536
  deep: true
4068
4537
  });
@@ -4076,11 +4545,22 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
4076
4545
  pkNames,
4077
4546
  parsedInfo
4078
4547
  });
4079
- let query = executor.insert(table).values(input).returning(columns);
4080
- if (conflictDoNothing) {
4081
- query = query.onConflictDoNothing();
4082
- }
4083
- const result = await query;
4548
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
4549
+ const runInsert = async (target, values) => {
4550
+ let query = target.insert(table).values(values).returning(returning);
4551
+ if (conflictDoNothing) {
4552
+ query = query.onConflictDoNothing();
4553
+ }
4554
+ return await query;
4555
+ };
4556
+ const result = nestedEntries ? await writeWithNestedOps({
4557
+ executor,
4558
+ runtime: nested,
4559
+ tableName,
4560
+ entries: nestedEntries,
4561
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
4562
+ write: (tx, values) => runInsert(tx, [values])
4563
+ }) : await runInsert(executor, input);
4084
4564
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
4085
4565
  return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
4086
4566
  });
@@ -4091,10 +4571,10 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
4091
4571
  args: queryArgs
4092
4572
  };
4093
4573
  };
4094
- var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
4574
+ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4095
4575
  const queryArgs = {
4096
4576
  values: {
4097
- type: new GraphQLNonNull5(baseType)
4577
+ type: new GraphQLNonNull6(baseType)
4098
4578
  }
4099
4579
  };
4100
4580
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4103,7 +4583,9 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
4103
4583
  resolver: async (_source, args, context, info) => {
4104
4584
  try {
4105
4585
  return await runMutation(db, context, info, txCtx, async (executor) => {
4106
- const input = remapFromGraphQLSingleInput(args.values, table);
4586
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, args.values) : void 0;
4587
+ const nestedEntry = entry && nested.hasOps(entry.ops) ? entry : void 0;
4588
+ const input = nestedEntry ? {} : remapFromGraphQLSingleInput(entry ? entry.columns : args.values, table);
4107
4589
  const parsedInfo = parseResolveInfo3(info, {
4108
4590
  deep: true
4109
4591
  });
@@ -4117,11 +4599,22 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
4117
4599
  pkNames,
4118
4600
  parsedInfo
4119
4601
  });
4120
- let query = executor.insert(table).values(input).returning(columns);
4121
- if (conflictDoNothing) {
4122
- query = query.onConflictDoNothing();
4123
- }
4124
- const result = await query;
4602
+ const returning = nestedEntry ? nested.withJoinColumns(tableName, nestedEntry.ops, { ...columns }, table) : columns;
4603
+ const runInsert = async (target, values) => {
4604
+ let query = target.insert(table).values(values).returning(returning);
4605
+ if (conflictDoNothing) {
4606
+ query = query.onConflictDoNothing();
4607
+ }
4608
+ return await query;
4609
+ };
4610
+ const result = nestedEntry ? await writeWithNestedOps({
4611
+ executor,
4612
+ runtime: nested,
4613
+ tableName,
4614
+ entries: [nestedEntry],
4615
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
4616
+ write: runInsert
4617
+ }) : await runInsert(executor, input);
4125
4618
  if (!result[0]) {
4126
4619
  return void 0;
4127
4620
  }
@@ -4135,10 +4628,10 @@ var generateInsertSingle2 = (db, tableName, table, tables, relationMap, baseType
4135
4628
  args: queryArgs
4136
4629
  };
4137
4630
  };
4138
- var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx) => {
4631
+ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx, nested) => {
4139
4632
  const queryArgs = {
4140
4633
  values: {
4141
- type: single ? new GraphQLNonNull5(baseType) : new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(baseType)))
4634
+ type: single ? new GraphQLNonNull6(baseType) : new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(baseType)))
4142
4635
  },
4143
4636
  onConflict: {
4144
4637
  type: onConflictType,
@@ -4151,10 +4644,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
4151
4644
  resolver: async (_source, args, context, info) => {
4152
4645
  try {
4153
4646
  return await runMutation(db, context, info, txCtx, async (executor) => {
4154
- const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
4155
- if (!input.length) {
4156
- throw new GraphQLError6("No values were provided!");
4647
+ const supplied = single ? [args.values] : args.values;
4648
+ if (!supplied.length) {
4649
+ throw new GraphQLError7("No values were provided!");
4157
4650
  }
4651
+ const entries = nested?.enabled(tableName) ? supplied.map((values) => nested.split(tableName, values)) : void 0;
4652
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
4653
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : supplied, table);
4158
4654
  const parsedInfo = parseResolveInfo3(info, { deep: true });
4159
4655
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
4160
4656
  relationMap,
@@ -4166,19 +4662,30 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
4166
4662
  pkNames,
4167
4663
  parsedInfo
4168
4664
  });
4169
- const plan = resolveConflictPlan({
4170
- table,
4171
- values: input,
4172
- onConflict: args.onConflict,
4173
- pkNames,
4174
- uniqueSets,
4175
- excludedRef: excludedColumnRef,
4176
- withTarget: true,
4177
- buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
4178
- });
4179
- let query = executor.insert(table).values(input).returning(columns);
4180
- query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
4181
- const result = await query;
4665
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
4666
+ const runUpsert = async (target, values) => {
4667
+ const plan = resolveConflictPlan({
4668
+ table,
4669
+ values,
4670
+ onConflict: args.onConflict,
4671
+ pkNames,
4672
+ uniqueSets,
4673
+ excludedRef: excludedColumnRef,
4674
+ withTarget: true,
4675
+ buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
4676
+ });
4677
+ let query = target.insert(table).values(values).returning(returning);
4678
+ query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
4679
+ return await query;
4680
+ };
4681
+ const result = nestedEntries ? await writeWithNestedOps({
4682
+ executor,
4683
+ runtime: nested,
4684
+ tableName,
4685
+ entries: nestedEntries,
4686
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
4687
+ write: (tx, values) => runUpsert(tx, [values])
4688
+ }) : await runUpsert(executor, input);
4182
4689
  if (single && !result[0]) {
4183
4690
  return void 0;
4184
4691
  }
@@ -4192,13 +4699,13 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
4192
4699
  args: queryArgs
4193
4700
  };
4194
4701
  };
4195
- var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx) => {
4702
+ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx, nested) => {
4196
4703
  const queryArgs = {
4197
4704
  set: {
4198
- type: new GraphQLNonNull5(setArgs)
4705
+ type: new GraphQLNonNull6(setArgs)
4199
4706
  },
4200
4707
  where: {
4201
- type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
4708
+ type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
4202
4709
  }
4203
4710
  };
4204
4711
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4221,23 +4728,37 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
4221
4728
  pkNames,
4222
4729
  parsedInfo
4223
4730
  });
4224
- const input = remapFromGraphQLSingleInput(set, table);
4225
- if (!Object.keys(input).length) {
4226
- throw new GraphQLError6("Unable to update with no values specified!");
4731
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
4732
+ const nestedOps = entry && nested.hasOps(entry.ops) ? entry.ops : void 0;
4733
+ const input = remapFromGraphQLSingleInput(entry ? entry.columns : set, table);
4734
+ if (!Object.keys(input).length && !nestedOps) {
4735
+ throw new GraphQLError7("Unable to update with no values specified!");
4227
4736
  }
4228
4737
  const relationCtx = relationFilterCtx(filterCtx, tableName);
4229
4738
  const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
4230
4739
  if (single) {
4231
4740
  await assertSingleMatch(executor, table, filters, fieldName);
4232
4741
  }
4233
- let query = executor.update(table).set(input);
4234
- if (filters) {
4235
- query = query.where(filters);
4236
- }
4237
- query = query.returning(columns);
4238
- const result = await query;
4742
+ const returning = nestedOps ? nested.withJoinColumns(tableName, nestedOps, { ...columns }, table) : columns;
4743
+ const runUpdate = async (target, values) => {
4744
+ const writes = Object.keys(values).length > 0;
4745
+ let query = writes ? target.update(table).set(values) : target.select(returning).from(table);
4746
+ if (filters) {
4747
+ query = query.where(filters);
4748
+ }
4749
+ return await (writes ? query.returning(returning) : query);
4750
+ };
4751
+ const result = nestedOps ? await updateWithNestedOps({
4752
+ executor,
4753
+ runtime: nested,
4754
+ tableName,
4755
+ columns: input,
4756
+ ops: nestedOps,
4757
+ remapValues: (values) => values,
4758
+ write: runUpdate
4759
+ }) : await runUpdate(executor, input);
4239
4760
  if (single && result.length > 1) {
4240
- throw new GraphQLError6(`${fieldName}: 'where' matched more than one row!`);
4761
+ throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
4241
4762
  }
4242
4763
  if (single && !result[0]) {
4243
4764
  return void 0;
@@ -4252,10 +4773,10 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
4252
4773
  args: queryArgs
4253
4774
  };
4254
4775
  };
4255
- var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx) => {
4776
+ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx, nested) => {
4256
4777
  const queryArgs = {
4257
4778
  updates: {
4258
- type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(updateManyInput)))
4779
+ type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(updateManyInput)))
4259
4780
  }
4260
4781
  };
4261
4782
  const pkNames = pgPrimaryKeyPropNames(table);
@@ -4266,7 +4787,7 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
4266
4787
  return await runMutation(db, context, info, txCtx, async (executor) => {
4267
4788
  const { updates } = args;
4268
4789
  if (!updates.length) {
4269
- throw new GraphQLError6("No updates were provided!");
4790
+ throw new GraphQLError7("No updates were provided!");
4270
4791
  }
4271
4792
  const parsedInfo = parseResolveInfo3(info, {
4272
4793
  deep: true
@@ -4282,23 +4803,40 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
4282
4803
  parsedInfo
4283
4804
  });
4284
4805
  const entries = updates.map(({ where, set }) => {
4285
- const input = remapFromGraphQLSingleInput(set, table);
4286
- if (!Object.keys(input).length) {
4287
- throw new GraphQLError6("Unable to update with no values specified!");
4806
+ const split = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
4807
+ const ops = split && nested.hasOps(split.ops) ? split.ops : void 0;
4808
+ const input = remapFromGraphQLSingleInput(split ? split.columns : set, table);
4809
+ if (!Object.keys(input).length && !ops) {
4810
+ throw new GraphQLError7("Unable to update with no values specified!");
4288
4811
  }
4289
4812
  return {
4290
4813
  set: input,
4814
+ ops,
4291
4815
  filters: where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
4292
4816
  };
4293
4817
  });
4818
+ const returning = entries.some((entry) => entry.ops) ? nested.withJoinColumns(
4819
+ tableName,
4820
+ mergedOps(entries.map((entry) => ({ ops: entry.ops ?? {} }))),
4821
+ {
4822
+ ...columns
4823
+ },
4824
+ table
4825
+ ) : columns;
4294
4826
  const perEntry = await executor.transaction(async (tx) => {
4295
4827
  const results = [];
4296
4828
  for (const entry of entries) {
4297
- let query = tx.update(table).set(entry.set);
4829
+ const values = entry.ops ? { ...entry.set, ...await nested.applyParentSide(tx, tableName, entry.ops) } : entry.set;
4830
+ const writes = Object.keys(values).length > 0;
4831
+ let query = writes ? tx.update(table).set(values) : tx.select(returning).from(table);
4298
4832
  if (entry.filters) {
4299
4833
  query = query.where(entry.filters);
4300
4834
  }
4301
- results.push(await query.returning(columns));
4835
+ const rows = await (writes ? query.returning(returning) : query);
4836
+ if (entry.ops) {
4837
+ await nested.applyChildSide(tx, tableName, entry.ops, rows);
4838
+ }
4839
+ results.push(rows);
4302
4840
  }
4303
4841
  return results;
4304
4842
  });
@@ -4328,7 +4866,7 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
4328
4866
  var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx) => {
4329
4867
  const queryArgs = {
4330
4868
  where: {
4331
- type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
4869
+ type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
4332
4870
  }
4333
4871
  };
4334
4872
  return {
@@ -4357,7 +4895,7 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, si
4357
4895
  query = query.returning(columns);
4358
4896
  const result = await query;
4359
4897
  if (single && result.length > 1) {
4360
- throw new GraphQLError6(`${fieldName}: 'where' matched more than one row!`);
4898
+ throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
4361
4899
  }
4362
4900
  if (single) {
4363
4901
  return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
@@ -4383,7 +4921,7 @@ function generateSchemaData2(db, schema, relations, options) {
4383
4921
  complexity
4384
4922
  } = options;
4385
4923
  const schemaEntries = Object.entries(schema);
4386
- const tableEntries = schemaEntries.filter(([_key, value]) => is5(value, PgTable));
4924
+ const tableEntries = schemaEntries.filter(([_key, value]) => is6(value, PgTable));
4387
4925
  const tables = Object.fromEntries(tableEntries);
4388
4926
  if (!tableEntries.length) {
4389
4927
  throw new Error(
@@ -4391,6 +4929,7 @@ function generateSchemaData2(db, schema, relations, options) {
4391
4929
  );
4392
4930
  }
4393
4931
  registerScalarOverrides(tables, options);
4932
+ registerEnumConfig(options);
4394
4933
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
4395
4934
  attachTargetPrimaryKeys(namedRelations, tables, pgPrimaryKeyPropNames);
4396
4935
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
@@ -4408,8 +4947,18 @@ function generateSchemaData2(db, schema, relations, options) {
4408
4947
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
4409
4948
  listRelationFilterCache: /* @__PURE__ */ new Map(),
4410
4949
  aggregateTypeCache: /* @__PURE__ */ new Map(),
4411
- complexity
4950
+ complexity,
4951
+ docs: options.docs ?? {}
4412
4952
  };
4953
+ const nestedPlans = features.nestedWrites ? buildNestedWritePlans(
4954
+ tables,
4955
+ namedRelations,
4956
+ (target) => getUniqueColumnSets(target, getTableConfig2),
4957
+ (target) => pgPrimaryKeyPropNames(target),
4958
+ extractRelationJoinColumns
4959
+ ) : void 0;
4960
+ const nestedTypes = nestedPlans ? createNestedWriteTypes({ plans: nestedPlans, cacheCtx, typeNameMapper, insertPrefix: prefixes.insert }) : void 0;
4961
+ const nestedRuntime = nestedPlans ? createNestedWriteRuntime({ plans: nestedPlans, filterCtx }) : void 0;
4413
4962
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
4414
4963
  const queries = {};
4415
4964
  const mutations = {};
@@ -4428,7 +4977,8 @@ function generateSchemaData2(db, schema, relations, options) {
4428
4977
  prefixes.insert,
4429
4978
  prefixes.update,
4430
4979
  resolverFactory,
4431
- relationAggregateFactory
4980
+ relationAggregateFactory,
4981
+ nestedTypes
4432
4982
  )
4433
4983
  ])
4434
4984
  );
@@ -4489,7 +5039,8 @@ function generateSchemaData2(db, schema, relations, options) {
4489
5039
  typeName,
4490
5040
  typeNameMapper,
4491
5041
  conflictDoNothing,
4492
- mutationTxCtx
5042
+ mutationTxCtx,
5043
+ nestedRuntime
4493
5044
  ) : void 0;
4494
5045
  const insertSingleGenerated = features.insert ? generateInsertSingle2(
4495
5046
  db,
@@ -4502,7 +5053,8 @@ function generateSchemaData2(db, schema, relations, options) {
4502
5053
  typeName,
4503
5054
  typeNameMapper,
4504
5055
  conflictDoNothing,
4505
- mutationTxCtx
5056
+ mutationTxCtx,
5057
+ nestedRuntime
4506
5058
  ) : void 0;
4507
5059
  const uniqueSets = features.upsert ? getUniqueColumnSets(schema[tableName], getTableConfig2) : [];
4508
5060
  const onConflictInput = features.upsert ? generateOnConflictInput({
@@ -4526,7 +5078,8 @@ function generateSchemaData2(db, schema, relations, options) {
4526
5078
  false,
4527
5079
  typeNameMapper,
4528
5080
  filterCtx,
4529
- mutationTxCtx
5081
+ mutationTxCtx,
5082
+ nestedRuntime
4530
5083
  ) : void 0;
4531
5084
  const upsertSingleGenerated = onConflictInput ? generateUpsert2(
4532
5085
  db,
@@ -4542,7 +5095,8 @@ function generateSchemaData2(db, schema, relations, options) {
4542
5095
  true,
4543
5096
  typeNameMapper,
4544
5097
  filterCtx,
4545
- mutationTxCtx
5098
+ mutationTxCtx,
5099
+ nestedRuntime
4546
5100
  ) : void 0;
4547
5101
  const updateGenerated = features.update ? generateUpdate2(
4548
5102
  db,
@@ -4558,7 +5112,8 @@ function generateSchemaData2(db, schema, relations, options) {
4558
5112
  features.requireWhere,
4559
5113
  typeNameMapper,
4560
5114
  filterCtx,
4561
- mutationTxCtx
5115
+ mutationTxCtx,
5116
+ nestedRuntime
4562
5117
  ) : void 0;
4563
5118
  const updateSingleGenerated = features.update ? generateUpdate2(
4564
5119
  db,
@@ -4574,7 +5129,8 @@ function generateSchemaData2(db, schema, relations, options) {
4574
5129
  features.requireWhere,
4575
5130
  typeNameMapper,
4576
5131
  filterCtx,
4577
- mutationTxCtx
5132
+ mutationTxCtx,
5133
+ nestedRuntime
4578
5134
  ) : void 0;
4579
5135
  const updateManyInput = features.update && features.updateMany ? generateUpdateManyInput({ typeName, updatePrefix: prefixes.update, updateInput, tableFilters }) : void 0;
4580
5136
  const updateManyGenerated = updateManyInput ? generateUpdateMany2(
@@ -4588,7 +5144,8 @@ function generateSchemaData2(db, schema, relations, options) {
4588
5144
  typeName,
4589
5145
  typeNameMapper,
4590
5146
  filterCtx,
4591
- mutationTxCtx
5147
+ mutationTxCtx,
5148
+ nestedRuntime
4592
5149
  ) : void 0;
4593
5150
  const deleteGenerated = features.delete ? generateDelete2(
4594
5151
  db,
@@ -4653,7 +5210,7 @@ function generateSchemaData2(db, schema, relations, options) {
4653
5210
  };
4654
5211
  if (aggregateGenerated && aggregateType) {
4655
5212
  queries[aggregateGenerated.name] = {
4656
- type: new GraphQLNonNull5(aggregateType),
5213
+ type: new GraphQLNonNull6(aggregateType),
4657
5214
  args: aggregateGenerated.args,
4658
5215
  resolve: aggregateGenerated.resolver,
4659
5216
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -4661,7 +5218,7 @@ function generateSchemaData2(db, schema, relations, options) {
4661
5218
  }
4662
5219
  if (groupByGenerated && groupByType) {
4663
5220
  queries[groupByGenerated.name] = {
4664
- type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(groupByType))),
5221
+ type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(groupByType))),
4665
5222
  args: groupByGenerated.args,
4666
5223
  resolve: groupByGenerated.resolver,
4667
5224
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -4705,7 +5262,7 @@ function generateSchemaData2(db, schema, relations, options) {
4705
5262
  if (updateManyGenerated) {
4706
5263
  mutations[updateManyGenerated.name] = {
4707
5264
  // Nullable items: a no-match entry yields `null` in its slot.
4708
- type: new GraphQLNonNull5(new GraphQLList5(singleTableItemOutput)),
5265
+ type: new GraphQLNonNull6(new GraphQLList6(singleTableItemOutput)),
4709
5266
  args: updateManyGenerated.args,
4710
5267
  resolve: updateManyGenerated.resolver
4711
5268
  };
@@ -4762,7 +5319,7 @@ function generateSchemaData2(db, schema, relations, options) {
4762
5319
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
4763
5320
  const relResolvers = {};
4764
5321
  for (const [relName, relEntry] of Object.entries(tableRelations)) {
4765
- const isOne = is5(relEntry.relation ?? relEntry, One4);
5322
+ const isOne = is6(relEntry.relation ?? relEntry, One5);
4766
5323
  const resolver = resolverFactory({ tableName, relationName: relName, relEntry, isOne });
4767
5324
  if (resolver) {
4768
5325
  relResolvers[relName] = resolver;
@@ -4776,12 +5333,12 @@ function generateSchemaData2(db, schema, relations, options) {
4776
5333
  }
4777
5334
 
4778
5335
  // src/util/builders/sqlite.ts
4779
- import { is as is6, One as One5 } from "drizzle-orm";
5336
+ import { is as is7, One as One6 } from "drizzle-orm";
4780
5337
  import { getTableConfig as getTableConfig3, SQLiteTable } from "drizzle-orm/sqlite-core";
4781
5338
  import {
4782
- GraphQLError as GraphQLError7,
4783
- GraphQLList as GraphQLList6,
4784
- GraphQLNonNull as GraphQLNonNull6
5339
+ GraphQLError as GraphQLError8,
5340
+ GraphQLList as GraphQLList7,
5341
+ GraphQLNonNull as GraphQLNonNull7
4785
5342
  } from "graphql";
4786
5343
  import { parseResolveInfo as parseResolveInfo4 } from "graphql-parse-resolve-info";
4787
5344
  var generateSelectArray3 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
@@ -4867,10 +5424,10 @@ var generateSelectSingle3 = (db, tableName, tables, relationMap, orderArgs, filt
4867
5424
  };
4868
5425
  };
4869
5426
  var sqlitePrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig3);
4870
- var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
5427
+ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4871
5428
  const queryArgs = {
4872
5429
  values: {
4873
- type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(baseType)))
5430
+ type: new GraphQLNonNull7(new GraphQLList7(new GraphQLNonNull7(baseType)))
4874
5431
  }
4875
5432
  };
4876
5433
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -4879,10 +5436,12 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
4879
5436
  resolver: async (_source, args, context, info) => {
4880
5437
  try {
4881
5438
  return await runMutation(db, context, info, txCtx, async (executor) => {
4882
- const input = remapFromGraphQLArrayInput(args.values, table);
4883
- if (!input.length) {
4884
- throw new GraphQLError7("No values were provided!");
5439
+ if (!args.values.length) {
5440
+ throw new GraphQLError8("No values were provided!");
4885
5441
  }
5442
+ const entries = nested?.enabled(tableName) ? args.values.map((values) => nested.split(tableName, values)) : void 0;
5443
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
5444
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : args.values, table);
4886
5445
  const parsedInfo = parseResolveInfo4(info, {
4887
5446
  deep: true
4888
5447
  });
@@ -4896,11 +5455,22 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
4896
5455
  pkNames,
4897
5456
  parsedInfo
4898
5457
  });
4899
- let query = executor.insert(table).values(input).returning(columns);
4900
- if (conflictDoNothing) {
4901
- query = query.onConflictDoNothing();
4902
- }
4903
- const result = await query;
5458
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
5459
+ const runInsert = async (target, values) => {
5460
+ let query = target.insert(table).values(values).returning(returning);
5461
+ if (conflictDoNothing) {
5462
+ query = query.onConflictDoNothing();
5463
+ }
5464
+ return await query;
5465
+ };
5466
+ const result = nestedEntries ? await writeWithNestedOps({
5467
+ executor,
5468
+ runtime: nested,
5469
+ tableName,
5470
+ entries: nestedEntries,
5471
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
5472
+ write: (tx, values) => runInsert(tx, [values])
5473
+ }) : await runInsert(executor, input);
4904
5474
  const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, result, pkNames, withParams) : result;
4905
5475
  return remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
4906
5476
  });
@@ -4911,10 +5481,10 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
4911
5481
  args: queryArgs
4912
5482
  };
4913
5483
  };
4914
- var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx) => {
5484
+ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType, fieldName, typeName, typeNameMapper, conflictDoNothing = false, txCtx, nested) => {
4915
5485
  const queryArgs = {
4916
5486
  values: {
4917
- type: new GraphQLNonNull6(baseType)
5487
+ type: new GraphQLNonNull7(baseType)
4918
5488
  }
4919
5489
  };
4920
5490
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -4923,7 +5493,9 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
4923
5493
  resolver: async (_source, args, context, info) => {
4924
5494
  try {
4925
5495
  return await runMutation(db, context, info, txCtx, async (executor) => {
4926
- const input = remapFromGraphQLSingleInput(args.values, table);
5496
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, args.values) : void 0;
5497
+ const nestedEntry = entry && nested.hasOps(entry.ops) ? entry : void 0;
5498
+ const input = nestedEntry ? {} : remapFromGraphQLSingleInput(entry ? entry.columns : args.values, table);
4927
5499
  const parsedInfo = parseResolveInfo4(info, {
4928
5500
  deep: true
4929
5501
  });
@@ -4937,11 +5509,22 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
4937
5509
  pkNames,
4938
5510
  parsedInfo
4939
5511
  });
4940
- let query = executor.insert(table).values(input).returning(columns);
4941
- if (conflictDoNothing) {
4942
- query = query.onConflictDoNothing();
4943
- }
4944
- const result = await query;
5512
+ const returning = nestedEntry ? nested.withJoinColumns(tableName, nestedEntry.ops, { ...columns }, table) : columns;
5513
+ const runInsert = async (target, values) => {
5514
+ let query = target.insert(table).values(values).returning(returning);
5515
+ if (conflictDoNothing) {
5516
+ query = query.onConflictDoNothing();
5517
+ }
5518
+ return await query;
5519
+ };
5520
+ const result = nestedEntry ? await writeWithNestedOps({
5521
+ executor,
5522
+ runtime: nested,
5523
+ tableName,
5524
+ entries: [nestedEntry],
5525
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
5526
+ write: runInsert
5527
+ }) : await runInsert(executor, input);
4945
5528
  if (!result[0]) {
4946
5529
  return void 0;
4947
5530
  }
@@ -4955,10 +5538,10 @@ var generateInsertSingle3 = (db, tableName, table, tables, relationMap, baseType
4955
5538
  args: queryArgs
4956
5539
  };
4957
5540
  };
4958
- var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx) => {
5541
+ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onConflictType, uniqueSets, fieldName, typeName, single, typeNameMapper, filterCtx, txCtx, nested) => {
4959
5542
  const queryArgs = {
4960
5543
  values: {
4961
- type: single ? new GraphQLNonNull6(baseType) : new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(baseType)))
5544
+ type: single ? new GraphQLNonNull7(baseType) : new GraphQLNonNull7(new GraphQLList7(new GraphQLNonNull7(baseType)))
4962
5545
  },
4963
5546
  onConflict: {
4964
5547
  type: onConflictType,
@@ -4971,10 +5554,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
4971
5554
  resolver: async (_source, args, context, info) => {
4972
5555
  try {
4973
5556
  return await runMutation(db, context, info, txCtx, async (executor) => {
4974
- const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
4975
- if (!input.length) {
4976
- throw new GraphQLError7("No values were provided!");
5557
+ const supplied = single ? [args.values] : args.values;
5558
+ if (!supplied.length) {
5559
+ throw new GraphQLError8("No values were provided!");
4977
5560
  }
5561
+ const entries = nested?.enabled(tableName) ? supplied.map((values) => nested.split(tableName, values)) : void 0;
5562
+ const nestedEntries = entries?.some((entry) => nested.hasOps(entry.ops)) ? entries : void 0;
5563
+ const input = nestedEntries ? [] : remapFromGraphQLArrayInput(entries ? entries.map((entry) => entry.columns) : supplied, table);
4978
5564
  const parsedInfo = parseResolveInfo4(info, { deep: true });
4979
5565
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
4980
5566
  relationMap,
@@ -4986,19 +5572,30 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
4986
5572
  pkNames,
4987
5573
  parsedInfo
4988
5574
  });
4989
- const plan = resolveConflictPlan({
4990
- table,
4991
- values: input,
4992
- onConflict: args.onConflict,
4993
- pkNames,
4994
- uniqueSets,
4995
- excludedRef: excludedColumnRef,
4996
- withTarget: true,
4997
- buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
4998
- });
4999
- let query = executor.insert(table).values(input).returning(columns);
5000
- query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
5001
- const result = await query;
5575
+ const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
5576
+ const runUpsert = async (target, values) => {
5577
+ const plan = resolveConflictPlan({
5578
+ table,
5579
+ values,
5580
+ onConflict: args.onConflict,
5581
+ pkNames,
5582
+ uniqueSets,
5583
+ excludedRef: excludedColumnRef,
5584
+ withTarget: true,
5585
+ buildWhere: (where) => extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName))
5586
+ });
5587
+ let query = target.insert(table).values(values).returning(returning);
5588
+ query = plan.action === "NOTHING" ? query.onConflictDoNothing(plan.target ? { target: plan.target } : void 0) : query.onConflictDoUpdate({ target: plan.target, set: plan.set, setWhere: plan.setWhere });
5589
+ return await query;
5590
+ };
5591
+ const result = nestedEntries ? await writeWithNestedOps({
5592
+ executor,
5593
+ runtime: nested,
5594
+ tableName,
5595
+ entries: nestedEntries,
5596
+ remapValues: (values) => remapFromGraphQLSingleInput(values, table),
5597
+ write: (tx, values) => runUpsert(tx, [values])
5598
+ }) : await runUpsert(executor, input);
5002
5599
  if (single && !result[0]) {
5003
5600
  return void 0;
5004
5601
  }
@@ -5012,13 +5609,13 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
5012
5609
  args: queryArgs
5013
5610
  };
5014
5611
  };
5015
- var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx) => {
5612
+ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filterArgs, fieldName, typeName, single, requireWhere, typeNameMapper, filterCtx, txCtx, nested) => {
5016
5613
  const queryArgs = {
5017
5614
  set: {
5018
- type: new GraphQLNonNull6(setArgs)
5615
+ type: new GraphQLNonNull7(setArgs)
5019
5616
  },
5020
5617
  where: {
5021
- type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
5618
+ type: single || requireWhere ? new GraphQLNonNull7(filterArgs) : filterArgs
5022
5619
  }
5023
5620
  };
5024
5621
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -5041,23 +5638,37 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
5041
5638
  pkNames,
5042
5639
  parsedInfo
5043
5640
  });
5044
- const input = remapFromGraphQLSingleInput(set, table);
5045
- if (!Object.keys(input).length) {
5046
- throw new GraphQLError7("Unable to update with no values specified!");
5641
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
5642
+ const nestedOps = entry && nested.hasOps(entry.ops) ? entry.ops : void 0;
5643
+ const input = remapFromGraphQLSingleInput(entry ? entry.columns : set, table);
5644
+ if (!Object.keys(input).length && !nestedOps) {
5645
+ throw new GraphQLError8("Unable to update with no values specified!");
5047
5646
  }
5048
5647
  const relationCtx = relationFilterCtx(filterCtx, tableName);
5049
5648
  const filters = single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0;
5050
5649
  if (single) {
5051
5650
  await assertSingleMatch(executor, table, filters, fieldName);
5052
5651
  }
5053
- let query = executor.update(table).set(input);
5054
- if (filters) {
5055
- query = query.where(filters);
5056
- }
5057
- query = query.returning(columns);
5058
- const result = await query;
5652
+ const returning = nestedOps ? nested.withJoinColumns(tableName, nestedOps, { ...columns }, table) : columns;
5653
+ const runUpdate = async (target, values) => {
5654
+ const writes = Object.keys(values).length > 0;
5655
+ let query = writes ? target.update(table).set(values) : target.select(returning).from(table);
5656
+ if (filters) {
5657
+ query = query.where(filters);
5658
+ }
5659
+ return await (writes ? query.returning(returning) : query);
5660
+ };
5661
+ const result = nestedOps ? await updateWithNestedOps({
5662
+ executor,
5663
+ runtime: nested,
5664
+ tableName,
5665
+ columns: input,
5666
+ ops: nestedOps,
5667
+ remapValues: (values) => values,
5668
+ write: runUpdate
5669
+ }) : await runUpdate(executor, input);
5059
5670
  if (single && result.length > 1) {
5060
- throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
5671
+ throw new GraphQLError8(`${fieldName}: 'where' matched more than one row!`);
5061
5672
  }
5062
5673
  if (single && !result[0]) {
5063
5674
  return void 0;
@@ -5072,10 +5683,10 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
5072
5683
  args: queryArgs
5073
5684
  };
5074
5685
  };
5075
- var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx) => {
5686
+ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx, txCtx, nested) => {
5076
5687
  const queryArgs = {
5077
5688
  updates: {
5078
- type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(updateManyInput)))
5689
+ type: new GraphQLNonNull7(new GraphQLList7(new GraphQLNonNull7(updateManyInput)))
5079
5690
  }
5080
5691
  };
5081
5692
  const pkNames = sqlitePrimaryKeyPropNames(table);
@@ -5086,7 +5697,7 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
5086
5697
  return await runMutation(db, context, info, txCtx, async (executor) => {
5087
5698
  const { updates } = args;
5088
5699
  if (!updates.length) {
5089
- throw new GraphQLError7("No updates were provided!");
5700
+ throw new GraphQLError8("No updates were provided!");
5090
5701
  }
5091
5702
  const parsedInfo = parseResolveInfo4(info, {
5092
5703
  deep: true
@@ -5102,23 +5713,55 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
5102
5713
  parsedInfo
5103
5714
  });
5104
5715
  const entries = updates.map(({ where, set }) => {
5105
- const input = remapFromGraphQLSingleInput(set, table);
5106
- if (!Object.keys(input).length) {
5107
- throw new GraphQLError7("Unable to update with no values specified!");
5716
+ const split = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
5717
+ const ops = split && nested.hasOps(split.ops) ? split.ops : void 0;
5718
+ const input = remapFromGraphQLSingleInput(split ? split.columns : set, table);
5719
+ if (!Object.keys(input).length && !ops) {
5720
+ throw new GraphQLError8("Unable to update with no values specified!");
5108
5721
  }
5109
5722
  return {
5110
5723
  set: input,
5724
+ ops,
5111
5725
  filters: where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
5112
5726
  };
5113
5727
  });
5728
+ const anyNested = entries.some((entry) => entry.ops);
5729
+ const returning = anyNested ? nested.withJoinColumns(
5730
+ tableName,
5731
+ mergedOps(entries.map((entry) => ({ ops: entry.ops ?? {} }))),
5732
+ { ...columns },
5733
+ table
5734
+ ) : columns;
5114
5735
  const runEntry = (tx, entry) => {
5115
5736
  let query = tx.update(table).set(entry.set);
5116
5737
  if (entry.filters) {
5117
5738
  query = query.where(entry.filters);
5118
5739
  }
5119
- return query.returning(columns).all();
5740
+ return query.returning(returning).all();
5741
+ };
5742
+ const runNestedEntry = async (tx, entry) => {
5743
+ const values = entry.ops ? { ...entry.set, ...await nested.applyParentSide(tx, tableName, entry.ops) } : entry.set;
5744
+ const writes = Object.keys(values).length > 0;
5745
+ let query = writes ? tx.update(table).set(values) : tx.select(returning).from(table);
5746
+ if (entry.filters) {
5747
+ query = query.where(entry.filters);
5748
+ }
5749
+ const rows = await (writes ? query.returning(returning) : query);
5750
+ if (entry.ops) {
5751
+ await nested.applyChildSide(tx, tableName, entry.ops, rows);
5752
+ }
5753
+ return rows;
5120
5754
  };
5121
5755
  const perEntry = await executor.transaction((tx) => {
5756
+ if (anyNested) {
5757
+ return (async () => {
5758
+ const results2 = [];
5759
+ for (const entry of entries) {
5760
+ results2.push(await runNestedEntry(tx, entry));
5761
+ }
5762
+ return results2;
5763
+ })();
5764
+ }
5122
5765
  const first = runEntry(tx, entries[0]);
5123
5766
  if (typeof first?.then === "function") {
5124
5767
  return (async () => {
@@ -5161,7 +5804,7 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
5161
5804
  var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx) => {
5162
5805
  const queryArgs = {
5163
5806
  where: {
5164
- type: single || requireWhere ? new GraphQLNonNull6(filterArgs) : filterArgs
5807
+ type: single || requireWhere ? new GraphQLNonNull7(filterArgs) : filterArgs
5165
5808
  }
5166
5809
  };
5167
5810
  return {
@@ -5190,7 +5833,7 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, si
5190
5833
  query = query.returning(columns);
5191
5834
  const result = await query;
5192
5835
  if (single && result.length > 1) {
5193
- throw new GraphQLError7(`${fieldName}: 'where' matched more than one row!`);
5836
+ throw new GraphQLError8(`${fieldName}: 'where' matched more than one row!`);
5194
5837
  }
5195
5838
  if (single) {
5196
5839
  return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
@@ -5217,7 +5860,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5217
5860
  } = options;
5218
5861
  const rawSchema = schema;
5219
5862
  const schemaEntries = Object.entries(rawSchema);
5220
- const tableEntries = schemaEntries.filter(([_key, value]) => is6(value, SQLiteTable));
5863
+ const tableEntries = schemaEntries.filter(([_key, value]) => is7(value, SQLiteTable));
5221
5864
  const tables = Object.fromEntries(tableEntries);
5222
5865
  if (!tableEntries.length) {
5223
5866
  throw new Error(
@@ -5225,6 +5868,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5225
5868
  );
5226
5869
  }
5227
5870
  registerScalarOverrides(tables, options);
5871
+ registerEnumConfig(options);
5228
5872
  const namedRelations = buildNamedRelations(relations ?? {}, tableEntries);
5229
5873
  attachTargetPrimaryKeys(namedRelations, tables, sqlitePrimaryKeyPropNames);
5230
5874
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
@@ -5242,8 +5886,23 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5242
5886
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
5243
5887
  listRelationFilterCache: /* @__PURE__ */ new Map(),
5244
5888
  aggregateTypeCache: /* @__PURE__ */ new Map(),
5245
- complexity
5889
+ complexity,
5890
+ docs: options.docs ?? {}
5246
5891
  };
5892
+ if (features.nestedWrites && db.resultKind === "sync") {
5893
+ throw new Error(
5894
+ "Drizzle-GraphQL Error: features.nestedWrites requires an asynchronous SQLite driver (e.g. libsql). Synchronous drivers cannot run the multi-statement transaction a nested write needs."
5895
+ );
5896
+ }
5897
+ const nestedPlans = features.nestedWrites ? buildNestedWritePlans(
5898
+ tables,
5899
+ namedRelations,
5900
+ (target) => getUniqueColumnSets(target, getTableConfig3),
5901
+ (target) => sqlitePrimaryKeyPropNames(target),
5902
+ extractRelationJoinColumns
5903
+ ) : void 0;
5904
+ const nestedTypes = nestedPlans ? createNestedWriteTypes({ plans: nestedPlans, cacheCtx, typeNameMapper, insertPrefix: prefixes.insert }) : void 0;
5905
+ const nestedRuntime = nestedPlans ? createNestedWriteRuntime({ plans: nestedPlans, filterCtx }) : void 0;
5247
5906
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
5248
5907
  const queries = {};
5249
5908
  const mutations = {};
@@ -5267,7 +5926,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5267
5926
  prefixes.insert,
5268
5927
  prefixes.update,
5269
5928
  resolverFactory,
5270
- relationAggregateFactory
5929
+ relationAggregateFactory,
5930
+ nestedTypes
5271
5931
  )
5272
5932
  ])
5273
5933
  );
@@ -5328,7 +5988,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5328
5988
  typeName,
5329
5989
  typeNameMapper,
5330
5990
  conflictDoNothing,
5331
- mutationTxCtx
5991
+ mutationTxCtx,
5992
+ nestedRuntime
5332
5993
  ) : void 0;
5333
5994
  const insertSingleGenerated = features.insert ? generateInsertSingle3(
5334
5995
  db,
@@ -5341,7 +6002,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5341
6002
  typeName,
5342
6003
  typeNameMapper,
5343
6004
  conflictDoNothing,
5344
- mutationTxCtx
6005
+ mutationTxCtx,
6006
+ nestedRuntime
5345
6007
  ) : void 0;
5346
6008
  const uniqueSets = features.upsert ? getUniqueColumnSets(schema[tableName], getTableConfig3) : [];
5347
6009
  const onConflictInput = features.upsert ? generateOnConflictInput({
@@ -5365,7 +6027,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5365
6027
  false,
5366
6028
  typeNameMapper,
5367
6029
  filterCtx,
5368
- mutationTxCtx
6030
+ mutationTxCtx,
6031
+ nestedRuntime
5369
6032
  ) : void 0;
5370
6033
  const upsertSingleGenerated = onConflictInput ? generateUpsert3(
5371
6034
  db,
@@ -5381,7 +6044,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5381
6044
  true,
5382
6045
  typeNameMapper,
5383
6046
  filterCtx,
5384
- mutationTxCtx
6047
+ mutationTxCtx,
6048
+ nestedRuntime
5385
6049
  ) : void 0;
5386
6050
  const updateGenerated = features.update ? generateUpdate3(
5387
6051
  db,
@@ -5397,7 +6061,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5397
6061
  features.requireWhere,
5398
6062
  typeNameMapper,
5399
6063
  filterCtx,
5400
- mutationTxCtx
6064
+ mutationTxCtx,
6065
+ nestedRuntime
5401
6066
  ) : void 0;
5402
6067
  const updateSingleGenerated = features.update ? generateUpdate3(
5403
6068
  db,
@@ -5413,7 +6078,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5413
6078
  features.requireWhere,
5414
6079
  typeNameMapper,
5415
6080
  filterCtx,
5416
- mutationTxCtx
6081
+ mutationTxCtx,
6082
+ nestedRuntime
5417
6083
  ) : void 0;
5418
6084
  const updateManyInput = features.update && features.updateMany ? generateUpdateManyInput({ typeName, updatePrefix: prefixes.update, updateInput, tableFilters }) : void 0;
5419
6085
  const updateManyGenerated = updateManyInput ? generateUpdateMany3(
@@ -5427,7 +6093,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5427
6093
  typeName,
5428
6094
  typeNameMapper,
5429
6095
  filterCtx,
5430
- mutationTxCtx
6096
+ mutationTxCtx,
6097
+ nestedRuntime
5431
6098
  ) : void 0;
5432
6099
  const deleteGenerated = features.delete ? generateDelete3(
5433
6100
  db,
@@ -5492,7 +6159,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5492
6159
  };
5493
6160
  if (aggregateGenerated && aggregateType) {
5494
6161
  queries[aggregateGenerated.name] = {
5495
- type: new GraphQLNonNull6(aggregateType),
6162
+ type: new GraphQLNonNull7(aggregateType),
5496
6163
  args: aggregateGenerated.args,
5497
6164
  resolve: aggregateGenerated.resolver,
5498
6165
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -5500,7 +6167,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5500
6167
  }
5501
6168
  if (groupByGenerated && groupByType) {
5502
6169
  queries[groupByGenerated.name] = {
5503
- type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(groupByType))),
6170
+ type: new GraphQLNonNull7(new GraphQLList7(new GraphQLNonNull7(groupByType))),
5504
6171
  args: groupByGenerated.args,
5505
6172
  resolve: groupByGenerated.resolver,
5506
6173
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
@@ -5544,7 +6211,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5544
6211
  if (updateManyGenerated) {
5545
6212
  mutations[updateManyGenerated.name] = {
5546
6213
  // Nullable items: a no-match entry yields `null` in its slot.
5547
- type: new GraphQLNonNull6(new GraphQLList6(singleTableItemOutput)),
6214
+ type: new GraphQLNonNull7(new GraphQLList7(singleTableItemOutput)),
5548
6215
  args: updateManyGenerated.args,
5549
6216
  resolve: updateManyGenerated.resolver
5550
6217
  };
@@ -5601,7 +6268,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
5601
6268
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
5602
6269
  const relResolvers = {};
5603
6270
  for (const [relName, relEntry] of Object.entries(tableRelations)) {
5604
- const isOne = is6(relEntry.relation ?? relEntry, One5);
6271
+ const isOne = is7(relEntry.relation ?? relEntry, One6);
5605
6272
  const resolver = resolverFactory({ tableName, relationName: relName, relEntry, isOne });
5606
6273
  if (resolver) {
5607
6274
  relResolvers[relName] = resolver;
@@ -5646,6 +6313,7 @@ var buildSchema = (db, config) => {
5646
6313
  updateMany: config?.features?.updateMany ?? true,
5647
6314
  delete: config?.features?.delete ?? true,
5648
6315
  upsert: config?.features?.upsert ?? false,
6316
+ nestedWrites: config?.features?.nestedWrites ?? false,
5649
6317
  requireWhere: config?.features?.requireWhere ?? false
5650
6318
  };
5651
6319
  const complexityConfig = config?.complexity ?? true;
@@ -5685,14 +6353,21 @@ var buildSchema = (db, config) => {
5685
6353
  complexity,
5686
6354
  scalars: config?.scalars,
5687
6355
  mapColumnType: config?.mapColumnType,
5688
- transactions
6356
+ enumNameMapper: config?.enumNameMapper,
6357
+ transactions,
6358
+ docs: {
6359
+ describeColumn: config?.describeColumn,
6360
+ describeTable: config?.describeTable,
6361
+ describeRelation: config?.describeRelation,
6362
+ deprecateColumn: config?.deprecateColumn
6363
+ }
5689
6364
  };
5690
6365
  let generatorOutput;
5691
- if (is7(db, MySqlDatabase)) {
6366
+ if (is8(db, MySqlDatabase)) {
5692
6367
  generatorOutput = generateSchemaData(db, schema, relations, generatorOptions);
5693
- } else if (is7(db, PgAsyncDatabase)) {
6368
+ } else if (is8(db, PgAsyncDatabase)) {
5694
6369
  generatorOutput = generateSchemaData2(db, schema, relations, generatorOptions);
5695
- } else if (is7(db, BaseSQLiteDatabase)) {
6370
+ } else if (is8(db, BaseSQLiteDatabase)) {
5696
6371
  generatorOutput = generateSchemaData3(db, schema, relations, generatorOptions);
5697
6372
  } else {
5698
6373
  throw new Error("Drizzle-GraphQL Error: Unknown database instance type");