@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/README.md CHANGED
@@ -1623,9 +1623,27 @@ mutation {
1623
1623
  - Both return `Int!` — the number of rows the write affected — and add no new output type
1624
1624
  to the schema
1625
1625
  - Arguments are exactly the plural mutation's, so a client swaps one field name for the
1626
- other; `features.requireWhere` applies to them the same way
1626
+ other; `features.requireWhere` applies to them the same way, and on a soft-deleting
1627
+ table that opted into `hardDelete` the delete takes `hard` too
1627
1628
  - They follow the feature switch of the write they mirror: `updateCount` needs
1628
1629
  `features.update`, `deleteCount` needs `features.delete`
1630
+ - They obey the same row policies as the plural write — only the answer differs:
1631
+ - [`scope`](#row-scoping-and-multi-tenancy) is ANDed into the `where`, so they reach,
1632
+ and count, only in-scope rows
1633
+ - on a [soft-deleting](#soft-delete) table `delete<Table>Count` marks the rows rather
1634
+ than removing them, and neither mutation reaches a row that is already marked
1635
+ - a [`contextValues`](#row-scoping-and-multi-tenancy) column is never reassigned by the
1636
+ update
1637
+ - [`onWrite`](#write-hooks) hooks run `before` and `after`, in a transaction, with the
1638
+ plural write's payload (`operation: 'update'` / `'delete'`, `single: false`). An
1639
+ `after` hook is handed rows, so a table with one gives up the returnless write: the
1640
+ statement `RETURNING`s the hook's `columns`, or just the primary key when it names
1641
+ none (every column, on a table without a key), and the count is the number of rows
1642
+ returned. Without an `after` hook there is no `RETURNING` at all. On MySQL the hook
1643
+ gets `rows: []`, as it does on every MySQL mutation
1644
+ - Their [`extensions.drizzle`](#identifying-generated-fields) is the plural write's
1645
+ (`operation: 'update'` / `'delete'`, `targetArg: 'where'`) plus `count: true`, so a
1646
+ wrapper that gates writes on `operation` covers them too
1629
1647
  - **MySQL** gets them too, and they are arguably most useful there: MySQL's other mutations
1630
1648
  return only `MutationReturn { isSuccess }`, so a row count is strictly more information
1631
1649
  - `update<Table>Count` **rejects** nested writes with a `GraphQLError` — a nested write
@@ -2122,6 +2140,9 @@ onWrite: {
2122
2140
  works.
2123
2141
  - The columns are added to `RETURNING` for every write the hook is attached to: insert, upsert,
2124
2142
  update, `updateMany`, delete and restore. A delete's rows are the rows it removed.
2143
+ - The [count mutations](#row-counts-instead-of-rows) fire the hooks as `update` / `delete`.
2144
+ The client selects nothing there, so an `after` hook's rows hold exactly its `columns`, or
2145
+ just the primary key when it names none — the one `RETURNING` those mutations pay for.
2125
2146
  - **The client's response is unchanged.** Columns the hook asked for but the client did not
2126
2147
  select are taken back off before the rows are mapped, so they reach neither the response nor
2127
2148
  a custom resolver calling the generated one. The hook gets its own copy of the rows.
@@ -2329,7 +2350,9 @@ the check to make before treating a field as one of ours. Relation fields (and
2329
2350
  naming the relation's **target** — so `Users.posts` reads as
2330
2351
  `{ table: 'Posts', parentTable: 'Users', relation: 'posts' }`. Object types carry
2331
2352
  `{ table, kind: 'type', primaryKey }`, which is what a stitching layer needs to map a type
2332
- back to its source.
2353
+ back to its source. The [count mutations](#row-counts-instead-of-rows) carry their plural
2354
+ write's `operation` plus `count: true` — they write the same rows but resolve to an `Int!`, so
2355
+ a wrapper that reads the result as rows should check `count` first.
2333
2356
 
2334
2357
  Because the row identity of a mutation lives in a different argument for every operation,
2335
2358
  `identifyRows` reads whichever one applies and hands back primary-key values:
package/dist/index.cjs CHANGED
@@ -3748,6 +3748,145 @@ const runMutation = async (db, context, info, txCtx, body, forceTx) => {
3748
3748
  return runOnSharedTx(state, body);
3749
3749
  };
3750
3750
  //#endregion
3751
+ //#region src/util/builders/common/write-hooks.ts
3752
+ /**
3753
+ * Normalizes the two registration shapes: a bare function is the `after` hook — the position
3754
+ * that has rows, and the one the common audit/outbox case wants — while `{ before, after }`
3755
+ * names them explicitly.
3756
+ */
3757
+ const normalizeWriteHooks = (hooks, tableColumns, where) => {
3758
+ if (!hooks) return;
3759
+ if (typeof hooks === "function") return { after: hooks };
3760
+ const resolved = {
3761
+ before: hooks.before,
3762
+ after: hooks.after
3763
+ };
3764
+ if (hooks.columns !== void 0) resolved.columns = resolveHookColumns(hooks.columns, !!hooks.after, tableColumns, where);
3765
+ return resolved.before || resolved.after ? resolved : void 0;
3766
+ };
3767
+ /**
3768
+ * Resolves a hook's `columns` against the table it runs on. `where` names the registration
3769
+ * (`config.onWrite.posts`) and, for a top-level one, the table, so the error says which.
3770
+ */
3771
+ const resolveHookColumns = (spec, hasAfter, tableColumns, where) => {
3772
+ if (!hasAfter) throw new Error(`Drizzle-GraphQL Error: ${where}.columns only applies to an 'after' hook, and none is registered.`);
3773
+ if (spec === "all") return { ...tableColumns };
3774
+ if (!Array.isArray(spec)) throw new Error(`Drizzle-GraphQL Error: ${where}.columns must be an array of column names or 'all'.`);
3775
+ const resolved = {};
3776
+ for (const name of spec) {
3777
+ const column = typeof name === "string" && Object.keys(tableColumns).includes(name) ? tableColumns[name] : void 0;
3778
+ if (!column) throw new Error(`Drizzle-GraphQL Error: ${where}.columns names '${String(name)}', which is not a column of that table.`);
3779
+ resolved[name] = column;
3780
+ }
3781
+ return resolved;
3782
+ };
3783
+ /**
3784
+ * Adds a hook's `columns` to a RETURNING column map, and reports which keys it added — the
3785
+ * ones the client never asked for, which have to come back off before the rows are mapped.
3786
+ * Returns the map untouched, and no keys, when the hook named none or the selection already
3787
+ * covers them.
3788
+ */
3789
+ const withHookColumns = (hooks, columns) => {
3790
+ const hookColumns = hooks?.columns;
3791
+ if (!hookColumns) return {
3792
+ returning: columns,
3793
+ added: void 0
3794
+ };
3795
+ const selected = new Set(Object.keys(columns));
3796
+ const added = Object.keys(hookColumns).filter((key) => !selected.has(key));
3797
+ if (!added.length) return {
3798
+ returning: columns,
3799
+ added: void 0
3800
+ };
3801
+ const returning = { ...columns };
3802
+ for (const key of added) returning[key] = hookColumns[key];
3803
+ return {
3804
+ returning,
3805
+ added
3806
+ };
3807
+ };
3808
+ /**
3809
+ * The rows with the hook-only keys taken off, as fresh objects: the hook was handed the
3810
+ * originals and may still hold them, so they are not mutated under it.
3811
+ */
3812
+ const omitHookColumns = (rows, added) => {
3813
+ if (!added) return rows;
3814
+ return rows.map((row) => {
3815
+ const copy = { ...row };
3816
+ for (const key of added) delete copy[key];
3817
+ return copy;
3818
+ });
3819
+ };
3820
+ /**
3821
+ * Invokes one position of a field's hooks. Returns `undefined` rather than a resolved promise
3822
+ * when nothing is registered, so the awaiting call site costs nothing on an unhooked build.
3823
+ */
3824
+ const runWriteHook = (hooks, position, payload) => {
3825
+ const hook = position === "before" ? hooks?.before : hooks?.after;
3826
+ if (!hook) return;
3827
+ return Promise.resolve(hook({
3828
+ ...payload,
3829
+ position,
3830
+ rows: payload.rows ?? []
3831
+ }));
3832
+ };
3833
+ //#endregion
3834
+ //#region src/util/builders/common/write-scaffold.ts
3835
+ /**
3836
+ * Wraps one mutation body in the scaffolding above and returns the field it becomes.
3837
+ *
3838
+ * A field carrying a hook is forced into a transaction even when it would have run straight
3839
+ * on `db`: a hook exists to write atomically with the mutation, and one that ran outside the
3840
+ * transaction could not roll anything back.
3841
+ */
3842
+ const writeResolver = ({ db, tableName, operation, single, fieldName, args: queryArgs, txCtx, policies, run }) => {
3843
+ const hooks = policies?.onWrite?.(tableName, operation);
3844
+ const errorCtx = {
3845
+ table: tableName,
3846
+ operation,
3847
+ field: fieldName
3848
+ };
3849
+ return {
3850
+ name: fieldName,
3851
+ resolver: async (_source, args, context, info) => {
3852
+ try {
3853
+ return await runMutation(db, context, info, txCtx, (executor) => {
3854
+ const payload = {
3855
+ table: tableName,
3856
+ operation,
3857
+ single,
3858
+ args,
3859
+ context,
3860
+ info,
3861
+ tx: executor
3862
+ };
3863
+ let added;
3864
+ return run({
3865
+ executor,
3866
+ args,
3867
+ context,
3868
+ info,
3869
+ before: () => runWriteHook(hooks, "before", payload),
3870
+ after: (rows) => runWriteHook(hooks, "after", {
3871
+ ...payload,
3872
+ rows: rows ?? []
3873
+ }),
3874
+ returning: (columns) => {
3875
+ const withHook = withHookColumns(hooks, columns);
3876
+ added = withHook.added;
3877
+ return withHook.returning;
3878
+ },
3879
+ output: (rows) => omitHookColumns(rows, added)
3880
+ });
3881
+ }, !!hooks);
3882
+ } catch (e) {
3883
+ throw withErrorContext(toGraphQLError(e), errorCtx);
3884
+ }
3885
+ },
3886
+ args: queryArgs
3887
+ };
3888
+ };
3889
+ //#endregion
3751
3890
  //#region src/util/builders/common/mutation-helpers.ts
3752
3891
  /**
3753
3892
  * The `hard` argument on the delete mutations of a soft-deleting table that opted into
@@ -3891,54 +4030,79 @@ const assertSingleMatch = async (executor, table, filters) => {
3891
4030
  * The plural `update` and `delete` always `RETURNING *`, which is the wrong shape for
3892
4031
  * "archive everything older than a year": the caller pays to ship rows it does not want, and
3893
4032
  * on a large match that cost is the whole mutation. These return `Int!` instead — how many
3894
- * rows the write touched, as the driver reported it, with no RETURNING clause at all.
4033
+ * rows the write touched.
3895
4034
  *
3896
- * Dialect-independent: drizzle's update/delete builders take the same calls everywhere, and
3897
- * the drivers' disagreement about how to spell the row count is handled by
3898
- * {@link rowsAffected}.
3899
- */
3900
- const generateWriteCount = ({ db, tableName, table, kind, setArgs, filterArgs, fieldName, requireWhere, filterCtx, txCtx, nested }) => {
4035
+ * Leaving the payload off changes nothing else: the write obeys every rule of the plural
4036
+ * mutation it mirrors, through the same {@link writeResolver} scaffolding.
4037
+ *
4038
+ * - `scope` (and the soft-delete marker) is ANDed into the `where`, so only rows the plural
4039
+ * write could reach are counted and written.
4040
+ * - On a soft-deleting table the delete is the marking `UPDATE`, not a `DELETE`, and rows that
4041
+ * are already marked are not matched; the update skips marked rows too. `hard: true` exists
4042
+ * exactly where the plural delete takes it.
4043
+ * - Context-derived columns are stripped from the update's `set`, as the plural update does.
4044
+ * - `onWrite` hooks run `before` and `after`, inside a transaction. The `after` hook is handed
4045
+ * rows, so a table with one pays for a `RETURNING` — of the columns the hook names in
4046
+ * `columns`, or of the primary key when it names none (the whole row on a table without a
4047
+ * key) — and the count is the number of rows returned. Every other write, and every write on
4048
+ * MySQL (no `RETURNING`; its hooks see `rows: []` as on every MySQL mutation), skips the
4049
+ * `RETURNING` and reads the count off the driver's result via {@link rowsAffected}.
4050
+ */
4051
+ const generateWriteCount = ({ db, tableName, table, kind, setArgs, filterArgs, fieldName, requireWhere, filterCtx, txCtx, nested, policies, pkNames = [], returnsRows }) => {
4052
+ const softDelete = kind === "delete" ? policies?.softDelete?.(tableName) : void 0;
4053
+ const canHardDelete = softDelete?.hardDelete === true;
3901
4054
  const queryArgs = {
3902
4055
  ...setArgs ? { set: { type: new graphql.GraphQLNonNull(setArgs) } } : {},
3903
- where: { type: requireWhere ? new graphql.GraphQLNonNull(filterArgs) : filterArgs }
4056
+ where: { type: requireWhere ? new graphql.GraphQLNonNull(filterArgs) : filterArgs },
4057
+ ...canHardDelete ? { hard: hardDeleteArg } : {}
3904
4058
  };
3905
- const errorCtx = {
3906
- table: tableName,
4059
+ const readsRows = returnsRows && !!policies?.onWrite?.(tableName, kind)?.after;
4060
+ const allColumns = (0, drizzle_orm.getColumns)(table);
4061
+ const keyColumns = pkNames.length ? Object.fromEntries(pkNames.map((name) => [name, allColumns[name]])) : allColumns;
4062
+ return writeResolver({
4063
+ db,
4064
+ tableName,
3907
4065
  operation: kind,
3908
- field: fieldName
3909
- };
3910
- return {
3911
- name: fieldName,
3912
- resolver: async (_source, args, context, info) => {
3913
- try {
3914
- return await runMutation(db, context, info, txCtx, async (executor) => {
3915
- const { where, set } = args;
3916
- const filters = scopedWhere({
3917
- scope: void 0,
3918
- tableName,
3919
- table,
3920
- where,
3921
- relationCtx: relationFilterCtx(filterCtx, tableName),
3922
- required: requireWhere
3923
- });
3924
- let query;
3925
- if (kind === "delete") query = executor.delete(table);
3926
- else {
3927
- const entry = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
3928
- 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" });
3929
- const values = remapUpdateInput(entry ? entry.columns : set, table, tableName);
3930
- if (!Object.keys(values).length) throw drizzleError("Unable to update with no values specified!", { code: "DRIZZLE_NO_VALUES" });
3931
- query = executor.update(table).set(values);
3932
- }
3933
- if (filters) query = query.where(filters);
3934
- return rowsAffected(await query);
3935
- });
3936
- } catch (e) {
3937
- throw withErrorContext(toGraphQLError(e), errorCtx);
4066
+ single: false,
4067
+ fieldName,
4068
+ txCtx,
4069
+ policies,
4070
+ args: queryArgs,
4071
+ run: async ({ executor, args, context, before, after, returning }) => {
4072
+ const { where, set } = args;
4073
+ const hard = canHardDelete && args.hard === true;
4074
+ const scope = policies?.scope?.(context);
4075
+ await before();
4076
+ let query;
4077
+ if (kind === "delete") query = softDelete && !hard ? executor.update(table).set({ [softDelete.columnName]: softDelete.writeDeleted() }) : executor.delete(table);
4078
+ else {
4079
+ const entry = nested?.enabled(tableName) ? nested.split(tableName, set) : void 0;
4080
+ 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" });
4081
+ const values = stripContextValues(remapUpdateInput(entry ? entry.columns : set, table, tableName), policies?.contextValues?.(tableName));
4082
+ if (!Object.keys(values).length) throw drizzleError("Unable to update with no values specified!", { code: "DRIZZLE_NO_VALUES" });
4083
+ query = executor.update(table).set(values);
3938
4084
  }
3939
- },
3940
- args: queryArgs
3941
- };
4085
+ const filters = scopedWhere({
4086
+ scope,
4087
+ tableName,
4088
+ table,
4089
+ where,
4090
+ relationCtx: relationFilterCtx(filterCtx, tableName),
4091
+ required: requireWhere,
4092
+ deleted: hard ? "INCLUDE" : void 0
4093
+ });
4094
+ if (filters) query = query.where(filters);
4095
+ if (!readsRows) {
4096
+ const result = await query;
4097
+ await after();
4098
+ return rowsAffected(result);
4099
+ }
4100
+ const named = returning({});
4101
+ const rows = await query.returning(Object.keys(named).length ? named : keyColumns);
4102
+ await after(rows);
4103
+ return rows.length;
4104
+ }
4105
+ });
3942
4106
  };
3943
4107
  //#endregion
3944
4108
  //#region src/util/batch-loader/index.ts
@@ -4876,145 +5040,6 @@ const generateTableTypes = (tableName, tables, relationMap, withReturning, relat
4876
5040
  };
4877
5041
  };
4878
5042
  //#endregion
4879
- //#region src/util/builders/common/write-hooks.ts
4880
- /**
4881
- * Normalizes the two registration shapes: a bare function is the `after` hook — the position
4882
- * that has rows, and the one the common audit/outbox case wants — while `{ before, after }`
4883
- * names them explicitly.
4884
- */
4885
- const normalizeWriteHooks = (hooks, tableColumns, where) => {
4886
- if (!hooks) return;
4887
- if (typeof hooks === "function") return { after: hooks };
4888
- const resolved = {
4889
- before: hooks.before,
4890
- after: hooks.after
4891
- };
4892
- if (hooks.columns !== void 0) resolved.columns = resolveHookColumns(hooks.columns, !!hooks.after, tableColumns, where);
4893
- return resolved.before || resolved.after ? resolved : void 0;
4894
- };
4895
- /**
4896
- * Resolves a hook's `columns` against the table it runs on. `where` names the registration
4897
- * (`config.onWrite.posts`) and, for a top-level one, the table, so the error says which.
4898
- */
4899
- const resolveHookColumns = (spec, hasAfter, tableColumns, where) => {
4900
- if (!hasAfter) throw new Error(`Drizzle-GraphQL Error: ${where}.columns only applies to an 'after' hook, and none is registered.`);
4901
- if (spec === "all") return { ...tableColumns };
4902
- if (!Array.isArray(spec)) throw new Error(`Drizzle-GraphQL Error: ${where}.columns must be an array of column names or 'all'.`);
4903
- const resolved = {};
4904
- for (const name of spec) {
4905
- const column = typeof name === "string" && Object.keys(tableColumns).includes(name) ? tableColumns[name] : void 0;
4906
- if (!column) throw new Error(`Drizzle-GraphQL Error: ${where}.columns names '${String(name)}', which is not a column of that table.`);
4907
- resolved[name] = column;
4908
- }
4909
- return resolved;
4910
- };
4911
- /**
4912
- * Adds a hook's `columns` to a RETURNING column map, and reports which keys it added — the
4913
- * ones the client never asked for, which have to come back off before the rows are mapped.
4914
- * Returns the map untouched, and no keys, when the hook named none or the selection already
4915
- * covers them.
4916
- */
4917
- const withHookColumns = (hooks, columns) => {
4918
- const hookColumns = hooks?.columns;
4919
- if (!hookColumns) return {
4920
- returning: columns,
4921
- added: void 0
4922
- };
4923
- const selected = new Set(Object.keys(columns));
4924
- const added = Object.keys(hookColumns).filter((key) => !selected.has(key));
4925
- if (!added.length) return {
4926
- returning: columns,
4927
- added: void 0
4928
- };
4929
- const returning = { ...columns };
4930
- for (const key of added) returning[key] = hookColumns[key];
4931
- return {
4932
- returning,
4933
- added
4934
- };
4935
- };
4936
- /**
4937
- * The rows with the hook-only keys taken off, as fresh objects: the hook was handed the
4938
- * originals and may still hold them, so they are not mutated under it.
4939
- */
4940
- const omitHookColumns = (rows, added) => {
4941
- if (!added) return rows;
4942
- return rows.map((row) => {
4943
- const copy = { ...row };
4944
- for (const key of added) delete copy[key];
4945
- return copy;
4946
- });
4947
- };
4948
- /**
4949
- * Invokes one position of a field's hooks. Returns `undefined` rather than a resolved promise
4950
- * when nothing is registered, so the awaiting call site costs nothing on an unhooked build.
4951
- */
4952
- const runWriteHook = (hooks, position, payload) => {
4953
- const hook = position === "before" ? hooks?.before : hooks?.after;
4954
- if (!hook) return;
4955
- return Promise.resolve(hook({
4956
- ...payload,
4957
- position,
4958
- rows: payload.rows ?? []
4959
- }));
4960
- };
4961
- //#endregion
4962
- //#region src/util/builders/common/write-scaffold.ts
4963
- /**
4964
- * Wraps one mutation body in the scaffolding above and returns the field it becomes.
4965
- *
4966
- * A field carrying a hook is forced into a transaction even when it would have run straight
4967
- * on `db`: a hook exists to write atomically with the mutation, and one that ran outside the
4968
- * transaction could not roll anything back.
4969
- */
4970
- const writeResolver = ({ db, tableName, operation, single, fieldName, args: queryArgs, txCtx, policies, run }) => {
4971
- const hooks = policies?.onWrite?.(tableName, operation);
4972
- const errorCtx = {
4973
- table: tableName,
4974
- operation,
4975
- field: fieldName
4976
- };
4977
- return {
4978
- name: fieldName,
4979
- resolver: async (_source, args, context, info) => {
4980
- try {
4981
- return await runMutation(db, context, info, txCtx, (executor) => {
4982
- const payload = {
4983
- table: tableName,
4984
- operation,
4985
- single,
4986
- args,
4987
- context,
4988
- info,
4989
- tx: executor
4990
- };
4991
- let added;
4992
- return run({
4993
- executor,
4994
- args,
4995
- context,
4996
- info,
4997
- before: () => runWriteHook(hooks, "before", payload),
4998
- after: (rows) => runWriteHook(hooks, "after", {
4999
- ...payload,
5000
- rows: rows ?? []
5001
- }),
5002
- returning: (columns) => {
5003
- const withHook = withHookColumns(hooks, columns);
5004
- added = withHook.added;
5005
- return withHook.returning;
5006
- },
5007
- output: (rows) => omitHookColumns(rows, added)
5008
- });
5009
- }, !!hooks);
5010
- } catch (e) {
5011
- throw withErrorContext(toGraphQLError(e), errorCtx);
5012
- }
5013
- },
5014
- args: queryArgs
5015
- };
5016
- };
5017
- //#endregion
5018
5043
  //#region src/util/features.ts
5019
5044
  /**
5020
5045
  * What a table generates when the config says nothing. Everything is on except the opt-in
@@ -7016,7 +7041,9 @@ const generateSchemaData$2 = (db, schema, relations, options) => {
7016
7041
  fieldName: updateCountFieldName,
7017
7042
  requireWhere: tableFeatures.requireWhere,
7018
7043
  filterCtx,
7019
- txCtx: mutationTxCtx
7044
+ txCtx: mutationTxCtx,
7045
+ policies,
7046
+ returnsRows: false
7020
7047
  }) : void 0;
7021
7048
  const deleteCountGenerated = tableFeatures.delete && tableFeatures.countMutations ? generateWriteCount({
7022
7049
  db,
@@ -7027,7 +7054,9 @@ const generateSchemaData$2 = (db, schema, relations, options) => {
7027
7054
  fieldName: deleteCountFieldName,
7028
7055
  requireWhere: tableFeatures.requireWhere,
7029
7056
  filterCtx,
7030
- txCtx: mutationTxCtx
7057
+ txCtx: mutationTxCtx,
7058
+ policies,
7059
+ returnsRows: false
7031
7060
  }) : void 0;
7032
7061
  const hardDeleteMeta = softDeleteInfo?.hardDelete ? { hardDelete: true } : {};
7033
7062
  const withMeta = (generated, meta) => ({
@@ -7097,12 +7126,25 @@ const generateSchemaData$2 = (db, schema, relations, options) => {
7097
7126
  {
7098
7127
  generated: updateCountGenerated,
7099
7128
  type: new graphql.GraphQLNonNull(graphql.GraphQLInt),
7129
+ meta: {
7130
+ operation: "update",
7131
+ single: false,
7132
+ targetArg: "where",
7133
+ count: true
7134
+ },
7100
7135
  description: "How many rows the update touched. The rows themselves are not read back, which is the point of this mutation."
7101
7136
  },
7102
7137
  {
7103
7138
  generated: deleteCountGenerated,
7104
7139
  type: new graphql.GraphQLNonNull(graphql.GraphQLInt),
7105
- description: "How many rows the delete removed. The rows themselves are not read back, which is the point of this mutation."
7140
+ meta: {
7141
+ operation: "delete",
7142
+ single: false,
7143
+ targetArg: "where",
7144
+ count: true,
7145
+ ...hardDeleteMeta
7146
+ },
7147
+ 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."
7106
7148
  }
7107
7149
  ],
7108
7150
  onConflictInput,
@@ -7603,7 +7645,10 @@ const createSchemaDataGenerator = (adapter) => {
7603
7645
  requireWhere: tableFeatures.requireWhere,
7604
7646
  filterCtx,
7605
7647
  txCtx: mutationTxCtx,
7606
- nested: nestedRuntime
7648
+ nested: nestedRuntime,
7649
+ policies,
7650
+ pkNames: primaryKeyPropNames(schema[tableName]),
7651
+ returnsRows: true
7607
7652
  }) : void 0;
7608
7653
  const deleteCountGenerated = tableFeatures.delete && tableFeatures.countMutations ? generateWriteCount({
7609
7654
  db,
@@ -7614,7 +7659,10 @@ const createSchemaDataGenerator = (adapter) => {
7614
7659
  fieldName: deleteCountFieldName,
7615
7660
  requireWhere: tableFeatures.requireWhere,
7616
7661
  filterCtx,
7617
- txCtx: mutationTxCtx
7662
+ txCtx: mutationTxCtx,
7663
+ policies,
7664
+ pkNames: primaryKeyPropNames(schema[tableName]),
7665
+ returnsRows: true
7618
7666
  }) : void 0;
7619
7667
  const hardDeleteMeta = softDeleteInfo?.hardDelete ? { hardDelete: true } : {};
7620
7668
  return {
@@ -7724,12 +7772,25 @@ const createSchemaDataGenerator = (adapter) => {
7724
7772
  {
7725
7773
  generated: updateCountGenerated,
7726
7774
  type: new graphql.GraphQLNonNull(graphql.GraphQLInt),
7775
+ meta: {
7776
+ operation: "update",
7777
+ single: false,
7778
+ targetArg: "where",
7779
+ count: true
7780
+ },
7727
7781
  description: "How many rows the update touched. The rows themselves are not read back, which is the point of this mutation."
7728
7782
  },
7729
7783
  {
7730
7784
  generated: deleteCountGenerated,
7731
7785
  type: new graphql.GraphQLNonNull(graphql.GraphQLInt),
7732
- description: "How many rows the delete removed. The rows themselves are not read back, which is the point of this mutation."
7786
+ meta: {
7787
+ operation: "delete",
7788
+ single: false,
7789
+ targetArg: "where",
7790
+ count: true,
7791
+ ...hardDeleteMeta
7792
+ },
7793
+ 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."
7733
7794
  }
7734
7795
  ],
7735
7796
  onConflictInput,