@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.cjs CHANGED
@@ -1144,7 +1144,7 @@ var batchedPaginatedRelationQuery = async (db, targetTable, foreignCol, whereCon
1144
1144
  }
1145
1145
  return rows;
1146
1146
  };
1147
- var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits, scopes) => ({ tableName, relationName, relEntry, isOne }) => {
1147
+ var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits, policies) => ({ tableName, relationName, relEntry, isOne }) => {
1148
1148
  const parentTable = tables[tableName];
1149
1149
  const targetTableName = relEntry.targetTableName;
1150
1150
  const targetTable = tables[targetTableName];
@@ -1166,7 +1166,14 @@ var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits
1166
1166
  if (localValue == null) {
1167
1167
  return isOne ? null : [];
1168
1168
  }
1169
- const { where: whereArg, orderBy: orderByArg, limit: requestedLimit, offset, after } = args ?? {};
1169
+ const {
1170
+ where: whereArg,
1171
+ orderBy: orderByArg,
1172
+ limit: requestedLimit,
1173
+ offset,
1174
+ after,
1175
+ deleted
1176
+ } = args ?? {};
1170
1177
  const limit = applyLimitPolicy(requestedLimit, limitPolicy, `${tableName}.${relationName}`);
1171
1178
  const distinct = (args ?? {}).distinct?.length ? (args ?? {}).distinct : void 0;
1172
1179
  const cursorSelected = !isOne && !!info && selectsCursorField(info, targetTable);
@@ -1197,6 +1204,7 @@ var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits
1197
1204
  orderBy: orderByArg ?? null,
1198
1205
  limit: limit ?? null,
1199
1206
  offset: offset ?? null,
1207
+ deleted: deleted ?? null,
1200
1208
  after: after ?? null,
1201
1209
  distinct: distinct ?? null,
1202
1210
  cursor: cursorEntries ? 1 : 0
@@ -1205,7 +1213,7 @@ var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits
1205
1213
  const loader = getOrCreateLoader(context, loaderKey, async (parentIds) => {
1206
1214
  const executor = resolveExecutor(db, context);
1207
1215
  const uniqueIds = [...new Set(parentIds)];
1208
- const scope = resolveScope(scopes, context, filterCtx);
1216
+ const scope = resolveScope(policies, context, filterCtx);
1209
1217
  let whereCondition = withScope(
1210
1218
  scope,
1211
1219
  targetTableName,
@@ -1214,7 +1222,8 @@ var createRelationResolverFactory = (db, tables, nullOrdering, filterCtx, limits
1214
1222
  (0, import_drizzle_orm4.inArray)(foreignCol, uniqueIds),
1215
1223
  whereArg ? extractFilters(targetTable, targetTableName, whereArg, relationFilterCtx(filterCtx, targetTableName)) : void 0,
1216
1224
  cursorValues ? buildCursorCondition(targetTable, cursorEntries, cursorValues, nullOrdering) : void 0
1217
- )
1225
+ ),
1226
+ deleted
1218
1227
  );
1219
1228
  if (distinct) {
1220
1229
  const keys = await selectDistinctKeys({
@@ -2019,7 +2028,8 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
2019
2028
  {
2020
2029
  type: isRequired ? new import_graphql5.GraphQLNonNull(relType) : relType,
2021
2030
  args: {
2022
- where: { type: relSelectData.filters }
2031
+ where: { type: relSelectData.filters },
2032
+ ...deletedArg(cacheCtx.softDeleteOf, targetTableName)
2023
2033
  },
2024
2034
  resolve,
2025
2035
  ...relationDocs,
@@ -2038,6 +2048,7 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
2038
2048
  orderBy: { type: relSelectData.order },
2039
2049
  offset: { type: import_graphql5.GraphQLInt },
2040
2050
  limit: { type: import_graphql5.GraphQLInt },
2051
+ ...deletedArg(cacheCtx.softDeleteOf, targetTableName),
2041
2052
  after: {
2042
2053
  type: import_graphql5.GraphQLString,
2043
2054
  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)."
@@ -2065,7 +2076,8 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
2065
2076
  {
2066
2077
  type: new import_graphql5.GraphQLNonNull(relationAggregate.type),
2067
2078
  args: {
2068
- where: { type: relSelectData.filters }
2079
+ where: { type: relSelectData.filters },
2080
+ ...deletedArg(cacheCtx.softDeleteOf, targetTableName)
2069
2081
  },
2070
2082
  resolve: relationAggregate.resolve,
2071
2083
  extensions: {
@@ -2121,7 +2133,10 @@ var generateTableTypes = (tableName, tables, relationMap, withReturning, relatio
2121
2133
  const columns = visibleColumns(table);
2122
2134
  const columnEntries = Object.entries(columns);
2123
2135
  const contextColumns = cacheCtx.contextValuesOf?.(tableName);
2124
- const writableEntries = contextColumns ? columnEntries.filter(([columnName]) => !(columnName in contextColumns)) : columnEntries;
2136
+ const markerColumn = cacheCtx.softDeleteOf?.(tableName)?.columnName;
2137
+ const writableEntries = contextColumns || markerColumn ? columnEntries.filter(
2138
+ ([columnName]) => !(contextColumns && columnName in contextColumns) && columnName !== markerColumn
2139
+ ) : columnEntries;
2125
2140
  const relaxedColumns = nestedWrites?.relaxedColumns(tableName);
2126
2141
  const insertFields = Object.fromEntries(
2127
2142
  writableEntries.map(([columnName, column]) => {
@@ -2663,40 +2678,103 @@ var extractFilters = (table, tableName, filters, relationCtx) => {
2663
2678
  }
2664
2679
  return variants.length ? variants.length > 1 ? (0, import_drizzle_orm4.and)(...variants) : variants[0] : void 0;
2665
2680
  };
2666
- var resolveScope = (scopes, context, filterCtx) => {
2667
- if (!scopes) {
2681
+ var deletedFilterEnum = new import_graphql5.GraphQLEnumType({
2682
+ name: "DeletedFilter",
2683
+ description: "Which rows a read over a soft-deleting table returns.",
2684
+ values: {
2685
+ EXCLUDE: { value: "EXCLUDE", description: "Only rows that are not marked deleted. The default." },
2686
+ INCLUDE: { value: "INCLUDE", description: "Marked and unmarked rows alike." },
2687
+ ONLY: { value: "ONLY", description: "Only rows that are marked deleted \u2014 a trash view." }
2688
+ }
2689
+ });
2690
+ var resolveSoftDeleteInfo = (table, tableName, declaration) => {
2691
+ const config = typeof declaration === "string" ? { column: declaration } : declaration;
2692
+ const columnName = config?.column;
2693
+ if (typeof columnName !== "string" || !columnName) {
2694
+ throw new Error(
2695
+ `Drizzle-GraphQL Error: config.softDelete.${tableName} must be a column name or an object with a 'column' property.`
2696
+ );
2697
+ }
2698
+ const column = (0, import_drizzle_orm4.getColumns)(table)[columnName];
2699
+ if (!column) {
2700
+ throw new Error(
2701
+ `Drizzle-GraphQL Error: config.softDelete names '${tableName}.${columnName}', which is not a column of that table.`
2702
+ );
2703
+ }
2704
+ const nullable = !column.notNull;
2705
+ const { type: baseType, constraint } = (0, import_drizzle_orm4.extractExtendedColumnType)(column);
2706
+ const hasDeleted = "deletedValue" in config && config.deletedValue !== void 0;
2707
+ 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;
2708
+ let marker;
2709
+ if (!nullable) {
2710
+ if (hasDeleted && typeof config.deletedValue !== "function") {
2711
+ marker = config.deletedValue;
2712
+ } else if (!hasDeleted && baseType === "boolean") {
2713
+ marker = true;
2714
+ } else {
2715
+ throw new Error(
2716
+ `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.`
2717
+ );
2718
+ }
2719
+ }
2720
+ const hasRestored = "restoredValue" in config;
2721
+ const writeRestored = hasRestored ? config.restoredValue : nullable ? null : baseType === "boolean" ? false : void 0;
2722
+ if (!nullable && writeRestored === void 0) {
2723
+ throw new Error(
2724
+ `Drizzle-GraphQL Error: config.softDelete.${tableName} marks a NOT NULL column ('${columnName}'), so 'restoredValue' must say what restoring writes back.`
2725
+ );
2726
+ }
2727
+ return { columnName, column, nullable, writeDeleted, writeRestored, marker };
2728
+ };
2729
+ var softDeletePredicate = (info, table, mode) => {
2730
+ if (mode === "INCLUDE") {
2731
+ return void 0;
2732
+ }
2733
+ const column = table?.[info.columnName] ?? info.column;
2734
+ if (info.nullable) {
2735
+ return mode === "ONLY" ? (0, import_drizzle_orm4.isNotNull)(column) : (0, import_drizzle_orm4.isNull)(column);
2736
+ }
2737
+ return mode === "ONLY" ? (0, import_drizzle_orm4.eq)(column, info.marker) : (0, import_drizzle_orm4.ne)(column, info.marker);
2738
+ };
2739
+ var resolveScope = (policies, context, filterCtx) => {
2740
+ const scopes = policies?.scope;
2741
+ const softDelete = policies?.softDelete;
2742
+ if (!scopes && !softDelete) {
2668
2743
  return void 0;
2669
2744
  }
2670
2745
  return {
2671
- has: (tableName) => !!scopes(tableName),
2672
- on: (tableName, table) => {
2673
- const hook = scopes(tableName);
2746
+ has: (tableName, mode) => !!scopes?.(tableName) || !!softDelete?.(tableName) && (mode ?? "EXCLUDE") !== "INCLUDE",
2747
+ on: (tableName, table, mode) => {
2748
+ const marked = softDelete?.(tableName);
2749
+ const deleted = marked ? softDeletePredicate(marked, table, mode ?? "EXCLUDE") : void 0;
2750
+ const hook = scopes?.(tableName);
2674
2751
  if (!hook) {
2675
- return void 0;
2752
+ return deleted;
2676
2753
  }
2677
2754
  const predicate = hook(context, table);
2678
2755
  if (predicate === void 0 || predicate === null) {
2679
- return void 0;
2756
+ return deleted;
2680
2757
  }
2681
2758
  if ((0, import_drizzle_orm4.is)(predicate, import_drizzle_orm4.SQL)) {
2682
- return predicate;
2759
+ return (0, import_drizzle_orm4.and)(deleted, predicate);
2683
2760
  }
2684
2761
  if (typeof predicate !== "object") {
2685
2762
  throw new import_graphql5.GraphQLError(
2686
2763
  `Drizzle-GraphQL Error: the scope for '${tableName}' returned a ${typeof predicate}. A scope returns a filter object, a Drizzle SQL expression, or undefined.`
2687
2764
  );
2688
2765
  }
2689
- return extractFilters(table, tableName, predicate, relationFilterCtx(filterCtx, tableName));
2766
+ return (0, import_drizzle_orm4.and)(deleted, extractFilters(table, tableName, predicate, relationFilterCtx(filterCtx, tableName)));
2690
2767
  }
2691
2768
  };
2692
2769
  };
2693
- var withScope = (scope, tableName, table, condition) => {
2694
- const predicate = scope?.on(tableName, table);
2770
+ var withScope = (scope, tableName, table, condition, mode) => {
2771
+ const predicate = scope?.on(tableName, table, mode);
2695
2772
  return predicate ? (0, import_drizzle_orm4.and)(condition, predicate) : condition;
2696
2773
  };
2697
- var bindPolicies = (policies, filterCtx) => policies?.scope || policies?.contextValues ? {
2698
- scope: policies.scope ? (context) => resolveScope(policies.scope, context, filterCtx) : void 0,
2699
- contextValues: policies.contextValues
2774
+ var bindPolicies = (policies, filterCtx) => policies?.scope || policies?.contextValues || policies?.softDelete ? {
2775
+ scope: policies.scope || policies.softDelete ? (context) => resolveScope(policies, context, filterCtx) : void 0,
2776
+ contextValues: policies.contextValues,
2777
+ softDelete: policies.softDelete
2700
2778
  } : void 0;
2701
2779
  var applyContextValues = (values, hooks, context) => {
2702
2780
  if (!hooks) {
@@ -2771,12 +2849,14 @@ var extractRelationsParamsInner = (relationMap, tables, tableName, typeName, ori
2771
2849
  const offset = relationArgs?.offset ?? void 0;
2772
2850
  const limit = (0, import_drizzle_orm4.is)(relEntry.relation, import_drizzle_orm4.One) ? relationArgs?.limit ?? void 0 : applyLimitPolicy(relationArgs?.limit, limits?.(targetTableName), `${tableName}.${relName}`);
2773
2851
  const relWhere = relationArgs?.where;
2774
- thisRecord.where = relWhere || scope?.has(targetTableName) ? {
2852
+ const relDeleted = relationArgs?.deleted;
2853
+ thisRecord.where = relWhere || scope?.has(targetTableName, relDeleted) ? {
2775
2854
  RAW: (aliasedTable2) => withScope(
2776
2855
  scope,
2777
2856
  targetTableName,
2778
2857
  aliasedTable2,
2779
- relWhere ? extractFilters(aliasedTable2, relName, relWhere, relationFilterCtx(filterCtx, targetTableName)) : void 0
2858
+ relWhere ? extractFilters(aliasedTable2, relName, relWhere, relationFilterCtx(filterCtx, targetTableName)) : void 0,
2859
+ relDeleted
2780
2860
  )
2781
2861
  } : void 0;
2782
2862
  const hasPagination = offset != null || limit != null;
@@ -3302,9 +3382,11 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
3302
3382
  const updateFieldName = `${prefixes.update}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
3303
3383
  const updateManyFieldName = `${prefixes.update}${mapped ? capitalize(mapped.plural) : capitalize(tableName)}Many`;
3304
3384
  const deleteFieldName = `${prefixes.delete}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
3385
+ const restoreFieldName = `${prefixes.restore ?? "restore"}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
3305
3386
  const writeSingleSuffix = suffixes.single === "" ? "Single" : suffixes.single;
3306
3387
  const updateSingleFieldName = `${updateFieldName}${writeSingleSuffix}`;
3307
3388
  const deleteSingleFieldName = `${deleteFieldName}${writeSingleSuffix}`;
3389
+ const restoreSingleFieldName = `${restoreFieldName}${writeSingleSuffix}`;
3308
3390
  const pluralNoun = mapped ? capitalize(mapped.plural) : capitalize(tableName);
3309
3391
  const updateCountFieldName = `${prefixes.update}${pluralNoun}Count`;
3310
3392
  const deleteCountFieldName = `${prefixes.delete}${pluralNoun}Count`;
@@ -3324,6 +3406,8 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
3324
3406
  updateCountFieldName,
3325
3407
  deleteFieldName,
3326
3408
  deleteSingleFieldName,
3409
+ restoreFieldName,
3410
+ restoreSingleFieldName,
3327
3411
  deleteCountFieldName
3328
3412
  };
3329
3413
  };
@@ -3428,7 +3512,13 @@ var generateWriteCount = ({
3428
3512
  args: queryArgs
3429
3513
  };
3430
3514
  };
3431
- var selectArrayArgs = (orderArgs, filterArgs, distinctEnum) => ({
3515
+ var deletedArg = (softDelete, tableName) => softDelete?.(tableName) ? {
3516
+ deleted: {
3517
+ type: deletedFilterEnum,
3518
+ description: "Whether rows marked deleted are returned. Defaults to EXCLUDE."
3519
+ }
3520
+ } : {};
3521
+ var selectArrayArgs = (orderArgs, filterArgs, distinctEnum, softDelete, tableName) => ({
3432
3522
  offset: { type: import_graphql5.GraphQLInt },
3433
3523
  limit: { type: import_graphql5.GraphQLInt },
3434
3524
  orderBy: { type: orderArgs },
@@ -3437,12 +3527,14 @@ var selectArrayArgs = (orderArgs, filterArgs, distinctEnum) => ({
3437
3527
  type: import_graphql5.GraphQLString,
3438
3528
  description: "Keyset pagination: only return rows strictly after this cursor (a row's `cursor` field from a previous page, under the same orderBy)."
3439
3529
  },
3440
- ...distinctEnum ? { distinct: { type: new import_graphql5.GraphQLList(new import_graphql5.GraphQLNonNull(distinctEnum)) } } : {}
3530
+ ...distinctEnum ? { distinct: { type: new import_graphql5.GraphQLList(new import_graphql5.GraphQLNonNull(distinctEnum)) } } : {},
3531
+ ...deletedArg(softDelete, tableName)
3441
3532
  });
3442
- var selectSingleArgs = (orderArgs, filterArgs) => ({
3533
+ var selectSingleArgs = (orderArgs, filterArgs, softDelete, tableName) => ({
3443
3534
  offset: { type: import_graphql5.GraphQLInt },
3444
3535
  orderBy: { type: orderArgs },
3445
- where: { type: filterArgs }
3536
+ where: { type: filterArgs },
3537
+ ...deletedArg(softDelete, tableName)
3446
3538
  });
3447
3539
  var runRelationalSelect = async (opts) => {
3448
3540
  const {
@@ -3461,7 +3553,8 @@ var runRelationalSelect = async (opts) => {
3461
3553
  filterCtx,
3462
3554
  pkNames,
3463
3555
  after,
3464
- scope
3556
+ scope,
3557
+ deleted
3465
3558
  } = opts;
3466
3559
  const distinct = opts.distinct?.length ? opts.distinct : void 0;
3467
3560
  const cursorSelected = !single && isCursorFieldSelected(parsedInfo.fieldsByTypeName[typeName], table);
@@ -3497,7 +3590,8 @@ var runRelationalSelect = async (opts) => {
3497
3590
  scope,
3498
3591
  tableName,
3499
3592
  table,
3500
- where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
3593
+ where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0,
3594
+ deleted
3501
3595
  ),
3502
3596
  orderBy,
3503
3597
  limit: single ? 1 : opts.limit,
@@ -3528,7 +3622,7 @@ var runRelationalSelect = async (opts) => {
3528
3622
  where: distinctKeys ? (
3529
3623
  // The distinct pass already ran inside the scope, so the keys it picked are in it.
3530
3624
  { RAW: (aliasedTable2) => primaryKeyRestriction(aliasedTable2, pkNames, distinctKeys) }
3531
- ) : where || cursorValues || scope?.has(tableName) ? {
3625
+ ) : where || cursorValues || scope?.has(tableName, deleted) ? {
3532
3626
  RAW: (aliasedTable2) => withScope(
3533
3627
  scope,
3534
3628
  tableName,
@@ -3541,7 +3635,8 @@ var runRelationalSelect = async (opts) => {
3541
3635
  cursorValues,
3542
3636
  opts.nullOrdering ?? "nulls-smallest"
3543
3637
  ) : void 0
3544
- )
3638
+ ),
3639
+ deleted
3545
3640
  )
3546
3641
  } : void 0,
3547
3642
  with: relationMap[tableName] ? extractRelationsParams(
@@ -3858,10 +3953,11 @@ var assembleAggregateRow = (row, request, target) => {
3858
3953
  }
3859
3954
  return result;
3860
3955
  };
3861
- var generateAggregate = (db, tableName, table, typeName, fieldName, filterArgs, filterCtx, scopes) => {
3956
+ var generateAggregate = (db, tableName, table, typeName, fieldName, filterArgs, filterCtx, policies) => {
3862
3957
  const target = aggregateTarget(table, tableName, typeName);
3863
3958
  const queryArgs = {
3864
- where: { type: filterArgs }
3959
+ where: { type: filterArgs },
3960
+ ...deletedArg(policies?.softDelete, tableName)
3865
3961
  };
3866
3962
  return {
3867
3963
  name: fieldName,
@@ -3873,10 +3969,11 @@ var generateAggregate = (db, tableName, table, typeName, fieldName, filterArgs,
3873
3969
  }
3874
3970
  let query = resolveExecutor(db, context).select(request.selection).from(table);
3875
3971
  const where = withScope(
3876
- resolveScope(scopes, context, filterCtx),
3972
+ resolveScope(policies, context, filterCtx),
3877
3973
  tableName,
3878
3974
  table,
3879
- args.where ? extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)) : void 0
3975
+ args.where ? extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)) : void 0,
3976
+ args.deleted
3880
3977
  );
3881
3978
  if (where) {
3882
3979
  query = query.where(where);
@@ -3891,7 +3988,7 @@ var generateAggregate = (db, tableName, table, typeName, fieldName, filterArgs,
3891
3988
  };
3892
3989
  };
3893
3990
  var GROUP_KEY = "__dgql_group_key";
3894
- var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filterCtx, scopes) => {
3991
+ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filterCtx, policies) => {
3895
3992
  return ({ tableName, relationName, relEntry }) => {
3896
3993
  const parentTable = tables[tableName];
3897
3994
  const targetTableName = relEntry.targetTableName;
@@ -3918,8 +4015,10 @@ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filt
3918
4015
  return assembleAggregateRow({}, request, target);
3919
4016
  }
3920
4017
  const whereArg = args?.where;
4018
+ const deleted = args?.deleted;
3921
4019
  const argsKey = JSON.stringify({
3922
4020
  where: whereArg ?? null,
4021
+ deleted: deleted ?? null,
3923
4022
  selection: Object.keys(request.selection).sort()
3924
4023
  });
3925
4024
  const loaderKey = `${tableName}::${relationName}::aggregate::${argsKey}`;
@@ -3927,13 +4026,14 @@ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filt
3927
4026
  const executor = resolveExecutor(db, context);
3928
4027
  const uniqueIds = [...new Set(parentIds)];
3929
4028
  const whereCondition = withScope(
3930
- resolveScope(scopes, context, filterCtx),
4029
+ resolveScope(policies, context, filterCtx),
3931
4030
  targetTableName,
3932
4031
  targetTable,
3933
4032
  (0, import_drizzle_orm5.and)(
3934
4033
  (0, import_drizzle_orm5.inArray)(foreignCol, uniqueIds),
3935
4034
  whereArg ? extractFilters(targetTable, targetTableName, whereArg, relationFilterCtx(filterCtx, targetTableName)) : void 0
3936
- )
4035
+ ),
4036
+ deleted
3937
4037
  );
3938
4038
  const rows = await executor.select({ [GROUP_KEY]: foreignCol, ...request.selection }).from(targetTable).where(whereCondition).groupBy(foreignCol);
3939
4039
  const byKey = new Map(rows.map((row) => [row[GROUP_KEY], row]));
@@ -4066,7 +4166,7 @@ var buildHavingCondition = (having, columns) => {
4066
4166
  }
4067
4167
  return conditions.length ? (0, import_drizzle_orm5.and)(...conditions) : void 0;
4068
4168
  };
4069
- var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, groupByEnum, havingInput, filterCtx, scopes) => {
4169
+ var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, groupByEnum, havingInput, filterCtx, policies) => {
4070
4170
  const target = aggregateTarget(table, tableName, typeName);
4071
4171
  const groupable = groupableColumns(table, tableName);
4072
4172
  const columns = (0, import_drizzle_orm5.getColumns)(table);
@@ -4077,7 +4177,8 @@ var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, gr
4077
4177
  description: "Columns to group by. One result row per distinct combination of their values."
4078
4178
  },
4079
4179
  where: { type: filterArgs, description: "Filters the rows before they are grouped." },
4080
- having: { type: havingInput, description: "Filters the groups after they are aggregated." }
4180
+ having: { type: havingInput, description: "Filters the groups after they are aggregated." },
4181
+ ...deletedArg(policies?.softDelete, tableName)
4081
4182
  };
4082
4183
  return {
4083
4184
  name: fieldName,
@@ -4101,10 +4202,11 @@ var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, gr
4101
4202
  };
4102
4203
  let query = resolveExecutor(db, context).select(selection).from(table);
4103
4204
  const where = withScope(
4104
- resolveScope(scopes, context, filterCtx),
4205
+ resolveScope(policies, context, filterCtx),
4105
4206
  tableName,
4106
4207
  table,
4107
- args.where ? extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)) : void 0
4208
+ args.where ? extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)) : void 0,
4209
+ args.deleted
4108
4210
  );
4109
4211
  if (where) {
4110
4212
  query = query.where(where);
@@ -4146,7 +4248,9 @@ var generateSelectArray = (db, tableName, tables, relationMap, orderArgs, filter
4146
4248
  const queryArgs = selectArrayArgs(
4147
4249
  orderArgs,
4148
4250
  filterArgs,
4149
- distinctEnabled ? generateDistinctEnum(table, typeName) : void 0
4251
+ distinctEnabled ? generateDistinctEnum(table, typeName) : void 0,
4252
+ policies?.softDelete,
4253
+ tableName
4150
4254
  );
4151
4255
  return {
4152
4256
  name: fieldName,
@@ -4188,7 +4292,7 @@ var generateSelectSingle = (db, tableName, tables, relationMap, orderArgs, filte
4188
4292
  `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`
4189
4293
  );
4190
4294
  }
4191
- const queryArgs = selectSingleArgs(orderArgs, filterArgs);
4295
+ const queryArgs = selectSingleArgs(orderArgs, filterArgs, policies?.softDelete, tableName);
4192
4296
  const table = tables[tableName];
4193
4297
  const pkNames = mysqlPrimaryKeyPropNames(table);
4194
4298
  return {
@@ -4420,7 +4524,8 @@ var generateUpdateMany = (db, tableName, table, updateManyInput, fieldName, filt
4420
4524
  args: queryArgs
4421
4525
  };
4422
4526
  };
4423
- var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requireWhere, filterCtx, txCtx, policies) => {
4527
+ var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requireWhere, filterCtx, txCtx, policies, restore = false) => {
4528
+ const softDelete = policies?.softDelete?.(tableName);
4424
4529
  const queryArgs = {
4425
4530
  where: {
4426
4531
  type: single || requireWhere ? new import_graphql7.GraphQLNonNull(filterArgs) : filterArgs
@@ -4438,12 +4543,13 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requi
4438
4543
  scope,
4439
4544
  tableName,
4440
4545
  table,
4441
- single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0
4546
+ single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0,
4547
+ restore ? "ONLY" : void 0
4442
4548
  );
4443
4549
  if (single) {
4444
4550
  await assertSingleMatch(executor, table, filters, fieldName);
4445
4551
  }
4446
- let query = executor.delete(table);
4552
+ let query = softDelete ? executor.update(table).set({ [softDelete.columnName]: restore ? softDelete.writeRestored : softDelete.writeDeleted() }) : executor.delete(table);
4447
4553
  if (filters) {
4448
4554
  query = query.where(filters);
4449
4555
  }
@@ -4487,16 +4593,17 @@ var generateSchemaData = (db, schema, relations, options) => {
4487
4593
  attachTargetPrimaryKeys(namedRelations, tables, mysqlPrimaryKeyPropNames);
4488
4594
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
4489
4595
  const filterCtx = { tables, relationMap: namedRelations };
4490
- const scopes = options.policies?.scope;
4491
- const contextValuesOf = options.policies?.contextValues;
4492
- const policies = bindPolicies(options.policies, filterCtx);
4596
+ const tablePolicies = options.policies;
4597
+ const contextValuesOf = tablePolicies?.contextValues;
4598
+ const softDeleteOf = tablePolicies?.softDelete;
4599
+ const policies = bindPolicies(tablePolicies, filterCtx);
4493
4600
  const resolverFactory = createRelationResolverFactory(
4494
4601
  db,
4495
4602
  tables,
4496
4603
  "nulls-smallest",
4497
4604
  filterCtx,
4498
4605
  limits,
4499
- scopes
4606
+ tablePolicies
4500
4607
  );
4501
4608
  const cacheCtx = {
4502
4609
  genericFilterCache: /* @__PURE__ */ new Map(),
@@ -4515,9 +4622,10 @@ var generateSchemaData = (db, schema, relations, options) => {
4515
4622
  docs: options.docs ?? {},
4516
4623
  primaryKeyOf: (name) => tables[name] ? mysqlPrimaryKeyPropNames(tables[name]) : [],
4517
4624
  contextValuesOf,
4625
+ softDeleteOf,
4518
4626
  featureOf
4519
4627
  };
4520
- const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, scopes) : void 0;
4628
+ const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, tablePolicies) : void 0;
4521
4629
  const queries = {};
4522
4630
  const mutations = {};
4523
4631
  const mutationTxCtx = createMutationTxCtx(options.transactions);
@@ -4573,8 +4681,11 @@ var generateSchemaData = (db, schema, relations, options) => {
4573
4681
  updateCountFieldName,
4574
4682
  deleteFieldName,
4575
4683
  deleteSingleFieldName,
4684
+ restoreFieldName,
4685
+ restoreSingleFieldName,
4576
4686
  deleteCountFieldName
4577
4687
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
4688
+ const softDeleteInfo = softDeleteOf?.(tableName);
4578
4689
  const selectArrGenerated = generateSelectArray(
4579
4690
  db,
4580
4691
  tableName,
@@ -4712,6 +4823,32 @@ var generateSchemaData = (db, schema, relations, options) => {
4712
4823
  mutationTxCtx,
4713
4824
  policies
4714
4825
  ) : void 0;
4826
+ const restoreGenerated = softDeleteInfo ? generateDelete(
4827
+ db,
4828
+ tableName,
4829
+ schema[tableName],
4830
+ tableFilters,
4831
+ restoreFieldName,
4832
+ false,
4833
+ tableFeatures.requireWhere,
4834
+ filterCtx,
4835
+ mutationTxCtx,
4836
+ policies,
4837
+ true
4838
+ ) : void 0;
4839
+ const restoreSingleGenerated = softDeleteInfo ? generateDelete(
4840
+ db,
4841
+ tableName,
4842
+ schema[tableName],
4843
+ tableFilters,
4844
+ restoreSingleFieldName,
4845
+ true,
4846
+ tableFeatures.requireWhere,
4847
+ filterCtx,
4848
+ mutationTxCtx,
4849
+ policies,
4850
+ true
4851
+ ) : void 0;
4715
4852
  const updateCountGenerated = tableFeatures.update && tableFeatures.countMutations ? generateWriteCount({
4716
4853
  db,
4717
4854
  tableName,
@@ -4744,7 +4881,7 @@ var generateSchemaData = (db, schema, relations, options) => {
4744
4881
  aggregateFieldName,
4745
4882
  tableFilters,
4746
4883
  filterCtx,
4747
- scopes
4884
+ tablePolicies
4748
4885
  ) : void 0;
4749
4886
  const groupByType = tableFeatures.aggregates && tableFeatures.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
4750
4887
  const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
@@ -4759,7 +4896,7 @@ var generateSchemaData = (db, schema, relations, options) => {
4759
4896
  groupByEnum,
4760
4897
  havingInput,
4761
4898
  filterCtx,
4762
- scopes
4899
+ tablePolicies
4763
4900
  ) : void 0;
4764
4901
  queries[selectArrGenerated.name] = {
4765
4902
  type: selectArrOutput,
@@ -4809,7 +4946,9 @@ var generateSchemaData = (db, schema, relations, options) => {
4809
4946
  [updateManyGenerated, { operation: "updateMany", single: false, targetArg: "updates" }],
4810
4947
  [updateSingleGenerated, { operation: "update", single: true, targetArg: "where" }],
4811
4948
  [deleteGenerated, { operation: "delete", single: false, targetArg: "where" }],
4812
- [deleteSingleGenerated, { operation: "delete", single: true, targetArg: "where" }]
4949
+ [deleteSingleGenerated, { operation: "delete", single: true, targetArg: "where" }],
4950
+ [restoreGenerated, { operation: "restore", single: false, targetArg: "where" }],
4951
+ [restoreSingleGenerated, { operation: "restore", single: true, targetArg: "where" }]
4813
4952
  ];
4814
4953
  for (const [generated, meta] of generatedMutations) {
4815
4954
  if (generated) {
@@ -5088,7 +5227,7 @@ var createNestedWriteTypes = (params) => {
5088
5227
  var mergedOps = (entries) => Object.assign({}, ...entries.map((entry) => entry.ops));
5089
5228
  var asArray = (value) => Array.isArray(value) ? value : value === void 0 ? [] : [value];
5090
5229
  var createNestedWriteRuntime = (params) => {
5091
- const { plans, filterCtx, scopes, contextValues } = params;
5230
+ const { plans, filterCtx, policies, contextValues } = params;
5092
5231
  const conditionOf = (plan, filter, operation, scope) => {
5093
5232
  const condition = extractFilters(
5094
5233
  plan.targetTable,
@@ -5151,7 +5290,7 @@ var createNestedWriteRuntime = (params) => {
5151
5290
  if (!tablePlans) {
5152
5291
  return patch;
5153
5292
  }
5154
- const scope = resolveScope(scopes, context, filterCtx);
5293
+ const scope = resolveScope(policies, context, filterCtx);
5155
5294
  for (const [relationName, op] of Object.entries(ops)) {
5156
5295
  const plan = tablePlans[relationName];
5157
5296
  if (!plan || plan.fkSide !== "parent") {
@@ -5191,7 +5330,7 @@ var createNestedWriteRuntime = (params) => {
5191
5330
  if (!tablePlans) {
5192
5331
  return;
5193
5332
  }
5194
- const scope = resolveScope(scopes, context, filterCtx);
5333
+ const scope = resolveScope(policies, context, filterCtx);
5195
5334
  for (const [relationName, op] of Object.entries(ops)) {
5196
5335
  const plan = tablePlans[relationName];
5197
5336
  if (!plan || plan.fkSide !== "child") {
@@ -5283,7 +5422,9 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
5283
5422
  const queryArgs = selectArrayArgs(
5284
5423
  orderArgs,
5285
5424
  filterArgs,
5286
- distinctEnabled ? generateDistinctEnum(table, typeName) : void 0
5425
+ distinctEnabled ? generateDistinctEnum(table, typeName) : void 0,
5426
+ policies?.softDelete,
5427
+ tableName
5287
5428
  );
5288
5429
  return {
5289
5430
  name: fieldName,
@@ -5315,7 +5456,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
5315
5456
  nullOrdering: "nulls-largest"
5316
5457
  });
5317
5458
  }
5318
- const { offset, orderBy, where, distinct, after } = args;
5459
+ const { offset, orderBy, where, distinct, after, deleted } = args;
5319
5460
  const selectedColumnsSql = extractSelectedColumnsFromTreeSQLFormat(
5320
5461
  parsedInfo.fieldsByTypeName[typeName],
5321
5462
  table,
@@ -5353,7 +5494,8 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
5353
5494
  scope,
5354
5495
  tableName,
5355
5496
  table,
5356
- where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
5497
+ where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0,
5498
+ deleted
5357
5499
  );
5358
5500
  const whereSql = cursorCondition ? (0, import_drizzle_orm8.and)(baseWhereSql, cursorCondition) : baseWhereSql;
5359
5501
  let distinctKeys;
@@ -5411,7 +5553,7 @@ var generateSelectArray2 = (db, tableName, tables, relationMap, orderArgs, filte
5411
5553
  };
5412
5554
  var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, limits, policies) => {
5413
5555
  const queryBase = db.query[tableName];
5414
- const queryArgs = selectSingleArgs(orderArgs, filterArgs);
5556
+ const queryArgs = selectSingleArgs(orderArgs, filterArgs, policies?.softDelete, tableName);
5415
5557
  const table = tables[tableName];
5416
5558
  const pkNames = pgPrimaryKeyPropNames(table);
5417
5559
  return {
@@ -5440,7 +5582,7 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
5440
5582
  scope
5441
5583
  });
5442
5584
  }
5443
- const { offset, orderBy, where } = args;
5585
+ const { offset, orderBy, where, deleted } = args;
5444
5586
  const selectedColumnsSql = extractSelectedColumnsFromTreeSQLFormat(
5445
5587
  parsedInfo.fieldsByTypeName[typeName],
5446
5588
  table,
@@ -5451,7 +5593,8 @@ var generateSelectSingle2 = (db, tableName, tables, relationMap, orderArgs, filt
5451
5593
  scope,
5452
5594
  tableName,
5453
5595
  table,
5454
- where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
5596
+ where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0,
5597
+ deleted
5455
5598
  );
5456
5599
  if (whereSql) {
5457
5600
  q = q.where(whereSql);
@@ -5879,7 +6022,8 @@ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateMany
5879
6022
  args: queryArgs
5880
6023
  };
5881
6024
  };
5882
- var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx, policies) => {
6025
+ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx, policies, restore = false) => {
6026
+ const softDelete = policies?.softDelete?.(tableName);
5883
6027
  const queryArgs = {
5884
6028
  where: {
5885
6029
  type: single || requireWhere ? new import_graphql9.GraphQLNonNull(filterArgs) : filterArgs
@@ -5905,12 +6049,13 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, si
5905
6049
  scope,
5906
6050
  tableName,
5907
6051
  table,
5908
- single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0
6052
+ single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0,
6053
+ restore ? "ONLY" : void 0
5909
6054
  );
5910
6055
  if (single) {
5911
6056
  await assertSingleMatch(executor, table, filters, fieldName);
5912
6057
  }
5913
- let query = executor.delete(table);
6058
+ let query = softDelete ? executor.update(table).set({ [softDelete.columnName]: restore ? softDelete.writeRestored : softDelete.writeDeleted() }) : executor.delete(table);
5914
6059
  if (filters) {
5915
6060
  query = query.where(filters);
5916
6061
  }
@@ -5964,16 +6109,17 @@ function generateSchemaData2(db, schema, relations, options) {
5964
6109
  attachTargetPrimaryKeys(namedRelations, tables, pgPrimaryKeyPropNames);
5965
6110
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
5966
6111
  const filterCtx = { tables, relationMap: namedRelations };
5967
- const scopes = options.policies?.scope;
5968
- const contextValuesOf = options.policies?.contextValues;
5969
- const policies = bindPolicies(options.policies, filterCtx);
6112
+ const tablePolicies = options.policies;
6113
+ const contextValuesOf = tablePolicies?.contextValues;
6114
+ const softDeleteOf = tablePolicies?.softDelete;
6115
+ const policies = bindPolicies(tablePolicies, filterCtx);
5970
6116
  const resolverFactory = createRelationResolverFactory(
5971
6117
  db,
5972
6118
  tables,
5973
6119
  "nulls-largest",
5974
6120
  filterCtx,
5975
6121
  limits,
5976
- scopes
6122
+ tablePolicies
5977
6123
  );
5978
6124
  const cacheCtx = {
5979
6125
  genericFilterCache: /* @__PURE__ */ new Map(),
@@ -5992,6 +6138,7 @@ function generateSchemaData2(db, schema, relations, options) {
5992
6138
  docs: options.docs ?? {},
5993
6139
  primaryKeyOf: (name) => tables[name] ? pgPrimaryKeyPropNames(tables[name]) : [],
5994
6140
  contextValuesOf,
6141
+ softDeleteOf,
5995
6142
  featureOf
5996
6143
  };
5997
6144
  const nestedPlans = features.nestedWrites ? buildNestedWritePlans(
@@ -6002,8 +6149,13 @@ function generateSchemaData2(db, schema, relations, options) {
6002
6149
  extractRelationJoinColumns
6003
6150
  ) : void 0;
6004
6151
  const nestedTypes = nestedPlans ? createNestedWriteTypes({ plans: nestedPlans, cacheCtx, typeNameMapper, insertPrefix: prefixes.insert }) : void 0;
6005
- const nestedRuntime = nestedPlans ? createNestedWriteRuntime({ plans: nestedPlans, filterCtx, scopes, contextValues: contextValuesOf }) : void 0;
6006
- const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, scopes) : void 0;
6152
+ const nestedRuntime = nestedPlans ? createNestedWriteRuntime({
6153
+ plans: nestedPlans,
6154
+ filterCtx,
6155
+ policies: tablePolicies,
6156
+ contextValues: contextValuesOf
6157
+ }) : void 0;
6158
+ const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, tablePolicies) : void 0;
6007
6159
  const queries = {};
6008
6160
  const mutations = {};
6009
6161
  const mutationTxCtx = createMutationTxCtx(options.transactions);
@@ -6049,8 +6201,11 @@ function generateSchemaData2(db, schema, relations, options) {
6049
6201
  updateCountFieldName,
6050
6202
  deleteFieldName,
6051
6203
  deleteSingleFieldName,
6204
+ restoreFieldName,
6205
+ restoreSingleFieldName,
6052
6206
  deleteCountFieldName
6053
6207
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
6208
+ const softDeleteInfo = softDeleteOf?.(tableName);
6054
6209
  const selectArrGenerated = generateSelectArray2(
6055
6210
  db,
6056
6211
  tableName,
@@ -6241,6 +6396,36 @@ function generateSchemaData2(db, schema, relations, options) {
6241
6396
  mutationTxCtx,
6242
6397
  policies
6243
6398
  ) : void 0;
6399
+ const restoreGenerated = softDeleteInfo ? generateDelete2(
6400
+ db,
6401
+ tableName,
6402
+ schema[tableName],
6403
+ tableFilters,
6404
+ restoreFieldName,
6405
+ typeName,
6406
+ false,
6407
+ tableFeatures.requireWhere,
6408
+ filterCtx,
6409
+ { tableName, relationMap: namedRelations, tables },
6410
+ mutationTxCtx,
6411
+ policies,
6412
+ true
6413
+ ) : void 0;
6414
+ const restoreSingleGenerated = softDeleteInfo ? generateDelete2(
6415
+ db,
6416
+ tableName,
6417
+ schema[tableName],
6418
+ tableFilters,
6419
+ restoreSingleFieldName,
6420
+ typeName,
6421
+ true,
6422
+ tableFeatures.requireWhere,
6423
+ filterCtx,
6424
+ { tableName, relationMap: namedRelations, tables },
6425
+ mutationTxCtx,
6426
+ policies,
6427
+ true
6428
+ ) : void 0;
6244
6429
  const updateCountGenerated = tableFeatures.update && tableFeatures.countMutations ? generateWriteCount({
6245
6430
  db,
6246
6431
  tableName,
@@ -6274,7 +6459,7 @@ function generateSchemaData2(db, schema, relations, options) {
6274
6459
  aggregateFieldName,
6275
6460
  tableFilters,
6276
6461
  filterCtx,
6277
- scopes
6462
+ tablePolicies
6278
6463
  ) : void 0;
6279
6464
  const groupByType = tableFeatures.aggregates && tableFeatures.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
6280
6465
  const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
@@ -6289,7 +6474,7 @@ function generateSchemaData2(db, schema, relations, options) {
6289
6474
  groupByEnum,
6290
6475
  havingInput,
6291
6476
  filterCtx,
6292
- scopes
6477
+ tablePolicies
6293
6478
  ) : void 0;
6294
6479
  queries[selectArrGenerated.name] = {
6295
6480
  type: selectArrOutput,
@@ -6426,6 +6611,26 @@ function generateSchemaData2(db, schema, relations, options) {
6426
6611
  }
6427
6612
  };
6428
6613
  }
6614
+ if (restoreGenerated) {
6615
+ mutations[restoreGenerated.name] = {
6616
+ type: arrTableItemOutput,
6617
+ args: restoreGenerated.args,
6618
+ resolve: restoreGenerated.resolver,
6619
+ extensions: {
6620
+ drizzle: drizzleMeta({ kind: "mutation", operation: "restore", single: false, targetArg: "where" })
6621
+ }
6622
+ };
6623
+ }
6624
+ if (restoreSingleGenerated) {
6625
+ mutations[restoreSingleGenerated.name] = {
6626
+ type: singleTableItemOutput,
6627
+ args: restoreSingleGenerated.args,
6628
+ resolve: restoreSingleGenerated.resolver,
6629
+ extensions: {
6630
+ drizzle: drizzleMeta({ kind: "mutation", operation: "restore", single: true, targetArg: "where" })
6631
+ }
6632
+ };
6633
+ }
6429
6634
  if (updateCountGenerated) {
6430
6635
  mutations[updateCountGenerated.name] = {
6431
6636
  type: new import_graphql9.GraphQLNonNull(import_graphql9.GraphQLInt),
@@ -6504,7 +6709,9 @@ var generateSelectArray3 = (db, tableName, tables, relationMap, orderArgs, filte
6504
6709
  const queryArgs = selectArrayArgs(
6505
6710
  orderArgs,
6506
6711
  filterArgs,
6507
- distinctEnabled ? generateDistinctEnum(table, typeName) : void 0
6712
+ distinctEnabled ? generateDistinctEnum(table, typeName) : void 0,
6713
+ policies?.softDelete,
6714
+ tableName
6508
6715
  );
6509
6716
  return {
6510
6717
  name: fieldName,
@@ -6546,7 +6753,7 @@ var generateSelectSingle3 = (db, tableName, tables, relationMap, orderArgs, filt
6546
6753
  `Drizzle-GraphQL Error: Table ${tableName} not found in drizzle instance. Did you forget to pass schema to drizzle constructor?`
6547
6754
  );
6548
6755
  }
6549
- const queryArgs = selectSingleArgs(orderArgs, filterArgs);
6756
+ const queryArgs = selectSingleArgs(orderArgs, filterArgs, policies?.softDelete, tableName);
6550
6757
  const table = tables[tableName];
6551
6758
  const pkNames = sqlitePrimaryKeyPropNames(table);
6552
6759
  return {
@@ -7012,7 +7219,8 @@ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateMany
7012
7219
  args: queryArgs
7013
7220
  };
7014
7221
  };
7015
- var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx, policies) => {
7222
+ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx, txCtx, policies, restore = false) => {
7223
+ const softDelete = policies?.softDelete?.(tableName);
7016
7224
  const queryArgs = {
7017
7225
  where: {
7018
7226
  type: single || requireWhere ? new import_graphql10.GraphQLNonNull(filterArgs) : filterArgs
@@ -7038,12 +7246,13 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, si
7038
7246
  scope,
7039
7247
  tableName,
7040
7248
  table,
7041
- single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0
7249
+ single || requireWhere ? extractRequiredFilters(table, tableName, where, fieldName, relationCtx) : where ? extractFilters(table, tableName, where, relationCtx) : void 0,
7250
+ restore ? "ONLY" : void 0
7042
7251
  );
7043
7252
  if (single) {
7044
7253
  await assertSingleMatch(executor, table, filters, fieldName);
7045
7254
  }
7046
- let query = executor.delete(table);
7255
+ let query = softDelete ? executor.update(table).set({ [softDelete.columnName]: restore ? softDelete.writeRestored : softDelete.writeDeleted() }) : executor.delete(table);
7047
7256
  if (filters) {
7048
7257
  query = query.where(filters);
7049
7258
  }
@@ -7098,16 +7307,17 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7098
7307
  attachTargetPrimaryKeys(namedRelations, tables, sqlitePrimaryKeyPropNames);
7099
7308
  const eagerRelations = pruneNonEagerRelations(namedRelations, shouldEagerLoad);
7100
7309
  const filterCtx = { tables, relationMap: namedRelations };
7101
- const scopes = options.policies?.scope;
7102
- const contextValuesOf = options.policies?.contextValues;
7103
- const policies = bindPolicies(options.policies, filterCtx);
7310
+ const tablePolicies = options.policies;
7311
+ const contextValuesOf = tablePolicies?.contextValues;
7312
+ const softDeleteOf = tablePolicies?.softDelete;
7313
+ const policies = bindPolicies(tablePolicies, filterCtx);
7104
7314
  const resolverFactory = createRelationResolverFactory(
7105
7315
  db,
7106
7316
  tables,
7107
7317
  "nulls-smallest",
7108
7318
  filterCtx,
7109
7319
  limits,
7110
- scopes
7320
+ tablePolicies
7111
7321
  );
7112
7322
  const cacheCtx = {
7113
7323
  genericFilterCache: /* @__PURE__ */ new Map(),
@@ -7126,6 +7336,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7126
7336
  docs: options.docs ?? {},
7127
7337
  primaryKeyOf: (name) => tables[name] ? sqlitePrimaryKeyPropNames(tables[name]) : [],
7128
7338
  contextValuesOf,
7339
+ softDeleteOf,
7129
7340
  featureOf
7130
7341
  };
7131
7342
  if (features.nestedWrites && db.resultKind === "sync") {
@@ -7141,8 +7352,13 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7141
7352
  extractRelationJoinColumns
7142
7353
  ) : void 0;
7143
7354
  const nestedTypes = nestedPlans ? createNestedWriteTypes({ plans: nestedPlans, cacheCtx, typeNameMapper, insertPrefix: prefixes.insert }) : void 0;
7144
- const nestedRuntime = nestedPlans ? createNestedWriteRuntime({ plans: nestedPlans, filterCtx, scopes, contextValues: contextValuesOf }) : void 0;
7145
- const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, scopes) : void 0;
7355
+ const nestedRuntime = nestedPlans ? createNestedWriteRuntime({
7356
+ plans: nestedPlans,
7357
+ filterCtx,
7358
+ policies: tablePolicies,
7359
+ contextValues: contextValuesOf
7360
+ }) : void 0;
7361
+ const relationAggregateFactory = anyTable("relationAggregates") ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx, tablePolicies) : void 0;
7146
7362
  const queries = {};
7147
7363
  const mutations = {};
7148
7364
  if (options.transactions && db.resultKind === "sync") {
@@ -7193,8 +7409,11 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7193
7409
  updateCountFieldName,
7194
7410
  deleteFieldName,
7195
7411
  deleteSingleFieldName,
7412
+ restoreFieldName,
7413
+ restoreSingleFieldName,
7196
7414
  deleteCountFieldName
7197
7415
  } = computeResolverFieldNames(tableName, typeNameMapper, prefixes, suffixes);
7416
+ const softDeleteInfo = softDeleteOf?.(tableName);
7198
7417
  const selectArrGenerated = generateSelectArray3(
7199
7418
  db,
7200
7419
  tableName,
@@ -7385,6 +7604,36 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7385
7604
  mutationTxCtx,
7386
7605
  policies
7387
7606
  ) : void 0;
7607
+ const restoreGenerated = softDeleteInfo ? generateDelete3(
7608
+ db,
7609
+ tableName,
7610
+ schema[tableName],
7611
+ tableFilters,
7612
+ restoreFieldName,
7613
+ typeName,
7614
+ false,
7615
+ tableFeatures.requireWhere,
7616
+ filterCtx,
7617
+ { tableName, relationMap: namedRelations, tables },
7618
+ mutationTxCtx,
7619
+ policies,
7620
+ true
7621
+ ) : void 0;
7622
+ const restoreSingleGenerated = softDeleteInfo ? generateDelete3(
7623
+ db,
7624
+ tableName,
7625
+ schema[tableName],
7626
+ tableFilters,
7627
+ restoreSingleFieldName,
7628
+ typeName,
7629
+ true,
7630
+ tableFeatures.requireWhere,
7631
+ filterCtx,
7632
+ { tableName, relationMap: namedRelations, tables },
7633
+ mutationTxCtx,
7634
+ policies,
7635
+ true
7636
+ ) : void 0;
7388
7637
  const updateCountGenerated = tableFeatures.update && tableFeatures.countMutations ? generateWriteCount({
7389
7638
  db,
7390
7639
  tableName,
@@ -7418,7 +7667,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7418
7667
  aggregateFieldName,
7419
7668
  tableFilters,
7420
7669
  filterCtx,
7421
- scopes
7670
+ tablePolicies
7422
7671
  ) : void 0;
7423
7672
  const groupByType = tableFeatures.aggregates && tableFeatures.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
7424
7673
  const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
@@ -7433,7 +7682,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7433
7682
  groupByEnum,
7434
7683
  havingInput,
7435
7684
  filterCtx,
7436
- scopes
7685
+ tablePolicies
7437
7686
  ) : void 0;
7438
7687
  queries[selectArrGenerated.name] = {
7439
7688
  type: selectArrOutput,
@@ -7570,6 +7819,26 @@ var generateSchemaData3 = (db, schema, relations, options) => {
7570
7819
  }
7571
7820
  };
7572
7821
  }
7822
+ if (restoreGenerated) {
7823
+ mutations[restoreGenerated.name] = {
7824
+ type: arrTableItemOutput,
7825
+ args: restoreGenerated.args,
7826
+ resolve: restoreGenerated.resolver,
7827
+ extensions: {
7828
+ drizzle: drizzleMeta({ kind: "mutation", operation: "restore", single: false, targetArg: "where" })
7829
+ }
7830
+ };
7831
+ }
7832
+ if (restoreSingleGenerated) {
7833
+ mutations[restoreSingleGenerated.name] = {
7834
+ type: singleTableItemOutput,
7835
+ args: restoreSingleGenerated.args,
7836
+ resolve: restoreSingleGenerated.resolver,
7837
+ extensions: {
7838
+ drizzle: drizzleMeta({ kind: "mutation", operation: "restore", single: true, targetArg: "where" })
7839
+ }
7840
+ };
7841
+ }
7573
7842
  if (updateCountGenerated) {
7574
7843
  mutations[updateCountGenerated.name] = {
7575
7844
  type: new import_graphql10.GraphQLNonNull(import_graphql10.GraphQLInt),
@@ -7780,7 +8049,8 @@ var buildSchema = (db, config) => {
7780
8049
  insert: config?.prefixes?.insert ?? "create",
7781
8050
  delete: config?.prefixes?.delete ?? "delete",
7782
8051
  update: config?.prefixes?.update ?? "update",
7783
- upsert: config?.prefixes?.upsert ?? "upsert"
8052
+ upsert: config?.prefixes?.upsert ?? "upsert",
8053
+ restore: config?.prefixes?.restore ?? "restore"
7784
8054
  };
7785
8055
  const suffixes = {
7786
8056
  list: config?.suffixes?.list ?? "",
@@ -7858,9 +8128,32 @@ var buildSchema = (db, config) => {
7858
8128
  }
7859
8129
  }
7860
8130
  }
7861
- const policies = scopeConfig || contextValuesConfig ? {
8131
+ const softDeleteConfig = config?.softDelete;
8132
+ const softDeleteInfos = /* @__PURE__ */ new Map();
8133
+ if (softDeleteConfig) {
8134
+ if (typeof softDeleteConfig === "function") {
8135
+ for (const tableName of tableKeys) {
8136
+ const declaration = softDeleteConfig(schema[tableName], tableName);
8137
+ if (declaration) {
8138
+ softDeleteInfos.set(tableName, resolveSoftDeleteInfo(schema[tableName], tableName, declaration));
8139
+ }
8140
+ }
8141
+ } else {
8142
+ const tableNames = new Set(tableKeys);
8143
+ for (const [tableName, declaration] of Object.entries(softDeleteConfig)) {
8144
+ if (!tableNames.has(tableName)) {
8145
+ throw new Error(
8146
+ `Drizzle-GraphQL Error: config.softDelete names '${tableName}', which is not a table in the Drizzle schema.`
8147
+ );
8148
+ }
8149
+ softDeleteInfos.set(tableName, resolveSoftDeleteInfo(schema[tableName], tableName, declaration));
8150
+ }
8151
+ }
8152
+ }
8153
+ const policies = scopeConfig || contextValuesConfig || softDeleteInfos.size ? {
7862
8154
  scope: scopeConfig ? (tableName) => scopeConfig[tableName] : void 0,
7863
- contextValues: contextValuesConfig ? (tableName) => contextValuesConfig[tableName] : void 0
8155
+ contextValues: contextValuesConfig ? (tableName) => contextValuesConfig[tableName] : void 0,
8156
+ softDelete: softDeleteInfos.size ? (tableName) => softDeleteInfos.get(tableName) : void 0
7864
8157
  } : void 0;
7865
8158
  const exclude = config?.exclude;
7866
8159
  if (exclude) {