@vantreeseba/drizzle-graphql 13.0.0 → 13.1.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/README.md +86 -3
- package/dist/index.cjs +149 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +79 -4
- package/dist/index.d.ts +79 -4
- package/dist/index.js +149 -29
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -165,6 +165,14 @@ const GraphQLDecimalString = new GraphQLScalarType({
|
|
|
165
165
|
const uncapitalize = (input) => input?.length ? `${input[0].toLocaleLowerCase()}${input.length > 1 ? input.slice(1, input.length) : ""}` : input;
|
|
166
166
|
const capitalize = (input) => input?.length ? `${input[0].toLocaleUpperCase()}${input.length > 1 ? input.slice(1, input.length) : ""}` : input;
|
|
167
167
|
/**
|
|
168
|
+
* `inProgress` / `in-progress` / `in progress` / `InProgress` → `IN_PROGRESS`; `HTTPError` →
|
|
169
|
+
* `HTTP_ERROR`. Words are split at non-alphanumeric runs and at lower→upper and
|
|
170
|
+
* acronym→word boundaries, then upper-cased and joined with `_`.
|
|
171
|
+
*
|
|
172
|
+
* The preset behind `enumValueNameMapper: 'constant'`.
|
|
173
|
+
*/
|
|
174
|
+
const constantCase = (input) => input.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z])([A-Z][a-z])/g, "$1 $2").split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => part.toUpperCase()).join("_");
|
|
175
|
+
/**
|
|
168
176
|
* The `typeNameMapper` preset behind `typeNameMapper: 'singularize'`.
|
|
169
177
|
*
|
|
170
178
|
* Derives the singular and plural forms of a table key with the library's own `pluralize`,
|
|
@@ -185,6 +193,8 @@ const singularizeMapper = (tableName) => ({
|
|
|
185
193
|
//#endregion
|
|
186
194
|
//#region src/util/type-converter/index.ts
|
|
187
195
|
const allowedNameChars = /^[a-zA-Z0-9_]+$/;
|
|
196
|
+
/** A GraphQL `Name` that is also allowed as an enum value — the spec reserves the three literals. */
|
|
197
|
+
const validEnumValueName = (name) => /^[_a-zA-Z][_a-zA-Z0-9]*$/.test(name) && name !== "true" && name !== "false" && name !== "null";
|
|
188
198
|
/**
|
|
189
199
|
* The enum type a column was declared with, when it is a *named* one — `pgEnum('status', …)`
|
|
190
200
|
* shared by however many tables reference it. An inline value list (`text({ enum: [...] })`,
|
|
@@ -205,20 +215,35 @@ const pascalize = (input) => input.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((p
|
|
|
205
215
|
*/
|
|
206
216
|
const enumValuesKey = (values) => JSON.stringify(values);
|
|
207
217
|
/**
|
|
218
|
+
* Identity of the GraphQL names those values were given. Kept apart from {@link enumValuesKey}
|
|
219
|
+
* because `enumValueNameMapper` sees the column, so two columns reaching one type can name its
|
|
220
|
+
* values differently — and only one set of names can win.
|
|
221
|
+
*/
|
|
222
|
+
const enumValueNamesKey = (names) => JSON.stringify(names);
|
|
223
|
+
/**
|
|
208
224
|
* Every GraphQL enum name this build has handed out. Two columns that resolve to the same
|
|
209
225
|
* name share one type — that is how the columns of one `pgEnum` end up on a single type —
|
|
210
226
|
* so the values are kept alongside it to tell a genuine collision from a re-use.
|
|
211
227
|
*/
|
|
212
228
|
let enumNamesInUse = /* @__PURE__ */ new Map();
|
|
213
229
|
let enumNameMapper;
|
|
230
|
+
let enumValueNameMapper;
|
|
231
|
+
/** The value-name presets, by the string a config passes for them. */
|
|
232
|
+
const enumValueNamePresets = { constant: ({ value }) => constantCase(value) };
|
|
214
233
|
/**
|
|
215
234
|
* Resets the enum registry for a fresh schema build and installs that build's
|
|
216
|
-
* `enumNameMapper`. Called once per `generateSchemaData`, alongside
|
|
235
|
+
* `enumNameMapper` and `enumValueNameMapper`. Called once per `generateSchemaData`, alongside
|
|
217
236
|
* {@link registerScalarOverrides} — without the reset a second build would reuse the first
|
|
218
237
|
* build's enum types, and so its naming decisions.
|
|
219
238
|
*/
|
|
220
239
|
const registerEnumConfig = (config) => {
|
|
221
240
|
enumNameMapper = config.enumNameMapper;
|
|
241
|
+
const valueMapper = config.enumValueNameMapper;
|
|
242
|
+
if (typeof valueMapper === "string") {
|
|
243
|
+
const preset = enumValueNamePresets[valueMapper];
|
|
244
|
+
if (!preset) throw new Error(`Drizzle-GraphQL Error: Unknown enumValueNameMapper preset '${valueMapper}'. The only preset is 'constant'; pass a function for anything else.`);
|
|
245
|
+
enumValueNameMapper = preset;
|
|
246
|
+
} else enumValueNameMapper = valueMapper;
|
|
222
247
|
enumNamesInUse = /* @__PURE__ */ new Map();
|
|
223
248
|
};
|
|
224
249
|
/**
|
|
@@ -247,22 +272,50 @@ const generateEnumCached = (column, columnName, tableName) => {
|
|
|
247
272
|
columnName,
|
|
248
273
|
values
|
|
249
274
|
}) ?? (declared ? `${pascalize(declared.enumName)}Enum` : `${capitalize(tableName)}${capitalize(columnName)}Enum`);
|
|
275
|
+
const valueNames = values.map((value, index) => {
|
|
276
|
+
const mapped = enumValueNameMapper?.({
|
|
277
|
+
enumName: declared?.enumName,
|
|
278
|
+
schema: declared?.schema,
|
|
279
|
+
tableName,
|
|
280
|
+
columnName,
|
|
281
|
+
values,
|
|
282
|
+
value,
|
|
283
|
+
index,
|
|
284
|
+
typeName: name
|
|
285
|
+
});
|
|
286
|
+
if (mapped === void 0) return allowedNameChars.test(value) ? value : `Option${index}`;
|
|
287
|
+
if (!validEnumValueName(mapped)) throw new Error(`Drizzle-GraphQL Error: config.enumValueNameMapper named value '${value}' of enum '${name}' (on '${tableName}.${columnName}') '${mapped}', which is not a valid GraphQL enum value name. A name must match /^[_a-zA-Z][_a-zA-Z0-9]*$/ and not be true, false or null.`);
|
|
288
|
+
return mapped;
|
|
289
|
+
});
|
|
290
|
+
const seen = /* @__PURE__ */ new Map();
|
|
291
|
+
values.forEach((value, index) => {
|
|
292
|
+
const valueName = valueNames[index];
|
|
293
|
+
const earlier = seen.get(valueName);
|
|
294
|
+
if (earlier !== void 0) throw new Error(`Drizzle-GraphQL Error: Values '${earlier}' and '${value}' of enum '${name}' (on '${tableName}.${columnName}') both map to the GraphQL value name '${valueName}'. Give one of them a different name via config.enumValueNameMapper.`);
|
|
295
|
+
seen.set(valueName, value);
|
|
296
|
+
});
|
|
250
297
|
const valuesKey = enumValuesKey(values);
|
|
298
|
+
const namesKey = enumValueNamesKey(valueNames);
|
|
251
299
|
const claimed = enumNamesInUse.get(name);
|
|
252
300
|
if (claimed) {
|
|
253
301
|
if (claimed.valuesKey !== valuesKey) throw new Error(`Drizzle-GraphQL Error: Two different enums both map to the GraphQL type name '${name}' (most recently '${tableName}.${columnName}'). Give one of them a different name via config.enumNameMapper.`);
|
|
302
|
+
if (claimed.namesKey !== namesKey) {
|
|
303
|
+
const before = claimed.type.getValues().map((v) => v.name).join(", ");
|
|
304
|
+
throw new Error(`Drizzle-GraphQL Error: Columns sharing the GraphQL enum '${name}' name its values differently ('${tableName}.${columnName}' gives ${valueNames.join(", ")}; an earlier column gave ${before}). config.enumValueNameMapper must name a shared enum's values the same way for every column, or config.enumNameMapper must give the columns separate types.`);
|
|
305
|
+
}
|
|
254
306
|
return claimed.type;
|
|
255
307
|
}
|
|
256
308
|
const gqlEnum = new GraphQLEnumType({
|
|
257
309
|
name,
|
|
258
|
-
values: Object.fromEntries(values.map((e, index) => [
|
|
310
|
+
values: Object.fromEntries(values.map((e, index) => [valueNames[index], {
|
|
259
311
|
value: e,
|
|
260
312
|
description: `Value: ${e}`
|
|
261
313
|
}]))
|
|
262
314
|
});
|
|
263
315
|
enumNamesInUse.set(name, {
|
|
264
316
|
type: gqlEnum,
|
|
265
|
-
valuesKey
|
|
317
|
+
valuesKey,
|
|
318
|
+
namesKey
|
|
266
319
|
});
|
|
267
320
|
return gqlEnum;
|
|
268
321
|
};
|
|
@@ -1017,6 +1070,7 @@ const remapToGraphQLArrayOutput = (queryOutput, tableName, table, relationMap) =
|
|
|
1017
1070
|
return queryOutput;
|
|
1018
1071
|
};
|
|
1019
1072
|
const remapFromGraphQLCore = (value, column, columnName) => {
|
|
1073
|
+
if (value === null) return null;
|
|
1020
1074
|
if (getColumnScalarOverride(column, true)) {
|
|
1021
1075
|
if (typeof value === "object" && value !== null && Object.getPrototypeOf(value) === null) return Object.assign({}, value);
|
|
1022
1076
|
return value;
|
|
@@ -4804,16 +4858,70 @@ const generateTableTypes = (tableName, tables, relationMap, withReturning, relat
|
|
|
4804
4858
|
* that has rows, and the one the common audit/outbox case wants — while `{ before, after }`
|
|
4805
4859
|
* names them explicitly.
|
|
4806
4860
|
*/
|
|
4807
|
-
const normalizeWriteHooks = (hooks) => {
|
|
4861
|
+
const normalizeWriteHooks = (hooks, tableColumns, where) => {
|
|
4808
4862
|
if (!hooks) return;
|
|
4809
4863
|
if (typeof hooks === "function") return { after: hooks };
|
|
4810
4864
|
const resolved = {
|
|
4811
4865
|
before: hooks.before,
|
|
4812
4866
|
after: hooks.after
|
|
4813
4867
|
};
|
|
4868
|
+
if (hooks.columns !== void 0) resolved.columns = resolveHookColumns(hooks.columns, !!hooks.after, tableColumns, where);
|
|
4814
4869
|
return resolved.before || resolved.after ? resolved : void 0;
|
|
4815
4870
|
};
|
|
4816
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
|
+
/**
|
|
4817
4925
|
* Invokes one position of a field's hooks. Returns `undefined` rather than a resolved promise
|
|
4818
4926
|
* when nothing is registered, so the awaiting call site costs nothing on an unhooked build.
|
|
4819
4927
|
*/
|
|
@@ -4856,6 +4964,7 @@ const writeResolver = ({ db, tableName, operation, single, fieldName, args: quer
|
|
|
4856
4964
|
info,
|
|
4857
4965
|
tx: executor
|
|
4858
4966
|
};
|
|
4967
|
+
let added;
|
|
4859
4968
|
return run({
|
|
4860
4969
|
executor,
|
|
4861
4970
|
args,
|
|
@@ -4865,7 +4974,13 @@ const writeResolver = ({ db, tableName, operation, single, fieldName, args: quer
|
|
|
4865
4974
|
after: (rows) => runWriteHook(hooks, "after", {
|
|
4866
4975
|
...payload,
|
|
4867
4976
|
rows: rows ?? []
|
|
4868
|
-
})
|
|
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)
|
|
4869
4984
|
});
|
|
4870
4985
|
}, !!hooks);
|
|
4871
4986
|
} catch (e) {
|
|
@@ -5039,19 +5154,18 @@ const resolveBuildConfig = (config, schema) => {
|
|
|
5039
5154
|
}
|
|
5040
5155
|
const onWriteConfig = config?.onWrite;
|
|
5041
5156
|
const writeHooks = /* @__PURE__ */ new Map();
|
|
5042
|
-
let globalWriteHooks;
|
|
5043
5157
|
if (onWriteConfig) {
|
|
5044
|
-
if (typeof onWriteConfig === "function" || typeof onWriteConfig.before === "function" || typeof onWriteConfig.after === "function")
|
|
5158
|
+
if (typeof onWriteConfig === "function" || typeof onWriteConfig.before === "function" || typeof onWriteConfig.after === "function") for (const tableName of featureTables) writeHooks.set(tableName, normalizeWriteHooks(onWriteConfig, getColumns(schema[tableName]), `config.onWrite (on table '${tableName}')`));
|
|
5045
5159
|
else {
|
|
5046
5160
|
const tableNames = new Set(tableKeys);
|
|
5047
5161
|
for (const [tableName, hooks] of Object.entries(onWriteConfig)) {
|
|
5048
5162
|
if (!tableNames.has(tableName)) throw new Error(`Drizzle-GraphQL Error: config.onWrite names '${tableName}', which is not a table in the Drizzle schema.`);
|
|
5049
5163
|
if (typeof hooks !== "function" && typeof hooks !== "object") throw new Error(`Drizzle-GraphQL Error: config.onWrite.${tableName} must be a function or an object with 'before' and/or 'after'.`);
|
|
5050
|
-
writeHooks.set(tableName, normalizeWriteHooks(hooks));
|
|
5164
|
+
writeHooks.set(tableName, normalizeWriteHooks(hooks, getColumns(schema[tableName]), `config.onWrite.${tableName}`));
|
|
5051
5165
|
}
|
|
5052
5166
|
}
|
|
5053
5167
|
}
|
|
5054
|
-
const onWrite =
|
|
5168
|
+
const onWrite = writeHooks.size ? (tableName) => writeHooks.get(tableName) : void 0;
|
|
5055
5169
|
const policies = scopeConfig || contextValuesConfig || softDeleteInfos.size || onWrite || defaultOrderBy ? {
|
|
5056
5170
|
scope: scopeConfig ? (tableName) => scopeConfig[tableName] : void 0,
|
|
5057
5171
|
contextValues: contextValuesConfig ? (tableName) => contextValuesConfig[tableName] : void 0,
|
|
@@ -5117,6 +5231,7 @@ const resolveBuildConfig = (config, schema) => {
|
|
|
5117
5231
|
scalars: config?.scalars,
|
|
5118
5232
|
mapColumnType: config?.mapColumnType,
|
|
5119
5233
|
enumNameMapper: config?.enumNameMapper,
|
|
5234
|
+
enumValueNameMapper: config?.enumValueNameMapper,
|
|
5120
5235
|
transactions,
|
|
5121
5236
|
limits,
|
|
5122
5237
|
policies,
|
|
@@ -7000,7 +7115,7 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7000
7115
|
txCtx,
|
|
7001
7116
|
policies,
|
|
7002
7117
|
args: queryArgs,
|
|
7003
|
-
run: async ({ executor, args, context, info, before, after }) => {
|
|
7118
|
+
run: async ({ executor, args, context, info, before, after, returning: withHookReturning, output }) => {
|
|
7004
7119
|
const supplied = single ? [args.values] : args.values;
|
|
7005
7120
|
if (!supplied.length) throw drizzleError("No values were provided!", { code: "DRIZZLE_NO_VALUES" });
|
|
7006
7121
|
await before();
|
|
@@ -7022,13 +7137,13 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7022
7137
|
scope,
|
|
7023
7138
|
defaultOrderBy: policies?.defaultOrderBy
|
|
7024
7139
|
});
|
|
7025
|
-
const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
|
|
7140
|
+
const returning = withHookReturning(nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns);
|
|
7026
7141
|
const runInsert = async (target, values) => {
|
|
7027
7142
|
let query = target.insert(table).values(values).returning(returning);
|
|
7028
7143
|
if (conflictDoNothing) query = query.onConflictDoNothing();
|
|
7029
7144
|
return await query;
|
|
7030
7145
|
};
|
|
7031
|
-
const
|
|
7146
|
+
const written = nestedEntries ? await writeWithNestedOps({
|
|
7032
7147
|
executor,
|
|
7033
7148
|
runtime: nested,
|
|
7034
7149
|
tableName,
|
|
@@ -7037,7 +7152,8 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7037
7152
|
write: (tx, values) => runInsert(tx, [values]),
|
|
7038
7153
|
context
|
|
7039
7154
|
}) : await runInsert(executor, input);
|
|
7040
|
-
await after(
|
|
7155
|
+
await after(written);
|
|
7156
|
+
const result = output(written);
|
|
7041
7157
|
if (single && !result[0]) {
|
|
7042
7158
|
if (!conflictDoNothing) throw drizzleError("The insert returned no row.", { code: "DRIZZLE_NO_ROW_RETURNED" });
|
|
7043
7159
|
return;
|
|
@@ -7073,7 +7189,7 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7073
7189
|
txCtx,
|
|
7074
7190
|
policies,
|
|
7075
7191
|
args: queryArgs,
|
|
7076
|
-
run: async ({ executor, args, context, info, before, after }) => {
|
|
7192
|
+
run: async ({ executor, args, context, info, before, after, returning: withHookReturning, output }) => {
|
|
7077
7193
|
const supplied = single ? [args.values] : args.values;
|
|
7078
7194
|
if (!supplied.length) throw drizzleError("No values were provided!", { code: "DRIZZLE_NO_VALUES" });
|
|
7079
7195
|
await before();
|
|
@@ -7095,7 +7211,7 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7095
7211
|
scope,
|
|
7096
7212
|
defaultOrderBy: policies?.defaultOrderBy
|
|
7097
7213
|
});
|
|
7098
|
-
const returning = nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns;
|
|
7214
|
+
const returning = withHookReturning(nestedEntries ? nested.withJoinColumns(tableName, mergedOps(nestedEntries), { ...columns }, table) : columns);
|
|
7099
7215
|
const runUpsert = async (target, values) => {
|
|
7100
7216
|
const plan = resolveConflictPlan({
|
|
7101
7217
|
table,
|
|
@@ -7116,7 +7232,7 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7116
7232
|
});
|
|
7117
7233
|
return await query;
|
|
7118
7234
|
};
|
|
7119
|
-
const
|
|
7235
|
+
const written = nestedEntries ? await writeWithNestedOps({
|
|
7120
7236
|
executor,
|
|
7121
7237
|
runtime: nested,
|
|
7122
7238
|
tableName,
|
|
@@ -7125,7 +7241,8 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7125
7241
|
write: (tx, values) => runUpsert(tx, [values]),
|
|
7126
7242
|
context
|
|
7127
7243
|
}) : await runUpsert(executor, input);
|
|
7128
|
-
await after(
|
|
7244
|
+
await after(written);
|
|
7245
|
+
const result = output(written);
|
|
7129
7246
|
if (single && !result[0]) return;
|
|
7130
7247
|
const enriched = await withEagerRelations(executor, tableName, result, pkNames, withParams, hasRelations);
|
|
7131
7248
|
return single ? remapToGraphQLSingleOutput(enriched[0], tableName, table, relationMap) : remapToGraphQLArrayOutput(enriched, tableName, table, relationMap);
|
|
@@ -7149,7 +7266,7 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7149
7266
|
txCtx,
|
|
7150
7267
|
policies,
|
|
7151
7268
|
args: queryArgs,
|
|
7152
|
-
run: async ({ executor, args, context, info, before, after }) => {
|
|
7269
|
+
run: async ({ executor, args, context, info, before, after, returning: withHookReturning, output }) => {
|
|
7153
7270
|
const { where, set } = args;
|
|
7154
7271
|
const scope = policies?.scope?.(context);
|
|
7155
7272
|
await before();
|
|
@@ -7180,14 +7297,14 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7180
7297
|
required: single || requireWhere
|
|
7181
7298
|
});
|
|
7182
7299
|
if (single) await assertSingleMatch(executor, table, filters);
|
|
7183
|
-
const returning = nestedOps ? nested.withJoinColumns(tableName, nestedOps, { ...columns }, table) : columns;
|
|
7300
|
+
const returning = withHookReturning(nestedOps ? nested.withJoinColumns(tableName, nestedOps, { ...columns }, table) : columns);
|
|
7184
7301
|
const runUpdate = async (target, values) => {
|
|
7185
7302
|
const writes = Object.keys(values).length > 0;
|
|
7186
7303
|
let query = writes ? target.update(table).set(values) : target.select(returning).from(table);
|
|
7187
7304
|
if (filters) query = query.where(filters);
|
|
7188
7305
|
return await (writes ? query.returning(returning) : query);
|
|
7189
7306
|
};
|
|
7190
|
-
const
|
|
7307
|
+
const written = nestedOps ? await updateWithNestedOps({
|
|
7191
7308
|
executor,
|
|
7192
7309
|
runtime: nested,
|
|
7193
7310
|
tableName,
|
|
@@ -7197,7 +7314,8 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7197
7314
|
write: runUpdate,
|
|
7198
7315
|
context
|
|
7199
7316
|
}) : await runUpdate(executor, input);
|
|
7200
|
-
await after(
|
|
7317
|
+
await after(written);
|
|
7318
|
+
const result = output(written);
|
|
7201
7319
|
if (single && result.length > 1) throw drizzleError("'where' matched more than one row!", { code: "DRIZZLE_MULTI_ROW_MATCH" });
|
|
7202
7320
|
if (single && !result[0]) return;
|
|
7203
7321
|
const enriched = await withEagerRelations(executor, tableName, result, pkNames, withParams, hasRelations);
|
|
@@ -7237,7 +7355,7 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7237
7355
|
txCtx,
|
|
7238
7356
|
policies,
|
|
7239
7357
|
args: queryArgs,
|
|
7240
|
-
run: async ({ executor, args, context, info, before, after }) => {
|
|
7358
|
+
run: async ({ executor, args, context, info, before, after, returning: withHookReturning, output }) => {
|
|
7241
7359
|
const { where } = args;
|
|
7242
7360
|
const hard = canHardDelete && args.hard === true;
|
|
7243
7361
|
const scope = policies?.scope?.(context);
|
|
@@ -7257,9 +7375,10 @@ const buildWriteResolvers = (primaryKeyPropNames) => {
|
|
|
7257
7375
|
if (single) await assertSingleMatch(executor, table, filters);
|
|
7258
7376
|
let query = softDelete && !hard ? executor.update(table).set({ [softDelete.columnName]: restore ? softDelete.writeRestored : softDelete.writeDeleted() }) : executor.delete(table);
|
|
7259
7377
|
if (filters) query = query.where(filters);
|
|
7260
|
-
query = query.returning(columns);
|
|
7261
|
-
const
|
|
7262
|
-
await after(
|
|
7378
|
+
query = query.returning(withHookReturning(columns));
|
|
7379
|
+
const written = await query;
|
|
7380
|
+
await after(written);
|
|
7381
|
+
const result = output(written);
|
|
7263
7382
|
if (single && result.length > 1) throw drizzleError("'where' matched more than one row!", { code: "DRIZZLE_MULTI_ROW_MATCH" });
|
|
7264
7383
|
if (single) return result[0] ? remapToGraphQLSingleOutput(result[0], tableName, table) : void 0;
|
|
7265
7384
|
return remapToGraphQLArrayOutput(result, tableName, table);
|
|
@@ -7648,7 +7767,7 @@ const createUpdateManyGenerator = (primaryKeyPropNames, runBatch = runUpdateMany
|
|
|
7648
7767
|
txCtx,
|
|
7649
7768
|
policies,
|
|
7650
7769
|
args: queryArgs,
|
|
7651
|
-
run: async ({ executor, args, context, info, before, after }) => {
|
|
7770
|
+
run: async ({ executor, args, context, info, before, after, returning: withHookReturning, output: withoutHookColumns }) => {
|
|
7652
7771
|
const { updates } = args;
|
|
7653
7772
|
if (!updates.length) throw drizzleError("No updates were provided!", { code: "DRIZZLE_NO_VALUES" });
|
|
7654
7773
|
await before();
|
|
@@ -7679,7 +7798,7 @@ const createUpdateManyGenerator = (primaryKeyPropNames, runBatch = runUpdateMany
|
|
|
7679
7798
|
};
|
|
7680
7799
|
});
|
|
7681
7800
|
const anyNested = entries.some((entry) => entry.ops);
|
|
7682
|
-
const returning = anyNested ? nested.withJoinColumns(tableName, mergedOps(entries.map((entry) => ({ ops: entry.ops ?? {} }))), { ...columns }, table) : columns;
|
|
7801
|
+
const returning = withHookReturning(anyNested ? nested.withJoinColumns(tableName, mergedOps(entries.map((entry) => ({ ops: entry.ops ?? {} }))), { ...columns }, table) : columns);
|
|
7683
7802
|
const perEntry = await runBatch({
|
|
7684
7803
|
executor,
|
|
7685
7804
|
entries,
|
|
@@ -7690,8 +7809,9 @@ const createUpdateManyGenerator = (primaryKeyPropNames, runBatch = runUpdateMany
|
|
|
7690
7809
|
tableName,
|
|
7691
7810
|
context
|
|
7692
7811
|
});
|
|
7693
|
-
const
|
|
7694
|
-
await after(
|
|
7812
|
+
const written = perEntry.flat();
|
|
7813
|
+
await after(written);
|
|
7814
|
+
const flatRows = withoutHookColumns(written);
|
|
7695
7815
|
const enriched = await withEagerRelations(executor, tableName, flatRows, pkNames, withParams, hasRelations);
|
|
7696
7816
|
const output = [];
|
|
7697
7817
|
let offset = 0;
|