@vantreeseba/drizzle-graphql 13.1.0 → 13.1.1

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.d.cts CHANGED
@@ -337,6 +337,13 @@ type DrizzleFieldExtension = {
337
337
  * Absent everywhere else, so a wrapper can gate purging without parsing arguments.
338
338
  */
339
339
  hardDelete?: boolean;
340
+ /**
341
+ * `true` on the count mutations (`update<Table>Count` / `delete<Table>Count`,
342
+ * `features.countMutations`): the field writes like its plural `update` / `delete` sibling
343
+ * — same `operation`, same rows — but resolves to how many rows it wrote (`Int!`) rather
344
+ * than to the rows. Absent everywhere else.
345
+ */
346
+ count?: boolean;
340
347
  /** For `kind: 'relation'` and `operation: 'relationAggregate'`: the relation's name. */
341
348
  relation?: string;
342
349
  /** For `kind: 'relation'` and `operation: 'relationAggregate'`: the table it hangs off. */
@@ -822,7 +829,8 @@ type WriteHookPayload = {
822
829
  *
823
830
  * Each row holds the columns the client's selection asked for (plus any key a relation or
824
831
  * nested write needed), **and** every column the hook names in `columns`. A column the
825
- * client did not select and the hook did not name is absent.
832
+ * client did not select and the hook did not name is absent. The count mutations select
833
+ * nothing, so there a row holds the named columns, or the primary key when none are named.
826
834
  */
827
835
  rows: any[];
828
836
  context: any;
@@ -1499,6 +1507,17 @@ type SchemaFeatures = {
1499
1507
  * for nothing. Each mutation is generated only when its plural counterpart is
1500
1508
  * (`features.update` / `features.delete`), and honours `features.requireWhere`.
1501
1509
  *
1510
+ * Apart from the answer, they obey every rule the plural write does: the table's `scope`
1511
+ * is ANDed into the `where`; on a `softDelete` table the delete marks rows instead of
1512
+ * removing them (taking `hard` where the plural delete does) and neither mutation reaches
1513
+ * an already-marked row; `contextValues` columns are never reassigned by the update; and
1514
+ * `onWrite` hooks run `before` and `after`, in a transaction, with the plural payload
1515
+ * (`single: false`). An `after` hook needs rows, so on a table with one the write adds a
1516
+ * `RETURNING` of the hook's `columns` — or of the primary key if it names none (every column
1517
+ * on a table without one) — and the count is the number of rows returned. On MySQL, which has
1518
+ * no `RETURNING`, the hook gets `rows: []` as on every MySQL mutation. Their
1519
+ * `extensions.drizzle` carries the plural write's `operation` plus `count: true`.
1520
+ *
1502
1521
  * Off unless asked for, so an existing schema does not grow new mutations on upgrade.
1503
1522
  *
1504
1523
  * @default false
package/dist/index.d.ts CHANGED
@@ -337,6 +337,13 @@ type DrizzleFieldExtension = {
337
337
  * Absent everywhere else, so a wrapper can gate purging without parsing arguments.
338
338
  */
339
339
  hardDelete?: boolean;
340
+ /**
341
+ * `true` on the count mutations (`update<Table>Count` / `delete<Table>Count`,
342
+ * `features.countMutations`): the field writes like its plural `update` / `delete` sibling
343
+ * — same `operation`, same rows — but resolves to how many rows it wrote (`Int!`) rather
344
+ * than to the rows. Absent everywhere else.
345
+ */
346
+ count?: boolean;
340
347
  /** For `kind: 'relation'` and `operation: 'relationAggregate'`: the relation's name. */
341
348
  relation?: string;
342
349
  /** For `kind: 'relation'` and `operation: 'relationAggregate'`: the table it hangs off. */
@@ -822,7 +829,8 @@ type WriteHookPayload = {
822
829
  *
823
830
  * Each row holds the columns the client's selection asked for (plus any key a relation or
824
831
  * nested write needed), **and** every column the hook names in `columns`. A column the
825
- * client did not select and the hook did not name is absent.
832
+ * client did not select and the hook did not name is absent. The count mutations select
833
+ * nothing, so there a row holds the named columns, or the primary key when none are named.
826
834
  */
827
835
  rows: any[];
828
836
  context: any;
@@ -1499,6 +1507,17 @@ type SchemaFeatures = {
1499
1507
  * for nothing. Each mutation is generated only when its plural counterpart is
1500
1508
  * (`features.update` / `features.delete`), and honours `features.requireWhere`.
1501
1509
  *
1510
+ * Apart from the answer, they obey every rule the plural write does: the table's `scope`
1511
+ * is ANDed into the `where`; on a `softDelete` table the delete marks rows instead of
1512
+ * removing them (taking `hard` where the plural delete does) and neither mutation reaches
1513
+ * an already-marked row; `contextValues` columns are never reassigned by the update; and
1514
+ * `onWrite` hooks run `before` and `after`, in a transaction, with the plural payload
1515
+ * (`single: false`). An `after` hook needs rows, so on a table with one the write adds a
1516
+ * `RETURNING` of the hook's `columns` — or of the primary key if it names none (every column
1517
+ * on a table without one) — and the count is the number of rows returned. On MySQL, which has
1518
+ * no `RETURNING`, the hook gets `rows: []` as on every MySQL mutation. Their
1519
+ * `extensions.drizzle` carries the plural write's `operation` plus `count: true`.
1520
+ *
1502
1521
  * Off unless asked for, so an existing schema does not grow new mutations on upgrade.
1503
1522
  *
1504
1523
  * @default false
package/dist/index.js CHANGED
@@ -3724,6 +3724,145 @@ const runMutation = async (db, context, info, txCtx, body, forceTx) => {
3724
3724
  return runOnSharedTx(state, body);
3725
3725
  };
3726
3726
  //#endregion
3727
+ //#region src/util/builders/common/write-hooks.ts
3728
+ /**
3729
+ * Normalizes the two registration shapes: a bare function is the `after` hook — the position
3730
+ * that has rows, and the one the common audit/outbox case wants — while `{ before, after }`
3731
+ * names them explicitly.
3732
+ */
3733
+ const normalizeWriteHooks = (hooks, tableColumns, where) => {
3734
+ if (!hooks) return;
3735
+ if (typeof hooks === "function") return { after: hooks };
3736
+ const resolved = {
3737
+ before: hooks.before,
3738
+ after: hooks.after
3739
+ };
3740
+ if (hooks.columns !== void 0) resolved.columns = resolveHookColumns(hooks.columns, !!hooks.after, tableColumns, where);
3741
+ return resolved.before || resolved.after ? resolved : void 0;
3742
+ };
3743
+ /**
3744
+ * Resolves a hook's `columns` against the table it runs on. `where` names the registration
3745
+ * (`config.onWrite.posts`) and, for a top-level one, the table, so the error says which.
3746
+ */
3747
+ const resolveHookColumns = (spec, hasAfter, tableColumns, where) => {
3748
+ if (!hasAfter) throw new Error(`Drizzle-GraphQL Error: ${where}.columns only applies to an 'after' hook, and none is registered.`);
3749
+ if (spec === "all") return { ...tableColumns };
3750
+ if (!Array.isArray(spec)) throw new Error(`Drizzle-GraphQL Error: ${where}.columns must be an array of column names or 'all'.`);
3751
+ const resolved = {};
3752
+ for (const name of spec) {
3753
+ const column = typeof name === "string" && Object.keys(tableColumns).includes(name) ? tableColumns[name] : void 0;
3754
+ if (!column) throw new Error(`Drizzle-GraphQL Error: ${where}.columns names '${String(name)}', which is not a column of that table.`);
3755
+ resolved[name] = column;
3756
+ }
3757
+ return resolved;
3758
+ };
3759
+ /**
3760
+ * Adds a hook's `columns` to a RETURNING column map, and reports which keys it added — the
3761
+ * ones the client never asked for, which have to come back off before the rows are mapped.
3762
+ * Returns the map untouched, and no keys, when the hook named none or the selection already
3763
+ * covers them.
3764
+ */
3765
+ const withHookColumns = (hooks, columns) => {
3766
+ const hookColumns = hooks?.columns;
3767
+ if (!hookColumns) return {
3768
+ returning: columns,
3769
+ added: void 0
3770
+ };
3771
+ const selected = new Set(Object.keys(columns));
3772
+ const added = Object.keys(hookColumns).filter((key) => !selected.has(key));
3773
+ if (!added.length) return {
3774
+ returning: columns,
3775
+ added: void 0
3776
+ };
3777
+ const returning = { ...columns };
3778
+ for (const key of added) returning[key] = hookColumns[key];
3779
+ return {
3780
+ returning,
3781
+ added
3782
+ };
3783
+ };
3784
+ /**
3785
+ * The rows with the hook-only keys taken off, as fresh objects: the hook was handed the
3786
+ * originals and may still hold them, so they are not mutated under it.
3787
+ */
3788
+ const omitHookColumns = (rows, added) => {
3789
+ if (!added) return rows;
3790
+ return rows.map((row) => {
3791
+ const copy = { ...row };
3792
+ for (const key of added) delete copy[key];
3793
+ return copy;
3794
+ });
3795
+ };
3796
+ /**
3797
+ * Invokes one position of a field's hooks. Returns `undefined` rather than a resolved promise
3798
+ * when nothing is registered, so the awaiting call site costs nothing on an unhooked build.
3799
+ */
3800
+ const runWriteHook = (hooks, position, payload) => {
3801
+ const hook = position === "before" ? hooks?.before : hooks?.after;
3802
+ if (!hook) return;
3803
+ return Promise.resolve(hook({
3804
+ ...payload,
3805
+ position,
3806
+ rows: payload.rows ?? []
3807
+ }));
3808
+ };
3809
+ //#endregion
3810
+ //#region src/util/builders/common/write-scaffold.ts
3811
+ /**
3812
+ * Wraps one mutation body in the scaffolding above and returns the field it becomes.
3813
+ *
3814
+ * A field carrying a hook is forced into a transaction even when it would have run straight
3815
+ * on `db`: a hook exists to write atomically with the mutation, and one that ran outside the
3816
+ * transaction could not roll anything back.
3817
+ */
3818
+ const writeResolver = ({ db, tableName, operation, single, fieldName, args: queryArgs, txCtx, policies, run }) => {
3819
+ const hooks = policies?.onWrite?.(tableName, operation);
3820
+ const errorCtx = {
3821
+ table: tableName,
3822
+ operation,
3823
+ field: fieldName
3824
+ };
3825
+ return {
3826
+ name: fieldName,
3827
+ resolver: async (_source, args, context, info) => {
3828
+ try {
3829
+ return await runMutation(db, context, info, txCtx, (executor) => {
3830
+ const payload = {
3831
+ table: tableName,
3832
+ operation,
3833
+ single,
3834
+ args,
3835
+ context,
3836
+ info,
3837
+ tx: executor
3838
+ };
3839
+ let added;
3840
+ return run({
3841
+ executor,
3842
+ args,
3843
+ context,
3844
+ info,
3845
+ before: () => runWriteHook(hooks, "before", payload),
3846
+ after: (rows) => runWriteHook(hooks, "after", {
3847
+ ...payload,
3848
+ rows: rows ?? []
3849
+ }),
3850
+ returning: (columns) => {
3851
+ const withHook = withHookColumns(hooks, columns);
3852
+ added = withHook.added;
3853
+ return withHook.returning;
3854
+ },
3855
+ output: (rows) => omitHookColumns(rows, added)
3856
+ });
3857
+ }, !!hooks);
3858
+ } catch (e) {
3859
+ throw withErrorContext(toGraphQLError(e), errorCtx);
3860
+ }
3861
+ },
3862
+ args: queryArgs
3863
+ };
3864
+ };
3865
+ //#endregion
3727
3866
  //#region src/util/builders/common/mutation-helpers.ts
3728
3867
  /**
3729
3868
  * The `hard` argument on the delete mutations of a soft-deleting table that opted into
@@ -3867,54 +4006,79 @@ const assertSingleMatch = async (executor, table, filters) => {
3867
4006
  * The plural `update` and `delete` always `RETURNING *`, which is the wrong shape for
3868
4007
  * "archive everything older than a year": the caller pays to ship rows it does not want, and
3869
4008
  * on a large match that cost is the whole mutation. These return `Int!` instead — how many
3870
- * rows the write touched, as the driver reported it, with no RETURNING clause at all.
4009
+ * rows the write touched.
3871
4010
  *
3872
- * Dialect-independent: drizzle's update/delete builders take the same calls everywhere, and
3873
- * the drivers' disagreement about how to spell the row count is handled by
3874
- * {@link rowsAffected}.
3875
- */
3876
- const generateWriteCount = ({ db, tableName, table, kind, setArgs, filterArgs, fieldName, requireWhere, filterCtx, txCtx, nested }) => {
4011
+ * Leaving the payload off changes nothing else: the write obeys every rule of the plural
4012
+ * mutation it mirrors, through the same {@link writeResolver} scaffolding.
4013
+ *
4014
+ * - `scope` (and the soft-delete marker) is ANDed into the `where`, so only rows the plural
4015
+ * write could reach are counted and written.
4016
+ * - On a soft-deleting table the delete is the marking `UPDATE`, not a `DELETE`, and rows that
4017
+ * are already marked are not matched; the update skips marked rows too. `hard: true` exists
4018
+ * exactly where the plural delete takes it.
4019
+ * - Context-derived columns are stripped from the update's `set`, as the plural update does.
4020
+ * - `onWrite` hooks run `before` and `after`, inside a transaction. The `after` hook is handed
4021
+ * rows, so a table with one pays for a `RETURNING` — of the columns the hook names in
4022
+ * `columns`, or of the primary key when it names none (the whole row on a table without a
4023
+ * key) — and the count is the number of rows returned. Every other write, and every write on
4024
+ * MySQL (no `RETURNING`; its hooks see `rows: []` as on every MySQL mutation), skips the
4025
+ * `RETURNING` and reads the count off the driver's result via {@link rowsAffected}.
4026
+ */
4027
+ const generateWriteCount = ({ db, tableName, table, kind, setArgs, filterArgs, fieldName, requireWhere, filterCtx, txCtx, nested, policies, pkNames = [], returnsRows }) => {
4028
+ const softDelete = kind === "delete" ? policies?.softDelete?.(tableName) : void 0;
4029
+ const canHardDelete = softDelete?.hardDelete === true;
3877
4030
  const queryArgs = {
3878
4031
  ...setArgs ? { set: { type: new GraphQLNonNull(setArgs) } } : {},
3879
- where: { type: requireWhere ? new GraphQLNonNull(filterArgs) : filterArgs }
4032
+ where: { type: requireWhere ? new GraphQLNonNull(filterArgs) : filterArgs },
4033
+ ...canHardDelete ? { hard: hardDeleteArg } : {}
3880
4034
  };
3881
- const errorCtx = {
3882
- table: tableName,
4035
+ const readsRows = returnsRows && !!policies?.onWrite?.(tableName, kind)?.after;
4036
+ const allColumns = getColumns(table);
4037
+ const keyColumns = pkNames.length ? Object.fromEntries(pkNames.map((name) => [name, allColumns[name]])) : allColumns;
4038
+ return writeResolver({
4039
+ db,
4040
+ tableName,
3883
4041
  operation: kind,
3884
- field: fieldName
3885
- };
3886
- return {
3887
- name: fieldName,
3888
- resolver: async (_source, args, context, info) => {
3889
- try {
3890
- return await runMutation(db, context, info, txCtx, async (executor) => {
3891
- const { where, set } = args;
3892
- const filters = scopedWhere({
3893
- scope: void 0,
3894
- tableName,
3895
- table,
3896
- where,
3897
- relationCtx: relationFilterCtx(filterCtx, tableName),
3898
- required: requireWhere
3899
- });
3900
- let query;
3901
- if (kind === "delete") query = executor.delete(table);
3902
- else {
3903
- const entry = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
3904
- if (entry && nested.hasOps(entry.ops)) throw drizzleError("This mutation does not support nested writes — use the one that returns the rows instead.", { code: "DRIZZLE_NESTED_WRITES_UNSUPPORTED" });
3905
- const values = remapUpdateInput(entry ? entry.columns : set, table, tableName);
3906
- if (!Object.keys(values).length) throw drizzleError("Unable to update with no values specified!", { code: "DRIZZLE_NO_VALUES" });
3907
- query = executor.update(table).set(values);
3908
- }
3909
- if (filters) query = query.where(filters);
3910
- return rowsAffected(await query);
3911
- });
3912
- } catch (e) {
3913
- throw withErrorContext(toGraphQLError(e), errorCtx);
4042
+ single: false,
4043
+ fieldName,
4044
+ txCtx,
4045
+ policies,
4046
+ args: queryArgs,
4047
+ run: async ({ executor, args, context, before, after, returning }) => {
4048
+ const { where, set } = args;
4049
+ const hard = canHardDelete && args.hard === true;
4050
+ const scope = policies?.scope?.(context);
4051
+ await before();
4052
+ let query;
4053
+ if (kind === "delete") query = softDelete && !hard ? executor.update(table).set({ [softDelete.columnName]: softDelete.writeDeleted() }) : executor.delete(table);
4054
+ else {
4055
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
4056
+ if (entry && nested.hasOps(entry.ops)) throw drizzleError("This mutation does not support nested writes — use the one that returns the rows instead.", { code: "DRIZZLE_NESTED_WRITES_UNSUPPORTED" });
4057
+ const values = stripContextValues(remapUpdateInput(entry ? entry.columns : set, table, tableName), policies?.contextValues?.(tableName));
4058
+ if (!Object.keys(values).length) throw drizzleError("Unable to update with no values specified!", { code: "DRIZZLE_NO_VALUES" });
4059
+ query = executor.update(table).set(values);
3914
4060
  }
3915
- },
3916
- args: queryArgs
3917
- };
4061
+ const filters = scopedWhere({
4062
+ scope,
4063
+ tableName,
4064
+ table,
4065
+ where,
4066
+ relationCtx: relationFilterCtx(filterCtx, tableName),
4067
+ required: requireWhere,
4068
+ deleted: hard ? "INCLUDE" : void 0
4069
+ });
4070
+ if (filters) query = query.where(filters);
4071
+ if (!readsRows) {
4072
+ const result = await query;
4073
+ await after();
4074
+ return rowsAffected(result);
4075
+ }
4076
+ const named = returning({});
4077
+ const rows = await query.returning(Object.keys(named).length ? named : keyColumns);
4078
+ await after(rows);
4079
+ return rows.length;
4080
+ }
4081
+ });
3918
4082
  };
3919
4083
  //#endregion
3920
4084
  //#region src/util/batch-loader/index.ts
@@ -4852,145 +5016,6 @@ const generateTableTypes = (tableName, tables, relationMap, withReturning, relat
4852
5016
  };
4853
5017
  };
4854
5018
  //#endregion
4855
- //#region src/util/builders/common/write-hooks.ts
4856
- /**
4857
- * Normalizes the two registration shapes: a bare function is the `after` hook — the position
4858
- * that has rows, and the one the common audit/outbox case wants — while `{ before, after }`
4859
- * names them explicitly.
4860
- */
4861
- const normalizeWriteHooks = (hooks, tableColumns, where) => {
4862
- if (!hooks) return;
4863
- if (typeof hooks === "function") return { after: hooks };
4864
- const resolved = {
4865
- before: hooks.before,
4866
- after: hooks.after
4867
- };
4868
- if (hooks.columns !== void 0) resolved.columns = resolveHookColumns(hooks.columns, !!hooks.after, tableColumns, where);
4869
- return resolved.before || resolved.after ? resolved : void 0;
4870
- };
4871
- /**
4872
- * Resolves a hook's `columns` against the table it runs on. `where` names the registration
4873
- * (`config.onWrite.posts`) and, for a top-level one, the table, so the error says which.
4874
- */
4875
- const resolveHookColumns = (spec, hasAfter, tableColumns, where) => {
4876
- if (!hasAfter) throw new Error(`Drizzle-GraphQL Error: ${where}.columns only applies to an 'after' hook, and none is registered.`);
4877
- if (spec === "all") return { ...tableColumns };
4878
- if (!Array.isArray(spec)) throw new Error(`Drizzle-GraphQL Error: ${where}.columns must be an array of column names or 'all'.`);
4879
- const resolved = {};
4880
- for (const name of spec) {
4881
- const column = typeof name === "string" && Object.keys(tableColumns).includes(name) ? tableColumns[name] : void 0;
4882
- if (!column) throw new Error(`Drizzle-GraphQL Error: ${where}.columns names '${String(name)}', which is not a column of that table.`);
4883
- resolved[name] = column;
4884
- }
4885
- return resolved;
4886
- };
4887
- /**
4888
- * Adds a hook's `columns` to a RETURNING column map, and reports which keys it added — the
4889
- * ones the client never asked for, which have to come back off before the rows are mapped.
4890
- * Returns the map untouched, and no keys, when the hook named none or the selection already
4891
- * covers them.
4892
- */
4893
- const withHookColumns = (hooks, columns) => {
4894
- const hookColumns = hooks?.columns;
4895
- if (!hookColumns) return {
4896
- returning: columns,
4897
- added: void 0
4898
- };
4899
- const selected = new Set(Object.keys(columns));
4900
- const added = Object.keys(hookColumns).filter((key) => !selected.has(key));
4901
- if (!added.length) return {
4902
- returning: columns,
4903
- added: void 0
4904
- };
4905
- const returning = { ...columns };
4906
- for (const key of added) returning[key] = hookColumns[key];
4907
- return {
4908
- returning,
4909
- added
4910
- };
4911
- };
4912
- /**
4913
- * The rows with the hook-only keys taken off, as fresh objects: the hook was handed the
4914
- * originals and may still hold them, so they are not mutated under it.
4915
- */
4916
- const omitHookColumns = (rows, added) => {
4917
- if (!added) return rows;
4918
- return rows.map((row) => {
4919
- const copy = { ...row };
4920
- for (const key of added) delete copy[key];
4921
- return copy;
4922
- });
4923
- };
4924
- /**
4925
- * Invokes one position of a field's hooks. Returns `undefined` rather than a resolved promise
4926
- * when nothing is registered, so the awaiting call site costs nothing on an unhooked build.
4927
- */
4928
- const runWriteHook = (hooks, position, payload) => {
4929
- const hook = position === "before" ? hooks?.before : hooks?.after;
4930
- if (!hook) return;
4931
- return Promise.resolve(hook({
4932
- ...payload,
4933
- position,
4934
- rows: payload.rows ?? []
4935
- }));
4936
- };
4937
- //#endregion
4938
- //#region src/util/builders/common/write-scaffold.ts
4939
- /**
4940
- * Wraps one mutation body in the scaffolding above and returns the field it becomes.
4941
- *
4942
- * A field carrying a hook is forced into a transaction even when it would have run straight
4943
- * on `db`: a hook exists to write atomically with the mutation, and one that ran outside the
4944
- * transaction could not roll anything back.
4945
- */
4946
- const writeResolver = ({ db, tableName, operation, single, fieldName, args: queryArgs, txCtx, policies, run }) => {
4947
- const hooks = policies?.onWrite?.(tableName, operation);
4948
- const errorCtx = {
4949
- table: tableName,
4950
- operation,
4951
- field: fieldName
4952
- };
4953
- return {
4954
- name: fieldName,
4955
- resolver: async (_source, args, context, info) => {
4956
- try {
4957
- return await runMutation(db, context, info, txCtx, (executor) => {
4958
- const payload = {
4959
- table: tableName,
4960
- operation,
4961
- single,
4962
- args,
4963
- context,
4964
- info,
4965
- tx: executor
4966
- };
4967
- let added;
4968
- return run({
4969
- executor,
4970
- args,
4971
- context,
4972
- info,
4973
- before: () => runWriteHook(hooks, "before", payload),
4974
- after: (rows) => runWriteHook(hooks, "after", {
4975
- ...payload,
4976
- rows: rows ?? []
4977
- }),
4978
- returning: (columns) => {
4979
- const withHook = withHookColumns(hooks, columns);
4980
- added = withHook.added;
4981
- return withHook.returning;
4982
- },
4983
- output: (rows) => omitHookColumns(rows, added)
4984
- });
4985
- }, !!hooks);
4986
- } catch (e) {
4987
- throw withErrorContext(toGraphQLError(e), errorCtx);
4988
- }
4989
- },
4990
- args: queryArgs
4991
- };
4992
- };
4993
- //#endregion
4994
5019
  //#region src/util/features.ts
4995
5020
  /**
4996
5021
  * What a table generates when the config says nothing. Everything is on except the opt-in
@@ -6992,7 +7017,9 @@ const generateSchemaData$2 = (db, schema, relations, options) => {
6992
7017
  fieldName: updateCountFieldName,
6993
7018
  requireWhere: tableFeatures.requireWhere,
6994
7019
  filterCtx,
6995
- txCtx: mutationTxCtx
7020
+ txCtx: mutationTxCtx,
7021
+ policies,
7022
+ returnsRows: false
6996
7023
  }) : void 0;
6997
7024
  const deleteCountGenerated = tableFeatures.delete && tableFeatures.countMutations ? generateWriteCount({
6998
7025
  db,
@@ -7003,7 +7030,9 @@ const generateSchemaData$2 = (db, schema, relations, options) => {
7003
7030
  fieldName: deleteCountFieldName,
7004
7031
  requireWhere: tableFeatures.requireWhere,
7005
7032
  filterCtx,
7006
- txCtx: mutationTxCtx
7033
+ txCtx: mutationTxCtx,
7034
+ policies,
7035
+ returnsRows: false
7007
7036
  }) : void 0;
7008
7037
  const hardDeleteMeta = softDeleteInfo?.hardDelete ? { hardDelete: true } : {};
7009
7038
  const withMeta = (generated, meta) => ({
@@ -7073,12 +7102,25 @@ const generateSchemaData$2 = (db, schema, relations, options) => {
7073
7102
  {
7074
7103
  generated: updateCountGenerated,
7075
7104
  type: new GraphQLNonNull(GraphQLInt),
7105
+ meta: {
7106
+ operation: "update",
7107
+ single: false,
7108
+ targetArg: "where",
7109
+ count: true
7110
+ },
7076
7111
  description: "How many rows the update touched. The rows themselves are not read back, which is the point of this mutation."
7077
7112
  },
7078
7113
  {
7079
7114
  generated: deleteCountGenerated,
7080
7115
  type: new GraphQLNonNull(GraphQLInt),
7081
- description: "How many rows the delete removed. The rows themselves are not read back, which is the point of this mutation."
7116
+ meta: {
7117
+ operation: "delete",
7118
+ single: false,
7119
+ targetArg: "where",
7120
+ count: true,
7121
+ ...hardDeleteMeta
7122
+ },
7123
+ description: "How many rows the delete removed — or, on a soft-deleting table, marked deleted. The rows themselves are not read back, which is the point of this mutation."
7082
7124
  }
7083
7125
  ],
7084
7126
  onConflictInput,
@@ -7579,7 +7621,10 @@ const createSchemaDataGenerator = (adapter) => {
7579
7621
  requireWhere: tableFeatures.requireWhere,
7580
7622
  filterCtx,
7581
7623
  txCtx: mutationTxCtx,
7582
- nested: nestedRuntime
7624
+ nested: nestedRuntime,
7625
+ policies,
7626
+ pkNames: primaryKeyPropNames(schema[tableName]),
7627
+ returnsRows: true
7583
7628
  }) : void 0;
7584
7629
  const deleteCountGenerated = tableFeatures.delete && tableFeatures.countMutations ? generateWriteCount({
7585
7630
  db,
@@ -7590,7 +7635,10 @@ const createSchemaDataGenerator = (adapter) => {
7590
7635
  fieldName: deleteCountFieldName,
7591
7636
  requireWhere: tableFeatures.requireWhere,
7592
7637
  filterCtx,
7593
- txCtx: mutationTxCtx
7638
+ txCtx: mutationTxCtx,
7639
+ policies,
7640
+ pkNames: primaryKeyPropNames(schema[tableName]),
7641
+ returnsRows: true
7594
7642
  }) : void 0;
7595
7643
  const hardDeleteMeta = softDeleteInfo?.hardDelete ? { hardDelete: true } : {};
7596
7644
  return {
@@ -7700,12 +7748,25 @@ const createSchemaDataGenerator = (adapter) => {
7700
7748
  {
7701
7749
  generated: updateCountGenerated,
7702
7750
  type: new GraphQLNonNull(GraphQLInt),
7751
+ meta: {
7752
+ operation: "update",
7753
+ single: false,
7754
+ targetArg: "where",
7755
+ count: true
7756
+ },
7703
7757
  description: "How many rows the update touched. The rows themselves are not read back, which is the point of this mutation."
7704
7758
  },
7705
7759
  {
7706
7760
  generated: deleteCountGenerated,
7707
7761
  type: new GraphQLNonNull(GraphQLInt),
7708
- description: "How many rows the delete removed. The rows themselves are not read back, which is the point of this mutation."
7762
+ meta: {
7763
+ operation: "delete",
7764
+ single: false,
7765
+ targetArg: "where",
7766
+ count: true,
7767
+ ...hardDeleteMeta
7768
+ },
7769
+ description: "How many rows the delete removed — or, on a soft-deleting table, marked deleted. The rows themselves are not read back, which is the point of this mutation."
7709
7770
  }
7710
7771
  ],
7711
7772
  onConflictInput,