@vantreeseba/drizzle-graphql 7.6.0 → 7.7.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
@@ -1155,7 +1155,7 @@ var batchedPaginatedRelationQuery = async (db, targetTable, foreignCol, whereCon
1155
1155
  }
1156
1156
  return rows;
1157
1157
  };
1158
- var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits, scopes) => ({ tableName, relationName, relEntry, isOne }) => {
1158
+ var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits, policies) => ({ tableName, relationName, relEntry, isOne }) => {
1159
1159
  const parentTable = tables[tableName];
1160
1160
  const targetTableName = relEntry.targetTableName;
1161
1161
  const targetTable = tables[targetTableName];
@@ -1177,7 +1177,14 @@ var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits
1177
1177
  if (localValue == null) {
1178
1178
  return isOne ? null : [];
1179
1179
  }
1180
- const { where: whereArg, orderBy: orderByArg, limit: requestedLimit, offset, after } = args ?? {};
1180
+ const {
1181
+ where: whereArg,
1182
+ orderBy: orderByArg,
1183
+ limit: requestedLimit,
1184
+ offset,
1185
+ after,
1186
+ deleted
1187
+ } = args ?? {};
1181
1188
  const limit = applyLimitPolicy(requestedLimit, limitPolicy, `${tableName}.${relationName}`);
1182
1189
  const distinct = (args ?? {}).distinct?.length ? (args ?? {}).distinct : void 0;
1183
1190
  const cursorSelected = !isOne && !!info && selectsCursorField(info, targetTable);
@@ -1208,6 +1215,7 @@ var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits
1208
1215
  orderBy: orderByArg ?? null,
1209
1216
  limit: limit ?? null,
1210
1217
  offset: offset ?? null,
1218
+ deleted: deleted ?? null,
1211
1219
  after: after ?? null,
1212
1220
  distinct: distinct ?? null,
1213
1221
  cursor: cursorEntries ? 1 : 0
@@ -1216,7 +1224,7 @@ var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits
1216
1224
  const loader = getOrCreateLoader(context, loaderKey, async (parentIds) => {
1217
1225
  const executor = resolveExecutor(db, context);
1218
1226
  const uniqueIds = [...new Set(parentIds)];
1219
- const scope = resolveScope(scopes, context, filterCtx);
1227
+ const scope = resolveScope(policies, context, filterCtx);
1220
1228
  let whereCondition = withScope(
1221
1229
  scope,
1222
1230
  targetTableName,
@@ -1225,7 +1233,8 @@ var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits
1225
1233
  inArray(foreignCol, uniqueIds),
1226
1234
  whereArg ? extractFilters(targetTable, targetTableName, whereArg, relationFilterCtx(filterCtx, targetTableName)) : void 0,
1227
1235
  cursorValues ? buildCursorCondition(targetTable, cursorEntries, cursorValues, nullOrdering) : void 0
1228
- )
1236
+ ),
1237
+ deleted
1229
1238
  );
1230
1239
  if (distinct) {
1231
1240
  const keys = await selectDistinctKeys({
@@ -2030,7 +2039,8 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
2030
2039
  {
2031
2040
  type: isRequired ? new GraphQLNonNull3(relType) : relType,
2032
2041
  args: {
2033
- where: { type: relSelectData.filters }
2042
+ where: { type: relSelectData.filters },
2043
+ ...deletedArg(cacheCtx.softDeleteOf, targetTableName)
2034
2044
  },
2035
2045
  resolve,
2036
2046
  ...relationDocs,
@@ -2049,6 +2059,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
2049
2059
  orderBy: { type: relSelectData.order },
2050
2060
  offset: { type: GraphQLInt3 },
2051
2061
  limit: { type: GraphQLInt3 },
2062
+ ...deletedArg(cacheCtx.softDeleteOf, targetTableName),
2052
2063
  after: {
2053
2064
  type: GraphQLString2,
2054
2065
  description: "Keyset pagination: only return related rows strictly after this cursor (a row's `cursor` field from a previous page of this relation, under the same orderBy)."
@@ -2076,7 +2087,8 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
2076
2087
  {
2077
2088
  type: new GraphQLNonNull3(relationAggregate.type),
2078
2089
  args: {
2079
- where: { type: relSelectData.filters }
2090
+ where: { type: relSelectData.filters },
2091
+ ...deletedArg(cacheCtx.softDeleteOf, targetTableName)
2080
2092
  },
2081
2093
  resolve: relationAggregate.resolve,
2082
2094
  extensions: {
@@ -2132,7 +2144,10 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
2132
2144
  const columns = visibleColumns(table);
2133
2145
  const columnEntries = Object.entries(columns);
2134
2146
  const contextColumns = cacheCtx.contextValuesOf?.(tableName);
2135
- const writableEntries = contextColumns ? columnEntries.filter(([columnName]) => !(columnName in contextColumns)) : columnEntries;
2147
+ const markerColumn = cacheCtx.softDeleteOf?.(tableName)?.columnName;
2148
+ const writableEntries = contextColumns || markerColumn ? columnEntries.filter(
2149
+ ([columnName]) => !(contextColumns && columnName in contextColumns) && columnName !== markerColumn
2150
+ ) : columnEntries;
2136
2151
  const relaxedColumns = nestedWrites?.relaxedColumns(tableName);
2137
2152
  const insertFields = Object.fromEntries(
2138
2153
  writableEntries.map(([columnName, column]) => {
@@ -2674,40 +2689,103 @@ var extractFilters = (table, tableName, filters, relationCtx) => {
2674
2689
  }
2675
2690
  return variants.length ? variants.length > 1 ? and(...variants) : variants[0] : void 0;
2676
2691
  };
2677
- var resolveScope = (scopes, context, filterCtx) => {
2678
- if (!scopes) {
2692
+ var deletedFilterEnum = new GraphQLEnumType2({
2693
+ name: "DeletedFilter",
2694
+ description: "Which rows a read over a soft-deleting table returns.",
2695
+ values: {
2696
+ EXCLUDE: { value: "EXCLUDE", description: "Only rows that are not marked deleted. The default." },
2697
+ INCLUDE: { value: "INCLUDE", description: "Marked and unmarked rows alike." },
2698
+ ONLY: { value: "ONLY", description: "Only rows that are marked deleted \u2014 a trash view." }
2699
+ }
2700
+ });
2701
+ var resolveSoftDeleteInfo = (table, tableName, declaration) => {
2702
+ const config = typeof declaration === "string" ? { column: declaration } : declaration;
2703
+ const columnName = config?.column;
2704
+ if (typeof columnName !== "string" || !columnName) {
2705
+ throw new Error(
2706
+ `Drizzle-GraphQL Error: config.softDelete.${tableName} must be a column name or an object with a 'column' property.`
2707
+ );
2708
+ }
2709
+ const column = getColumns2(table)[columnName];
2710
+ if (!column) {
2711
+ throw new Error(
2712
+ `Drizzle-GraphQL Error: config.softDelete names '${tableName}.${columnName}', which is not a column of that table.`
2713
+ );
2714
+ }
2715
+ const nullable = !column.notNull;
2716
+ const { type: baseType, constraint } = extractExtendedColumnType2(column);
2717
+ const hasDeleted = "deletedValue" in config && config.deletedValue !== void 0;
2718
+ const writeDeleted = hasDeleted ? typeof config.deletedValue === "function" ? config.deletedValue : () => config.deletedValue : constraint === "date" && baseType === "object" ? () => /* @__PURE__ */ new Date() : baseType === "string" ? () => (/* @__PURE__ */ new Date()).toISOString() : baseType === "number" ? () => Date.now() : baseType === "bigint" ? () => BigInt(Date.now()) : () => true;
2719
+ let marker;
2720
+ if (!nullable) {
2721
+ if (hasDeleted && typeof config.deletedValue !== "function") {
2722
+ marker = config.deletedValue;
2723
+ } else if (!hasDeleted && baseType === "boolean") {
2724
+ marker = true;
2725
+ } else {
2726
+ throw new Error(
2727
+ `Drizzle-GraphQL Error: config.softDelete.${tableName} marks a NOT NULL column ('${columnName}'), so 'deletedValue' must be a constant that means deleted \u2014 not a function, and not omitted for a non-boolean column.`
2728
+ );
2729
+ }
2730
+ }
2731
+ const hasRestored = "restoredValue" in config;
2732
+ const writeRestored = hasRestored ? config.restoredValue : nullable ? null : baseType === "boolean" ? false : void 0;
2733
+ if (!nullable && writeRestored === void 0) {
2734
+ throw new Error(
2735
+ `Drizzle-GraphQL Error: config.softDelete.${tableName} marks a NOT NULL column ('${columnName}'), so 'restoredValue' must say what restoring writes back.`
2736
+ );
2737
+ }
2738
+ return { columnName, column, nullable, writeDeleted, writeRestored, marker };
2739
+ };
2740
+ var softDeletePredicate = (info, table, mode) => {
2741
+ if (mode === "INCLUDE") {
2742
+ return void 0;
2743
+ }
2744
+ const column = table?.[info.columnName] ?? info.column;
2745
+ if (info.nullable) {
2746
+ return mode === "ONLY" ? isNotNull(column) : isNull(column);
2747
+ }
2748
+ return mode === "ONLY" ? eq(column, info.marker) : ne(column, info.marker);
2749
+ };
2750
+ var resolveScope = (policies, context, filterCtx) => {
2751
+ const scopes = policies?.scope;
2752
+ const softDelete = policies?.softDelete;
2753
+ if (!scopes && !softDelete) {
2679
2754
  return void 0;
2680
2755
  }
2681
2756
  return {
2682
- has: (tableName) => !!scopes(tableName),
2683
- on: (tableName, table) => {
2684
- const hook = scopes(tableName);
2757
+ has: (tableName, mode) => !!scopes?.(tableName) || !!softDelete?.(tableName) && (mode ?? "EXCLUDE") !== "INCLUDE",
2758
+ on: (tableName, table, mode) => {
2759
+ const marked = softDelete?.(tableName);
2760
+ const deleted = marked ? softDeletePredicate(marked, table, mode ?? "EXCLUDE") : void 0;
2761
+ const hook = scopes?.(tableName);
2685
2762
  if (!hook) {
2686
- return void 0;
2763
+ return deleted;
2687
2764
  }
2688
2765
  const predicate = hook(context, table);
2689
2766
  if (predicate === void 0 || predicate === null) {
2690
- return void 0;
2767
+ return deleted;
2691
2768
  }
2692
2769
  if (is3(predicate, SQL)) {
2693
- return predicate;
2770
+ return and(deleted, predicate);
2694
2771
  }
2695
2772
  if (typeof predicate !== "object") {
2696
2773
  throw new GraphQLError4(
2697
2774
  `Drizzle-GraphQL Error: the scope for '${tableName}' returned a ${typeof predicate}. A scope returns a filter object, a Drizzle SQL expression, or undefined.`
2698
2775
  );
2699
2776
  }
2700
- return extractFilters(table, tableName, predicate, relationFilterCtx(filterCtx, tableName));
2777
+ return and(deleted, extractFilters(table, tableName, predicate, relationFilterCtx(filterCtx, tableName)));
2701
2778
  }
2702
2779
  };
2703
2780
  };
2704
- var withScope = (scope, tableName, table, condition) => {
2705
- const predicate = scope?.on(tableName, table);
2781
+ var withScope = (scope, tableName, table, condition, mode) => {
2782
+ const predicate = scope?.on(tableName, table, mode);
2706
2783
  return predicate ? and(condition, predicate) : condition;
2707
2784
  };
2708
- var bindPolicies = (policies, filterCtx) => policies?.scope || policies?.contextValues ? {
2709
- scope: policies.scope ? (context) => resolveScope(policies.scope, context, filterCtx) : void 0,
2710
- contextValues: policies.contextValues
2785
+ var bindPolicies = (policies, filterCtx) => policies?.scope || policies?.contextValues || policies?.softDelete ? {
2786
+ scope: policies.scope || policies.softDelete ? (context) => resolveScope(policies, context, filterCtx) : void 0,
2787
+ contextValues: policies.contextValues,
2788
+ softDelete: policies.softDelete
2711
2789
  } : void 0;
2712
2790
  var applyContextValues = (values, hooks, context) => {
2713
2791
  if (!hooks) {
@@ -2782,12 +2860,14 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
2782
2860
  const offset = relationArgs?.offset ?? void 0;
2783
2861
  const limit = is3(relEntry.relation, One2) ? relationArgs?.limit ?? void 0 : applyLimitPolicy(relationArgs?.limit, limits?.(targetTableName), `${tableName}.${relName}`);
2784
2862
  const relWhere = relationArgs?.where;
2785
- thisRecord.where = relWhere || scope?.has(targetTableName) ? {
2863
+ const relDeleted = relationArgs?.deleted;
2864
+ thisRecord.where = relWhere || scope?.has(targetTableName, relDeleted) ? {
2786
2865
  RAW: (aliasedTable2) => withScope(
2787
2866
  scope,
2788
2867
  targetTableName,
2789
2868
  aliasedTable2,
2790
- relWhere ? extractFilters(aliasedTable2, relName, relWhere, relationFilterCtx(filterCtx, targetTableName)) : void 0
2869
+ relWhere ? extractFilters(aliasedTable2, relName, relWhere, relationFilterCtx(filterCtx, targetTableName)) : void 0,
2870
+ relDeleted
2791
2871
  )
2792
2872
  } : void 0;
2793
2873
  const hasPagination = offset != null || limit != null;
@@ -3313,9 +3393,11 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
3313
3393
  const updateFieldName = `${prefixes.update}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
3314
3394
  const updateManyFieldName = `${prefixes.update}${mapped ? capitalize(mapped.plural) : capitalize(tableName)}Many`;
3315
3395
  const deleteFieldName = `${prefixes.delete}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
3396
+ const restoreFieldName = `${prefixes.restore ?? "restore"}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
3316
3397
  const writeSingleSuffix = suffixes.single === "" ? "Single" : suffixes.single;
3317
3398
  const updateSingleFieldName = `${updateFieldName}${writeSingleSuffix}`;
3318
3399
  const deleteSingleFieldName = `${deleteFieldName}${writeSingleSuffix}`;
3400
+ const restoreSingleFieldName = `${restoreFieldName}${writeSingleSuffix}`;
3319
3401
  const pluralNoun = mapped ? capitalize(mapped.plural) : capitalize(tableName);
3320
3402
  const updateCountFieldName = `${prefixes.update}${pluralNoun}Count`;
3321
3403
  const deleteCountFieldName = `${prefixes.delete}${pluralNoun}Count`;
@@ -3335,6 +3417,8 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
3335
3417
  updateCountFieldName,
3336
3418
  deleteFieldName,
3337
3419
  deleteSingleFieldName,
3420
+ restoreFieldName,
3421
+ restoreSingleFieldName,
3338
3422
  deleteCountFieldName
3339
3423
  };
3340
3424
  };
@@ -3439,7 +3523,13 @@ var generateWriteCount = ({
3439
3523
  args: queryArgs
3440
3524
  };
3441
3525
  };
3442
- var selectArrayArgs = (orderArgs, filterArgs, distinctEnum) => ({
3526
+ var deletedArg = (softDelete, tableName) => softDelete?.(tableName) ? {
3527
+ deleted: {
3528
+ type: deletedFilterEnum,
3529
+ description: "Whether rows marked deleted are returned. Defaults to EXCLUDE."
3530
+ }
3531
+ } : {};
3532
+ var selectArrayArgs = (orderArgs, filterArgs, distinctEnum, softDelete, tableName) => ({
3443
3533
  offset: { type: GraphQLInt3 },
3444
3534
  limit: { type: GraphQLInt3 },
3445
3535
  orderBy: { type: orderArgs },
@@ -3448,12 +3538,14 @@ var selectArrayArgs = (orderArgs, filterArgs, distinctEnum) => ({
3448
3538
  type: GraphQLString2,
3449
3539
  description: "Keyset pagination: only return rows strictly after this cursor (a row's `cursor` field from a previous page, under the same orderBy)."
3450
3540
  },
3451
- ...distinctEnum ? { distinct: { type: new GraphQLList3(new GraphQLNonNull3(distinctEnum)) } } : {}
3541
+ ...distinctEnum ? { distinct: { type: new GraphQLList3(new GraphQLNonNull3(distinctEnum)) } } : {},
3542
+ ...deletedArg(softDelete, tableName)
3452
3543
  });
3453
- var selectSingleArgs = (orderArgs, filterArgs) => ({
3544
+ var selectSingleArgs = (orderArgs, filterArgs, softDelete, tableName) => ({
3454
3545
  offset: { type: GraphQLInt3 },
3455
3546
  orderBy: { type: orderArgs },
3456
- where: { type: filterArgs }
3547
+ where: { type: filterArgs },
3548
+ ...deletedArg(softDelete, tableName)
3457
3549
  });
3458
3550
  var runRelationalSelect = async (opts) => {
3459
3551
  const {
@@ -3472,7 +3564,8 @@ var runRelationalSelect = async (opts) => {
3472
3564
  filterCtx,
3473
3565
  pkNames,
3474
3566
  after,
3475
- scope
3567
+ scope,
3568
+ deleted
3476
3569
  } = opts;
3477
3570
  const distinct = opts.distinct?.length ? opts.distinct : void 0;
3478
3571
  const cursorSelected = !single && isCursorFieldSelected(parsedInfo.fieldsByTypeName[typeName], table);
@@ -3508,7 +3601,8 @@ var runRelationalSelect = async (opts) => {
3508
3601
  scope,
3509
3602
  tableName,
3510
3603
  table,
3511
- where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
3604
+ where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0,
3605
+ deleted
3512
3606
  ),
3513
3607
  orderBy,
3514
3608
  limit: single ? 1 : opts.limit,
@@ -3539,7 +3633,7 @@ var runRelationalSelect = async (opts) => {
3539
3633
  where: distinctKeys ? (
3540
3634
  // The distinct pass already ran inside the scope, so the keys it picked are in it.
3541
3635
  { RAW: (aliasedTable2) => primaryKeyRestriction(aliasedTable2, pkNames, distinctKeys) }
3542
- ) : where || cursorValues || scope?.has(tableName) ? {
3636
+ ) : where || cursorValues || scope?.has(tableName, deleted) ? {
3543
3637
  RAW: (aliasedTable2) => withScope(
3544
3638
  scope,
3545
3639
  tableName,
@@ -3552,7 +3646,8 @@ var runRelationalSelect = async (opts) => {
3552
3646
  cursorValues,
3553
3647
  opts.nullOrdering ?? "nulls-smallest"
3554
3648
  ) : void 0
3555
- )
3649
+ ),
3650
+ deleted
3556
3651
  )
3557
3652
  } : void 0,
3558
3653
  with: relationMap[tableName] ? extractRelationsParams(
@@ -3901,10 +3996,11 @@ var assembleAggregateRow = (row, request, target) => {
3901
3996
  }
3902
3997
  return result;
3903
3998
  };
3904
- var generateAggregate = (db, tableName, table, typeName, fieldName, filterArgs, filterCtx, scopes) => {
3999
+ var generateAggregate = (db, tableName, table, typeName, fieldName, filterArgs, filterCtx, policies) => {
3905
4000
  const target = aggregateTarget(table, tableName, typeName);
3906
4001
  const queryArgs = {
3907
- where: { type: filterArgs }
4002
+ where: { type: filterArgs },
4003
+ ...deletedArg(policies?.softDelete, tableName)
3908
4004
  };
3909
4005
  return {
3910
4006
  name: fieldName,
@@ -3916,10 +4012,11 @@ var generateAggregate = (db, tableName, table, typeName, fieldName, filterArgs,
3916
4012
  }
3917
4013
  let query = resolveExecutor(db, context).select(request.selection).from(table);
3918
4014
  const where = withScope(
3919
- resolveScope(scopes, context, filterCtx),
4015
+ resolveScope(policies, context, filterCtx),
3920
4016
  tableName,
3921
4017
  table,
3922
- args.where ? extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)) : void 0
4018
+ args.where ? extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)) : void 0,
4019
+ args.deleted
3923
4020
  );
3924
4021
  if (where) {
3925
4022
  query = query.where(where);
@@ -3934,7 +4031,7 @@ var generateAggregate = (db, tableName, table, typeName, fieldName, filterArgs,
3934
4031
  };
3935
4032
  };
3936
4033
  var GROUP_KEY = "__dgql_group_key";
3937
- var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filterCtx, scopes) => {
4034
+ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filterCtx, policies) => {
3938
4035
  return ({ tableName, relationName, relEntry }) => {
3939
4036
  const parentTable = tables[tableName];
3940
4037
  const targetTableName = relEntry.targetTableName;
@@ -3961,8 +4058,10 @@ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filt
3961
4058
  return assembleAggregateRow({}, request, target);
3962
4059
  }
3963
4060
  const whereArg = args?.where;
4061
+ const deleted = args?.deleted;
3964
4062
  const argsKey = JSON.stringify({
3965
4063
  where: whereArg ?? null,
4064
+ deleted: deleted ?? null,
3966
4065
  selection: Object.keys(request.selection).sort()
3967
4066
  });
3968
4067
  const loaderKey = `${tableName}::${relationName}::aggregate::${argsKey}`;
@@ -3970,13 +4069,14 @@ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filt
3970
4069
  const executor = resolveExecutor(db, context);
3971
4070
  const uniqueIds = [...new Set(parentIds)];
3972
4071
  const whereCondition = withScope(
3973
- resolveScope(scopes, context, filterCtx),
4072
+ resolveScope(policies, context, filterCtx),
3974
4073
  targetTableName,
3975
4074
  targetTable,
3976
4075
  and2(
3977
4076
  inArray2(foreignCol, uniqueIds),
3978
4077
  whereArg ? extractFilters(targetTable, targetTableName, whereArg, relationFilterCtx(filterCtx, targetTableName)) : void 0
3979
- )
4078
+ ),
4079
+ deleted
3980
4080
  );
3981
4081
  const rows = await executor.select({ [GROUP_KEY]: foreignCol, ...request.selection }).from(targetTable).where(whereCondition).groupBy(foreignCol);
3982
4082
  const byKey = new Map(rows.map((row) => [row[GROUP_KEY], row]));
@@ -4109,7 +4209,7 @@ var buildHavingCondition = (having, columns) => {
4109
4209
  }
4110
4210
  return conditions.length ? and2(...conditions) : void 0;
4111
4211
  };
4112
- var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, groupByEnum, havingInput, filterCtx, scopes) => {
4212
+ var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, groupByEnum, havingInput, filterCtx, policies) => {
4113
4213
  const target = aggregateTarget(table, tableName, typeName);
4114
4214
  const groupable = groupableColumns(table, tableName);
4115
4215
  const columns = getColumns3(table);
@@ -4120,7 +4220,8 @@ var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, gr
4120
4220
  description: "Columns to group by. One result row per distinct combination of their values."
4121
4221
  },
4122
4222
  where: { type: filterArgs, description: "Filters the rows before they are grouped." },
4123
- having: { type: havingInput, description: "Filters the groups after they are aggregated." }
4223
+ having: { type: havingInput, description: "Filters the groups after they are aggregated." },
4224
+ ...deletedArg(policies?.softDelete, tableName)
4124
4225
  };
4125
4226
  return {
4126
4227
  name: fieldName,
@@ -4144,10 +4245,11 @@ var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, gr
4144
4245
  };
4145
4246
  let query = resolveExecutor(db, context).select(selection).from(table);
4146
4247
  const where = withScope(
4147
- resolveScope(scopes, context, filterCtx),
4248
+ resolveScope(policies, context, filterCtx),
4148
4249
  tableName,
4149
4250
  table,
4150
- args.where ? extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)) : void 0
4251
+ args.where ? extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)) : void 0,
4252
+ args.deleted
4151
4253
  );
4152
4254
  if (where) {
4153
4255
  query = query.where(where);
@@ -4189,7 +4291,9 @@ var generateSelectArray = (db, tableName, tables, relationMap, orderArgs, filter
4189
4291
  const queryArgs = selectArrayArgs(
4190
4292
  orderArgs,
4191
4293
  filterArgs,
4192
- distinctEnabled ? generateDistinctEnum(table, typeName) : void 0
4294
+ distinctEnabled ? generateDistinctEnum(table, typeName) : void 0,
4295
+ policies?.softDelete,
4296
+ tableName
4193
4297
  );
4194
4298
  return {
4195
4299
  name: fieldName,
@@ -4231,7 +4335,7 @@ var generateSelectSingle = (db, tableName, tables, relationMap, orderArgs, filte
4231
4335
  `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`
4232
4336
  );
4233
4337
  }
4234
- const queryArgs = selectSingleArgs(orderArgs, filterArgs);
4338
+ const queryArgs = selectSingleArgs(orderArgs, filterArgs, policies?.softDelete, tableName);
4235
4339
  const table = tables[tableName];
4236
4340
  const pkNames = mysqlPrimaryKeyPropNames(table);
4237
4341
  return {
@@ -4463,7 +4567,8 @@ var generateUpdateMany = (db, tableName, table, updateManyInput, fieldName, filt
4463
4567
  args: queryArgs
4464
4568
  };
4465
4569
  };
4466
- var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requireWhere, filterCtx, txCtx, policies) => {
4570
+ var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requireWhere, filterCtx, txCtx, policies, restore = false) => {
4571
+ const softDelete = policies?.softDelete?.(tableName);
4467
4572
  const queryArgs = {
4468
4573
  where: {
4469
4574
  type: single || requireWhere ? new GraphQLNonNull5(filterArgs) : filterArgs
@@ -4481,12 +4586,13 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requi
4481
4586
  scope,
4482
4587
  tableName,
4483
4588
  table,
4484
- single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0
4589
+ single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0,
4590
+ restore ? "ONLY" : void 0
4485
4591
  );
4486
4592
  if (single) {
4487
4593
  await assertSingleMatch(executor, table, filters, fieldName);
4488
4594
  }
4489
- let query = executor.delete(table);
4595
+ let query = softDelete ? executor.update(table).set({ [softDelete.columnName]: restore ? softDelete.writeRestored : softDelete.writeDeleted() }) : executor.delete(table);
4490
4596
  if (filters) {
4491
4597
  query = query.where(filters);
4492
4598
  }
@@ -4530,16 +4636,17 @@ var generateSchemaData = (db, schema, relations, options) => {
4530
4636
  attachTargetPrimaryKeys(namedRelations, tables, mysqlPrimaryKeyPropNames);
4531
4637
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
4532
4638
  const filterCtx = { tables, relationMap: namedRelations };
4533
- const scopes = options.policies?.scope;
4534
- const contextValuesOf = options.policies?.contextValues;
4535
- const policies = bindPolicies(options.policies, filterCtx);
4639
+ const tablePolicies = options.policies;
4640
+ const contextValuesOf = tablePolicies?.contextValues;
4641
+ const softDeleteOf = tablePolicies?.softDelete;
4642
+ const policies = bindPolicies(tablePolicies, filterCtx);
4536
4643
  const resolverFactory = createRelationResolverFactory(
4537
4644
  db,
4538
4645
  tables,
4539
4646
  "nulls-smallest",
4540
4647
  filterCtx,
4541
4648
  limits,
4542
- scopes
4649
+ tablePolicies
4543
4650
  );
4544
4651
  const cacheCtx = {
4545
4652
  genericFilterCache: /* @__PURE__ */ new Map(),
@@ -4558,9 +4665,10 @@ var generateSchemaData = (db, schema, relations, options) => {
4558
4665
  docs: options.docs ?? {},
4559
4666
  primaryKeyOf: (name) => tables[name] ? mysqlPrimaryKeyPropNames(tables[name]) : [],
4560
4667
  contextValuesOf,
4668
+ softDeleteOf,
4561
4669
  featureOf
4562
4670
  };
4563
- const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, scopes) : void 0;
4671
+ const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, tablePolicies) : void 0;
4564
4672
  const queries = {};
4565
4673
  const mutations = {};
4566
4674
  const mutationTxCtx = createMutationTxCtx(options.transactions);
@@ -4616,8 +4724,11 @@ var generateSchemaData = (db, schema, relations, options) => {
4616
4724
  updateCountFieldName,
4617
4725
  deleteFieldName,
4618
4726
  deleteSingleFieldName,
4727
+ restoreFieldName,
4728
+ restoreSingleFieldName,
4619
4729
  deleteCountFieldName
4620
4730
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
4731
+ const softDeleteInfo = softDeleteOf?.(tableName);
4621
4732
  const selectArrGenerated = generateSelectArray(
4622
4733
  db,
4623
4734
  tableName,
@@ -4755,6 +4866,32 @@ var generateSchemaData = (db, schema, relations, options) => {
4755
4866
  mutationTxCtx,
4756
4867
  policies
4757
4868
  ) : void 0;
4869
+ const restoreGenerated = softDeleteInfo ? generateDelete(
4870
+ db,
4871
+ tableName,
4872
+ schema[tableName],
4873
+ tableFilters,
4874
+ restoreFieldName,
4875
+ false,
4876
+ tableFeatures.requireWhere,
4877
+ filterCtx,
4878
+ mutationTxCtx,
4879
+ policies,
4880
+ true
4881
+ ) : void 0;
4882
+ const restoreSingleGenerated = softDeleteInfo ? generateDelete(
4883
+ db,
4884
+ tableName,
4885
+ schema[tableName],
4886
+ tableFilters,
4887
+ restoreSingleFieldName,
4888
+ true,
4889
+ tableFeatures.requireWhere,
4890
+ filterCtx,
4891
+ mutationTxCtx,
4892
+ policies,
4893
+ true
4894
+ ) : void 0;
4758
4895
  const updateCountGenerated = tableFeatures.update && tableFeatures.countMutations ? generateWriteCount({
4759
4896
  db,
4760
4897
  tableName,
@@ -4787,7 +4924,7 @@ var generateSchemaData = (db, schema, relations, options) => {
4787
4924
  aggregateFieldName,
4788
4925
  tableFilters,
4789
4926
  filterCtx,
4790
- scopes
4927
+ tablePolicies
4791
4928
  ) : void 0;
4792
4929
  const groupByType = tableFeatures.aggregates && tableFeatures.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
4793
4930
  const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
@@ -4802,7 +4939,7 @@ var generateSchemaData = (db, schema, relations, options) => {
4802
4939
  groupByEnum,
4803
4940
  havingInput,
4804
4941
  filterCtx,
4805
- scopes
4942
+ tablePolicies
4806
4943
  ) : void 0;
4807
4944
  queries[selectArrGenerated.name] = {
4808
4945
  type: selectArrOutput,
@@ -4852,7 +4989,9 @@ var generateSchemaData = (db, schema, relations, options) => {
4852
4989
  [updateManyGenerated, { operation: "updateMany", single: false, targetArg: "updates" }],
4853
4990
  [updateSingleGenerated, { operation: "update", single: true, targetArg: "where" }],
4854
4991
  [deleteGenerated, { operation: "delete", single: false, targetArg: "where" }],
4855
- [deleteSingleGenerated, { operation: "delete", single: true, targetArg: "where" }]
4992
+ [deleteSingleGenerated, { operation: "delete", single: true, targetArg: "where" }],
4993
+ [restoreGenerated, { operation: "restore", single: false, targetArg: "where" }],
4994
+ [restoreSingleGenerated, { operation: "restore", single: true, targetArg: "where" }]
4856
4995
  ];
4857
4996
  for (const [generated, meta] of generatedMutations) {
4858
4997
  if (generated) {
@@ -5142,7 +5281,7 @@ var createNestedWriteTypes = (params) => {
5142
5281
  var mergedOps = (entries) => Object.assign({}, ...entries.map((entry) => entry.ops));
5143
5282
  var asArray = (value) => Array.isArray(value) ? value : value === void 0 ? [] : [value];
5144
5283
  var createNestedWriteRuntime = (params) => {
5145
- const { plans, filterCtx, scopes, contextValues } = params;
5284
+ const { plans, filterCtx, policies, contextValues } = params;
5146
5285
  const conditionOf = (plan, filter, operation, scope) => {
5147
5286
  const condition = extractFilters(
5148
5287
  plan.targetTable,
@@ -5205,7 +5344,7 @@ var createNestedWriteRuntime = (params) => {
5205
5344
  if (!tablePlans) {
5206
5345
  return patch;
5207
5346
  }
5208
- const scope = resolveScope(scopes, context, filterCtx);
5347
+ const scope = resolveScope(policies, context, filterCtx);
5209
5348
  for (const [relationName, op] of Object.entries(ops)) {
5210
5349
  const plan = tablePlans[relationName];
5211
5350
  if (!plan || plan.fkSide !== "parent") {
@@ -5245,7 +5384,7 @@ var createNestedWriteRuntime = (params) => {
5245
5384
  if (!tablePlans) {
5246
5385
  return;
5247
5386
  }
5248
- const scope = resolveScope(scopes, context, filterCtx);
5387
+ const scope = resolveScope(policies, context, filterCtx);
5249
5388
  for (const [relationName, op] of Object.entries(ops)) {
5250
5389
  const plan = tablePlans[relationName];
5251
5390
  if (!plan || plan.fkSide !== "child") {
@@ -5337,7 +5476,9 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
5337
5476
  const queryArgs = selectArrayArgs(
5338
5477
  orderArgs,
5339
5478
  filterArgs,
5340
- distinctEnabled ? generateDistinctEnum(table, typeName) : void 0
5479
+ distinctEnabled ? generateDistinctEnum(table, typeName) : void 0,
5480
+ policies?.softDelete,
5481
+ tableName
5341
5482
  );
5342
5483
  return {
5343
5484
  name: fieldName,
@@ -5369,7 +5510,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
5369
5510
  nullOrdering: "nulls-largest"
5370
5511
  });
5371
5512
  }
5372
- const { offset, orderBy, where, distinct, after } = args;
5513
+ const { offset, orderBy, where, distinct, after, deleted } = args;
5373
5514
  const selectedColumnsSql = extractSelectedColumnsFromTreeSQLFormat(
5374
5515
  parsedInfo.fieldsByTypeName[typeName],
5375
5516
  table,
@@ -5407,7 +5548,8 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
5407
5548
  scope,
5408
5549
  tableName,
5409
5550
  table,
5410
- where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
5551
+ where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0,
5552
+ deleted
5411
5553
  );
5412
5554
  const whereSql = cursorCondition ? and4(baseWhereSql, cursorCondition) : baseWhereSql;
5413
5555
  let distinctKeys;
@@ -5465,7 +5607,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
5465
5607
  };
5466
5608
  var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, limits, policies) => {
5467
5609
  const queryBase = db.query[tableName];
5468
- const queryArgs = selectSingleArgs(orderArgs, filterArgs);
5610
+ const queryArgs = selectSingleArgs(orderArgs, filterArgs, policies?.softDelete, tableName);
5469
5611
  const table = tables[tableName];
5470
5612
  const pkNames = pgPrimaryKeyPropNames(table);
5471
5613
  return {
@@ -5494,7 +5636,7 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
5494
5636
  scope
5495
5637
  });
5496
5638
  }
5497
- const { offset, orderBy, where } = args;
5639
+ const { offset, orderBy, where, deleted } = args;
5498
5640
  const selectedColumnsSql = extractSelectedColumnsFromTreeSQLFormat(
5499
5641
  parsedInfo.fieldsByTypeName[typeName],
5500
5642
  table,
@@ -5505,7 +5647,8 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
5505
5647
  scope,
5506
5648
  tableName,
5507
5649
  table,
5508
- where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
5650
+ where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0,
5651
+ deleted
5509
5652
  );
5510
5653
  if (whereSql) {
5511
5654
  q = q.where(whereSql);
@@ -5933,7 +6076,8 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
5933
6076
  args: queryArgs
5934
6077
  };
5935
6078
  };
5936
- var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx, policies) => {
6079
+ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx, policies, restore = false) => {
6080
+ const softDelete = policies?.softDelete?.(tableName);
5937
6081
  const queryArgs = {
5938
6082
  where: {
5939
6083
  type: single || requireWhere ? new GraphQLNonNull7(filterArgs) : filterArgs
@@ -5959,12 +6103,13 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, si
5959
6103
  scope,
5960
6104
  tableName,
5961
6105
  table,
5962
- single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0
6106
+ single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0,
6107
+ restore ? "ONLY" : void 0
5963
6108
  );
5964
6109
  if (single) {
5965
6110
  await assertSingleMatch(executor, table, filters, fieldName);
5966
6111
  }
5967
- let query = executor.delete(table);
6112
+ let query = softDelete ? executor.update(table).set({ [softDelete.columnName]: restore ? softDelete.writeRestored : softDelete.writeDeleted() }) : executor.delete(table);
5968
6113
  if (filters) {
5969
6114
  query = query.where(filters);
5970
6115
  }
@@ -6018,16 +6163,17 @@ function generateSchemaData2(db, schema, relations, options) {
6018
6163
  attachTargetPrimaryKeys(namedRelations, tables, pgPrimaryKeyPropNames);
6019
6164
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
6020
6165
  const filterCtx = { tables, relationMap: namedRelations };
6021
- const scopes = options.policies?.scope;
6022
- const contextValuesOf = options.policies?.contextValues;
6023
- const policies = bindPolicies(options.policies, filterCtx);
6166
+ const tablePolicies = options.policies;
6167
+ const contextValuesOf = tablePolicies?.contextValues;
6168
+ const softDeleteOf = tablePolicies?.softDelete;
6169
+ const policies = bindPolicies(tablePolicies, filterCtx);
6024
6170
  const resolverFactory = createRelationResolverFactory(
6025
6171
  db,
6026
6172
  tables,
6027
6173
  "nulls-largest",
6028
6174
  filterCtx,
6029
6175
  limits,
6030
- scopes
6176
+ tablePolicies
6031
6177
  );
6032
6178
  const cacheCtx = {
6033
6179
  genericFilterCache: /* @__PURE__ */ new Map(),
@@ -6046,6 +6192,7 @@ function generateSchemaData2(db, schema, relations, options) {
6046
6192
  docs: options.docs ?? {},
6047
6193
  primaryKeyOf: (name) => tables[name] ? pgPrimaryKeyPropNames(tables[name]) : [],
6048
6194
  contextValuesOf,
6195
+ softDeleteOf,
6049
6196
  featureOf
6050
6197
  };
6051
6198
  const nestedPlans = features.nestedWrites ? buildNestedWritePlans(
@@ -6056,8 +6203,13 @@ function generateSchemaData2(db, schema, relations, options) {
6056
6203
  extractRelationJoinColumns
6057
6204
  ) : void 0;
6058
6205
  const nestedTypes = nestedPlans ? createNestedWriteTypes({ plans: nestedPlans, cacheCtx, typeNameMapper, insertPrefix: prefixes.insert }) : void 0;
6059
- const nestedRuntime = nestedPlans ? createNestedWriteRuntime({ plans: nestedPlans, filterCtx, scopes, contextValues: contextValuesOf }) : void 0;
6060
- const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, scopes) : void 0;
6206
+ const nestedRuntime = nestedPlans ? createNestedWriteRuntime({
6207
+ plans: nestedPlans,
6208
+ filterCtx,
6209
+ policies: tablePolicies,
6210
+ contextValues: contextValuesOf
6211
+ }) : void 0;
6212
+ const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, tablePolicies) : void 0;
6061
6213
  const queries = {};
6062
6214
  const mutations = {};
6063
6215
  const mutationTxCtx = createMutationTxCtx(options.transactions);
@@ -6103,8 +6255,11 @@ function generateSchemaData2(db, schema, relations, options) {
6103
6255
  updateCountFieldName,
6104
6256
  deleteFieldName,
6105
6257
  deleteSingleFieldName,
6258
+ restoreFieldName,
6259
+ restoreSingleFieldName,
6106
6260
  deleteCountFieldName
6107
6261
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
6262
+ const softDeleteInfo = softDeleteOf?.(tableName);
6108
6263
  const selectArrGenerated = generateSelectArray2(
6109
6264
  db,
6110
6265
  tableName,
@@ -6295,6 +6450,36 @@ function generateSchemaData2(db, schema, relations, options) {
6295
6450
  mutationTxCtx,
6296
6451
  policies
6297
6452
  ) : void 0;
6453
+ const restoreGenerated = softDeleteInfo ? generateDelete2(
6454
+ db,
6455
+ tableName,
6456
+ schema[tableName],
6457
+ tableFilters,
6458
+ restoreFieldName,
6459
+ typeName,
6460
+ false,
6461
+ tableFeatures.requireWhere,
6462
+ filterCtx,
6463
+ { tableName, relationMap: namedRelations, tables },
6464
+ mutationTxCtx,
6465
+ policies,
6466
+ true
6467
+ ) : void 0;
6468
+ const restoreSingleGenerated = softDeleteInfo ? generateDelete2(
6469
+ db,
6470
+ tableName,
6471
+ schema[tableName],
6472
+ tableFilters,
6473
+ restoreSingleFieldName,
6474
+ typeName,
6475
+ true,
6476
+ tableFeatures.requireWhere,
6477
+ filterCtx,
6478
+ { tableName, relationMap: namedRelations, tables },
6479
+ mutationTxCtx,
6480
+ policies,
6481
+ true
6482
+ ) : void 0;
6298
6483
  const updateCountGenerated = tableFeatures.update && tableFeatures.countMutations ? generateWriteCount({
6299
6484
  db,
6300
6485
  tableName,
@@ -6328,7 +6513,7 @@ function generateSchemaData2(db, schema, relations, options) {
6328
6513
  aggregateFieldName,
6329
6514
  tableFilters,
6330
6515
  filterCtx,
6331
- scopes
6516
+ tablePolicies
6332
6517
  ) : void 0;
6333
6518
  const groupByType = tableFeatures.aggregates && tableFeatures.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
6334
6519
  const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
@@ -6343,7 +6528,7 @@ function generateSchemaData2(db, schema, relations, options) {
6343
6528
  groupByEnum,
6344
6529
  havingInput,
6345
6530
  filterCtx,
6346
- scopes
6531
+ tablePolicies
6347
6532
  ) : void 0;
6348
6533
  queries[selectArrGenerated.name] = {
6349
6534
  type: selectArrOutput,
@@ -6480,6 +6665,26 @@ function generateSchemaData2(db, schema, relations, options) {
6480
6665
  }
6481
6666
  };
6482
6667
  }
6668
+ if (restoreGenerated) {
6669
+ mutations[restoreGenerated.name] = {
6670
+ type: arrTableItemOutput,
6671
+ args: restoreGenerated.args,
6672
+ resolve: restoreGenerated.resolver,
6673
+ extensions: {
6674
+ drizzle: drizzleMeta({ kind: "mutation", operation: "restore", single: false, targetArg: "where" })
6675
+ }
6676
+ };
6677
+ }
6678
+ if (restoreSingleGenerated) {
6679
+ mutations[restoreSingleGenerated.name] = {
6680
+ type: singleTableItemOutput,
6681
+ args: restoreSingleGenerated.args,
6682
+ resolve: restoreSingleGenerated.resolver,
6683
+ extensions: {
6684
+ drizzle: drizzleMeta({ kind: "mutation", operation: "restore", single: true, targetArg: "where" })
6685
+ }
6686
+ };
6687
+ }
6483
6688
  if (updateCountGenerated) {
6484
6689
  mutations[updateCountGenerated.name] = {
6485
6690
  type: new GraphQLNonNull7(GraphQLInt6),
@@ -6563,7 +6768,9 @@ var generateSelectArray3 = (db, tableName, tables, relationMap, orderArgs, filte
6563
6768
  const queryArgs = selectArrayArgs(
6564
6769
  orderArgs,
6565
6770
  filterArgs,
6566
- distinctEnabled ? generateDistinctEnum(table, typeName) : void 0
6771
+ distinctEnabled ? generateDistinctEnum(table, typeName) : void 0,
6772
+ policies?.softDelete,
6773
+ tableName
6567
6774
  );
6568
6775
  return {
6569
6776
  name: fieldName,
@@ -6605,7 +6812,7 @@ var generateSelectSingle3 = (db, tableName, tables, relationMap, orderArgs, filt
6605
6812
  `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`
6606
6813
  );
6607
6814
  }
6608
- const queryArgs = selectSingleArgs(orderArgs, filterArgs);
6815
+ const queryArgs = selectSingleArgs(orderArgs, filterArgs, policies?.softDelete, tableName);
6609
6816
  const table = tables[tableName];
6610
6817
  const pkNames = sqlitePrimaryKeyPropNames(table);
6611
6818
  return {
@@ -7071,7 +7278,8 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
7071
7278
  args: queryArgs
7072
7279
  };
7073
7280
  };
7074
- var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx, policies) => {
7281
+ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx, policies, restore = false) => {
7282
+ const softDelete = policies?.softDelete?.(tableName);
7075
7283
  const queryArgs = {
7076
7284
  where: {
7077
7285
  type: single || requireWhere ? new GraphQLNonNull8(filterArgs) : filterArgs
@@ -7097,12 +7305,13 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, si
7097
7305
  scope,
7098
7306
  tableName,
7099
7307
  table,
7100
- single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0
7308
+ single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0,
7309
+ restore ? "ONLY" : void 0
7101
7310
  );
7102
7311
  if (single) {
7103
7312
  await assertSingleMatch(executor, table, filters, fieldName);
7104
7313
  }
7105
- let query = executor.delete(table);
7314
+ let query = softDelete ? executor.update(table).set({ [softDelete.columnName]: restore ? softDelete.writeRestored : softDelete.writeDeleted() }) : executor.delete(table);
7106
7315
  if (filters) {
7107
7316
  query = query.where(filters);
7108
7317
  }
@@ -7157,16 +7366,17 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7157
7366
  attachTargetPrimaryKeys(namedRelations, tables, sqlitePrimaryKeyPropNames);
7158
7367
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
7159
7368
  const filterCtx = { tables, relationMap: namedRelations };
7160
- const scopes = options.policies?.scope;
7161
- const contextValuesOf = options.policies?.contextValues;
7162
- const policies = bindPolicies(options.policies, filterCtx);
7369
+ const tablePolicies = options.policies;
7370
+ const contextValuesOf = tablePolicies?.contextValues;
7371
+ const softDeleteOf = tablePolicies?.softDelete;
7372
+ const policies = bindPolicies(tablePolicies, filterCtx);
7163
7373
  const resolverFactory = createRelationResolverFactory(
7164
7374
  db,
7165
7375
  tables,
7166
7376
  "nulls-smallest",
7167
7377
  filterCtx,
7168
7378
  limits,
7169
- scopes
7379
+ tablePolicies
7170
7380
  );
7171
7381
  const cacheCtx = {
7172
7382
  genericFilterCache: /* @__PURE__ */ new Map(),
@@ -7185,6 +7395,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7185
7395
  docs: options.docs ?? {},
7186
7396
  primaryKeyOf: (name) => tables[name] ? sqlitePrimaryKeyPropNames(tables[name]) : [],
7187
7397
  contextValuesOf,
7398
+ softDeleteOf,
7188
7399
  featureOf
7189
7400
  };
7190
7401
  if (features.nestedWrites && db.resultKind === "sync") {
@@ -7200,8 +7411,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7200
7411
  extractRelationJoinColumns
7201
7412
  ) : void 0;
7202
7413
  const nestedTypes = nestedPlans ? createNestedWriteTypes({ plans: nestedPlans, cacheCtx, typeNameMapper, insertPrefix: prefixes.insert }) : void 0;
7203
- const nestedRuntime = nestedPlans ? createNestedWriteRuntime({ plans: nestedPlans, filterCtx, scopes, contextValues: contextValuesOf }) : void 0;
7204
- const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, scopes) : void 0;
7414
+ const nestedRuntime = nestedPlans ? createNestedWriteRuntime({
7415
+ plans: nestedPlans,
7416
+ filterCtx,
7417
+ policies: tablePolicies,
7418
+ contextValues: contextValuesOf
7419
+ }) : void 0;
7420
+ const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, tablePolicies) : void 0;
7205
7421
  const queries = {};
7206
7422
  const mutations = {};
7207
7423
  if (options.transactions && db.resultKind === "sync") {
@@ -7252,8 +7468,11 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7252
7468
  updateCountFieldName,
7253
7469
  deleteFieldName,
7254
7470
  deleteSingleFieldName,
7471
+ restoreFieldName,
7472
+ restoreSingleFieldName,
7255
7473
  deleteCountFieldName
7256
7474
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
7475
+ const softDeleteInfo = softDeleteOf?.(tableName);
7257
7476
  const selectArrGenerated = generateSelectArray3(
7258
7477
  db,
7259
7478
  tableName,
@@ -7444,6 +7663,36 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7444
7663
  mutationTxCtx,
7445
7664
  policies
7446
7665
  ) : void 0;
7666
+ const restoreGenerated = softDeleteInfo ? generateDelete3(
7667
+ db,
7668
+ tableName,
7669
+ schema[tableName],
7670
+ tableFilters,
7671
+ restoreFieldName,
7672
+ typeName,
7673
+ false,
7674
+ tableFeatures.requireWhere,
7675
+ filterCtx,
7676
+ { tableName, relationMap: namedRelations, tables },
7677
+ mutationTxCtx,
7678
+ policies,
7679
+ true
7680
+ ) : void 0;
7681
+ const restoreSingleGenerated = softDeleteInfo ? generateDelete3(
7682
+ db,
7683
+ tableName,
7684
+ schema[tableName],
7685
+ tableFilters,
7686
+ restoreSingleFieldName,
7687
+ typeName,
7688
+ true,
7689
+ tableFeatures.requireWhere,
7690
+ filterCtx,
7691
+ { tableName, relationMap: namedRelations, tables },
7692
+ mutationTxCtx,
7693
+ policies,
7694
+ true
7695
+ ) : void 0;
7447
7696
  const updateCountGenerated = tableFeatures.update && tableFeatures.countMutations ? generateWriteCount({
7448
7697
  db,
7449
7698
  tableName,
@@ -7477,7 +7726,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7477
7726
  aggregateFieldName,
7478
7727
  tableFilters,
7479
7728
  filterCtx,
7480
- scopes
7729
+ tablePolicies
7481
7730
  ) : void 0;
7482
7731
  const groupByType = tableFeatures.aggregates && tableFeatures.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
7483
7732
  const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
@@ -7492,7 +7741,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7492
7741
  groupByEnum,
7493
7742
  havingInput,
7494
7743
  filterCtx,
7495
- scopes
7744
+ tablePolicies
7496
7745
  ) : void 0;
7497
7746
  queries[selectArrGenerated.name] = {
7498
7747
  type: selectArrOutput,
@@ -7629,6 +7878,26 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7629
7878
  }
7630
7879
  };
7631
7880
  }
7881
+ if (restoreGenerated) {
7882
+ mutations[restoreGenerated.name] = {
7883
+ type: arrTableItemOutput,
7884
+ args: restoreGenerated.args,
7885
+ resolve: restoreGenerated.resolver,
7886
+ extensions: {
7887
+ drizzle: drizzleMeta({ kind: "mutation", operation: "restore", single: false, targetArg: "where" })
7888
+ }
7889
+ };
7890
+ }
7891
+ if (restoreSingleGenerated) {
7892
+ mutations[restoreSingleGenerated.name] = {
7893
+ type: singleTableItemOutput,
7894
+ args: restoreSingleGenerated.args,
7895
+ resolve: restoreSingleGenerated.resolver,
7896
+ extensions: {
7897
+ drizzle: drizzleMeta({ kind: "mutation", operation: "restore", single: true, targetArg: "where" })
7898
+ }
7899
+ };
7900
+ }
7632
7901
  if (updateCountGenerated) {
7633
7902
  mutations[updateCountGenerated.name] = {
7634
7903
  type: new GraphQLNonNull8(GraphQLInt7),
@@ -7839,7 +8108,8 @@ var buildSchema = (db, config) => {
7839
8108
  insert: config?.prefixes?.insert ?? "create",
7840
8109
  delete: config?.prefixes?.delete ?? "delete",
7841
8110
  update: config?.prefixes?.update ?? "update",
7842
- upsert: config?.prefixes?.upsert ?? "upsert"
8111
+ upsert: config?.prefixes?.upsert ?? "upsert",
8112
+ restore: config?.prefixes?.restore ?? "restore"
7843
8113
  };
7844
8114
  const suffixes = {
7845
8115
  list: config?.suffixes?.list ?? "",
@@ -7917,9 +8187,32 @@ var buildSchema = (db, config) => {
7917
8187
  }
7918
8188
  }
7919
8189
  }
7920
- const policies = scopeConfig || contextValuesConfig ? {
8190
+ const softDeleteConfig = config?.softDelete;
8191
+ const softDeleteInfos = /* @__PURE__ */ new Map();
8192
+ if (softDeleteConfig) {
8193
+ if (typeof softDeleteConfig === "function") {
8194
+ for (const tableName of tableKeys) {
8195
+ const declaration = softDeleteConfig(schema[tableName], tableName);
8196
+ if (declaration) {
8197
+ softDeleteInfos.set(tableName, resolveSoftDeleteInfo(schema[tableName], tableName, declaration));
8198
+ }
8199
+ }
8200
+ } else {
8201
+ const tableNames = new Set(tableKeys);
8202
+ for (const [tableName, declaration] of Object.entries(softDeleteConfig)) {
8203
+ if (!tableNames.has(tableName)) {
8204
+ throw new Error(
8205
+ `Drizzle-GraphQL Error: config.softDelete names '${tableName}', which is not a table in the Drizzle schema.`
8206
+ );
8207
+ }
8208
+ softDeleteInfos.set(tableName, resolveSoftDeleteInfo(schema[tableName], tableName, declaration));
8209
+ }
8210
+ }
8211
+ }
8212
+ const policies = scopeConfig || contextValuesConfig || softDeleteInfos.size ? {
7921
8213
  scope: scopeConfig ? (tableName) => scopeConfig[tableName] : void 0,
7922
- contextValues: contextValuesConfig ? (tableName) => contextValuesConfig[tableName] : void 0
8214
+ contextValues: contextValuesConfig ? (tableName) => contextValuesConfig[tableName] : void 0,
8215
+ softDelete: softDeleteInfos.size ? (tableName) => softDeleteInfos.get(tableName) : void 0
7923
8216
  } : void 0;
7924
8217
  const exclude = config?.exclude;
7925
8218
  if (exclude) {