@vantreeseba/drizzle-graphql 5.3.0 → 5.4.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.d.cts CHANGED
@@ -233,6 +233,17 @@ type UpdateArgs<TTable extends Table> = Partial<{
233
233
  set: GetRemappedTableUpdateDataType<TTable>;
234
234
  where?: Filters<TTable>;
235
235
  }>;
236
+ /**
237
+ * One entry of an `update<Table>Many` mutation: the rows `where` matches get this
238
+ * entry's `set` applied. An omitted `where` matches every row, same as `update<Table>`.
239
+ */
240
+ type UpdateManyEntry<TTable extends Table> = {
241
+ where?: Filters<TTable>;
242
+ set: GetRemappedTableUpdateDataType<TTable>;
243
+ };
244
+ type UpdateManyArgs<TTable extends Table> = {
245
+ updates: Array<UpdateManyEntry<TTable>>;
246
+ };
236
247
  /**
237
248
  * The `onConflict` argument of the generated upsert mutations.
238
249
  *
@@ -272,6 +283,13 @@ type InsertResolver<TTable extends Table, IsReturnless extends boolean> = (sourc
272
283
  /** Resolver for `create<Table>`: an array of rows in, an array of rows out. */
273
284
  type InsertArrResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: Partial<InsertArgs<TTable, false>>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? Array<GetRemappedTableDataType<TTable>> : MutationReturnlessResult>;
274
285
  type UpdateResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: UpdateArgs<TTable>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
286
+ /**
287
+ * Resolver for `update<Table>Many`: per-entry `set`/`where` pairs applied in input order
288
+ * inside one transaction. Where the dialect returns rows, the result holds each entry's
289
+ * updated rows in entry order, with `null` standing in for an entry whose `where`
290
+ * matched no rows.
291
+ */
292
+ type UpdateManyResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: UpdateManyArgs<TTable>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? Array<GetRemappedTableDataType<TTable> | null> : MutationReturnlessResult>;
275
293
  /**
276
294
  * Resolver for `update<Table>Single`: `where` required, the single (nullable) affected row
277
295
  * out. Throws before writing anything when `where` matches more than one row.
@@ -403,6 +421,16 @@ type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends
403
421
  };
404
422
  resolve: UpdateResolver<TSchemaTables[TName], IsReturnless>;
405
423
  } : never;
424
+ } & {
425
+ [TName in keyof TSchemaTables as TName extends string ? `update${Capitalize<TName>}Many` : never]: TName extends string ? {
426
+ type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<TOutputs[`${Capitalize<TName>}Item`]>>;
427
+ args: {
428
+ updates: {
429
+ type: GraphQLNonNull<GraphQLList<GraphQLNonNull<TInputs[`${Capitalize<TName>}UpdateManyInput`]>>>;
430
+ };
431
+ };
432
+ resolve: UpdateManyResolver<TSchemaTables[TName], IsReturnless>;
433
+ } : never;
406
434
  } & {
407
435
  [TName in keyof TSchemaTables as TName extends string ? `update${Capitalize<TName>}Single` : never]: TName extends string ? {
408
436
  type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[`${Capitalize<TName>}Item`];
@@ -441,6 +469,8 @@ type GeneratedInputs<TSchema extends Record<string, Table>> = {
441
469
  [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}InsertInput` : never]: GraphQLInputObjectType;
442
470
  } & {
443
471
  [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}UpdateInput` : never]: GraphQLInputObjectType;
472
+ } & {
473
+ [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}UpdateManyInput` : never]: GraphQLInputObjectType;
444
474
  } & {
445
475
  [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}OrderBy` : never]: GraphQLInputObjectType;
446
476
  } & {
@@ -496,6 +526,14 @@ type SchemaFeatures = {
496
526
  insert?: boolean;
497
527
  /** `update<Table>` / `update<Table>Single` mutations. @default true */
498
528
  update?: boolean;
529
+ /**
530
+ * `update<Table>Many` mutations — batch update with a per-entry `set` and `where`,
531
+ * executed inside one transaction. Only generated when `update` is also enabled,
532
+ * since the entries reuse the update `set` input.
533
+ *
534
+ * @default true
535
+ */
536
+ updateMany?: boolean;
499
537
  /** `delete<Table>` / `delete<Table>Single` mutations. @default true */
500
538
  delete?: boolean;
501
539
  /**
@@ -745,4 +783,4 @@ declare const GraphQLDecimalString: GraphQLScalarType<string, string>;
745
783
 
746
784
  declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
747
785
 
748
- export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ComplexityConfig, type DeleteResolver, type DeleteSingleResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, GraphQLDecimalString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
786
+ export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ComplexityConfig, type DeleteResolver, type DeleteSingleResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, GraphQLDecimalString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
package/dist/index.d.ts CHANGED
@@ -233,6 +233,17 @@ type UpdateArgs<TTable extends Table> = Partial<{
233
233
  set: GetRemappedTableUpdateDataType<TTable>;
234
234
  where?: Filters<TTable>;
235
235
  }>;
236
+ /**
237
+ * One entry of an `update<Table>Many` mutation: the rows `where` matches get this
238
+ * entry's `set` applied. An omitted `where` matches every row, same as `update<Table>`.
239
+ */
240
+ type UpdateManyEntry<TTable extends Table> = {
241
+ where?: Filters<TTable>;
242
+ set: GetRemappedTableUpdateDataType<TTable>;
243
+ };
244
+ type UpdateManyArgs<TTable extends Table> = {
245
+ updates: Array<UpdateManyEntry<TTable>>;
246
+ };
236
247
  /**
237
248
  * The `onConflict` argument of the generated upsert mutations.
238
249
  *
@@ -272,6 +283,13 @@ type InsertResolver<TTable extends Table, IsReturnless extends boolean> = (sourc
272
283
  /** Resolver for `create<Table>`: an array of rows in, an array of rows out. */
273
284
  type InsertArrResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: Partial<InsertArgs<TTable, false>>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? Array<GetRemappedTableDataType<TTable>> : MutationReturnlessResult>;
274
285
  type UpdateResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: UpdateArgs<TTable>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? GetRemappedTableDataType<TTable> | undefined : MutationReturnlessResult>;
286
+ /**
287
+ * Resolver for `update<Table>Many`: per-entry `set`/`where` pairs applied in input order
288
+ * inside one transaction. Where the dialect returns rows, the result holds each entry's
289
+ * updated rows in entry order, with `null` standing in for an entry whose `where`
290
+ * matched no rows.
291
+ */
292
+ type UpdateManyResolver<TTable extends Table, IsReturnless extends boolean> = (source: any, args: UpdateManyArgs<TTable>, context: any, info: GraphQLResolveInfo) => Promise<IsReturnless extends false ? Array<GetRemappedTableDataType<TTable> | null> : MutationReturnlessResult>;
275
293
  /**
276
294
  * Resolver for `update<Table>Single`: `where` required, the single (nullable) affected row
277
295
  * out. Throws before writing anything when `where` matches more than one row.
@@ -403,6 +421,16 @@ type MutationsCore<TSchemaTables extends Record<string, Table>, TInputs extends
403
421
  };
404
422
  resolve: UpdateResolver<TSchemaTables[TName], IsReturnless>;
405
423
  } : never;
424
+ } & {
425
+ [TName in keyof TSchemaTables as TName extends string ? `update${Capitalize<TName>}Many` : never]: TName extends string ? {
426
+ type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : GraphQLNonNull<GraphQLList<TOutputs[`${Capitalize<TName>}Item`]>>;
427
+ args: {
428
+ updates: {
429
+ type: GraphQLNonNull<GraphQLList<GraphQLNonNull<TInputs[`${Capitalize<TName>}UpdateManyInput`]>>>;
430
+ };
431
+ };
432
+ resolve: UpdateManyResolver<TSchemaTables[TName], IsReturnless>;
433
+ } : never;
406
434
  } & {
407
435
  [TName in keyof TSchemaTables as TName extends string ? `update${Capitalize<TName>}Single` : never]: TName extends string ? {
408
436
  type: IsReturnless extends true ? TOutputs['MutationReturn'] extends GraphQLObjectType ? TOutputs['MutationReturn'] : never : TOutputs[`${Capitalize<TName>}Item`];
@@ -441,6 +469,8 @@ type GeneratedInputs<TSchema extends Record<string, Table>> = {
441
469
  [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}InsertInput` : never]: GraphQLInputObjectType;
442
470
  } & {
443
471
  [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}UpdateInput` : never]: GraphQLInputObjectType;
472
+ } & {
473
+ [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}UpdateManyInput` : never]: GraphQLInputObjectType;
444
474
  } & {
445
475
  [TName in keyof TSchema as TName extends string ? `${Capitalize<TName>}OrderBy` : never]: GraphQLInputObjectType;
446
476
  } & {
@@ -496,6 +526,14 @@ type SchemaFeatures = {
496
526
  insert?: boolean;
497
527
  /** `update<Table>` / `update<Table>Single` mutations. @default true */
498
528
  update?: boolean;
529
+ /**
530
+ * `update<Table>Many` mutations — batch update with a per-entry `set` and `where`,
531
+ * executed inside one transaction. Only generated when `update` is also enabled,
532
+ * since the entries reuse the update `set` input.
533
+ *
534
+ * @default true
535
+ */
536
+ updateMany?: boolean;
499
537
  /** `delete<Table>` / `delete<Table>Single` mutations. @default true */
500
538
  delete?: boolean;
501
539
  /**
@@ -745,4 +783,4 @@ declare const GraphQLDecimalString: GraphQLScalarType<string, string>;
745
783
 
746
784
  declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
747
785
 
748
- export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ComplexityConfig, type DeleteResolver, type DeleteSingleResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, GraphQLDecimalString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
786
+ export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ComplexityConfig, type DeleteResolver, type DeleteSingleResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, GraphQLDecimalString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateManyArgs, type UpdateManyEntry, type UpdateManyResolver, type UpdateResolver, type UpdateSingleResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
package/dist/index.js CHANGED
@@ -2251,6 +2251,7 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
2251
2251
  const upsertArrayFieldName = `${upsertPrefix}${mapped ? capitalize(mapped.plural) : capitalize(tableName)}`;
2252
2252
  const upsertSingleFieldName = mapped ? `${upsertPrefix}${capitalize(mapped.singular)}` : `${upsertPrefix}${capitalize(tableName)}${suffixes.single}`;
2253
2253
  const updateFieldName = `${prefixes.update}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
2254
+ const updateManyFieldName = `${prefixes.update}${mapped ? capitalize(mapped.plural) : capitalize(tableName)}Many`;
2254
2255
  const deleteFieldName = `${prefixes.delete}${mapped ? capitalize(mapped.singular) : capitalize(tableName)}`;
2255
2256
  const writeSingleSuffix = suffixes.single === "" ? "Single" : suffixes.single;
2256
2257
  const updateSingleFieldName = `${updateFieldName}${writeSingleSuffix}`;
@@ -2266,11 +2267,28 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
2266
2267
  upsertArrayFieldName,
2267
2268
  upsertSingleFieldName,
2268
2269
  updateFieldName,
2270
+ updateManyFieldName,
2269
2271
  updateSingleFieldName,
2270
2272
  deleteFieldName,
2271
2273
  deleteSingleFieldName
2272
2274
  };
2273
2275
  };
2276
+ var generateUpdateManyInput = (params) => {
2277
+ const { typeName, updatePrefix, updateInput, tableFilters } = params;
2278
+ return new GraphQLInputObjectType2({
2279
+ name: `${capitalize(updatePrefix)}${typeName}ManyInput`,
2280
+ description: `One entry of a batch update of ${typeName}: the rows \`where\` matches get this entry's \`set\` applied.`,
2281
+ fields: {
2282
+ where: {
2283
+ type: tableFilters,
2284
+ description: "Rows this entry updates. An omitted filter updates every row."
2285
+ },
2286
+ set: {
2287
+ type: new GraphQLNonNull2(updateInput)
2288
+ }
2289
+ }
2290
+ });
2291
+ };
2274
2292
  var extractRequiredFilters = (table, tableName, where, fieldName, relationCtx) => {
2275
2293
  const filters = where ? extractFilters(table, tableName, where, relationCtx) : void 0;
2276
2294
  if (!filters) {
@@ -3151,6 +3169,48 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, sing
3151
3169
  args: queryArgs
3152
3170
  };
3153
3171
  };
3172
+ var generateUpdateMany = (db, tableName, table, updateManyInput, fieldName, filterCtx) => {
3173
+ const queryArgs = {
3174
+ updates: {
3175
+ type: new GraphQLNonNull4(new GraphQLList4(new GraphQLNonNull4(updateManyInput)))
3176
+ }
3177
+ };
3178
+ return {
3179
+ name: fieldName,
3180
+ resolver: async (_source, args, context, _info) => {
3181
+ try {
3182
+ const { updates } = args;
3183
+ if (!updates.length) {
3184
+ throw new GraphQLError5("No updates were provided!");
3185
+ }
3186
+ const entries = updates.map(({ where, set }) => {
3187
+ const input = remapFromGraphQLSingleInput(set, table);
3188
+ if (!Object.keys(input).length) {
3189
+ throw new GraphQLError5("Unable to update with no values specified!");
3190
+ }
3191
+ return {
3192
+ set: input,
3193
+ filters: where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
3194
+ };
3195
+ });
3196
+ const executor = resolveExecutor(db, context);
3197
+ await executor.transaction(async (tx) => {
3198
+ for (const entry of entries) {
3199
+ let query = tx.update(table).set(entry.set);
3200
+ if (entry.filters) {
3201
+ query = query.where(entry.filters);
3202
+ }
3203
+ await query;
3204
+ }
3205
+ });
3206
+ return { isSuccess: true };
3207
+ } catch (e) {
3208
+ throw toGraphQLError(e);
3209
+ }
3210
+ },
3211
+ args: queryArgs
3212
+ };
3213
+ };
3154
3214
  var generateDelete = (db, tableName, table, filterArgs, fieldName, single, requireWhere, filterCtx) => {
3155
3215
  const queryArgs = {
3156
3216
  where: {
@@ -3258,6 +3318,7 @@ var generateSchemaData = (db, schema, relations, options) => {
3258
3318
  upsertArrayFieldName,
3259
3319
  upsertSingleFieldName,
3260
3320
  updateFieldName,
3321
+ updateManyFieldName,
3261
3322
  updateSingleFieldName,
3262
3323
  deleteFieldName,
3263
3324
  deleteSingleFieldName
@@ -3320,6 +3381,15 @@ var generateSchemaData = (db, schema, relations, options) => {
3320
3381
  features.requireWhere,
3321
3382
  filterCtx
3322
3383
  ) : void 0;
3384
+ const updateManyInput = features.update && features.updateMany ? generateUpdateManyInput({ typeName, updatePrefix: prefixes.update, updateInput, tableFilters }) : void 0;
3385
+ const updateManyGenerated = updateManyInput ? generateUpdateMany(
3386
+ db,
3387
+ tableName,
3388
+ schema[tableName],
3389
+ updateManyInput,
3390
+ updateManyFieldName,
3391
+ filterCtx
3392
+ ) : void 0;
3323
3393
  const deleteGenerated = features.delete ? generateDelete(
3324
3394
  db,
3325
3395
  tableName,
@@ -3397,6 +3467,7 @@ var generateSchemaData = (db, schema, relations, options) => {
3397
3467
  upsertArrGenerated,
3398
3468
  upsertSingleGenerated,
3399
3469
  updateGenerated,
3470
+ updateManyGenerated,
3400
3471
  updateSingleGenerated,
3401
3472
  deleteGenerated,
3402
3473
  deleteSingleGenerated
@@ -3414,6 +3485,7 @@ var generateSchemaData = (db, schema, relations, options) => {
3414
3485
  ...features.insert || onConflictInput ? [insertInput] : [],
3415
3486
  ...onConflictInput ? [onConflictInput] : [],
3416
3487
  ...features.update ? [updateInput] : [],
3488
+ ...updateManyInput ? [updateManyInput] : [],
3417
3489
  tableFilters,
3418
3490
  tableOrder
3419
3491
  ];
@@ -3837,6 +3909,78 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
3837
3909
  args: queryArgs
3838
3910
  };
3839
3911
  };
3912
+ var generateUpdateMany2 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx) => {
3913
+ const queryArgs = {
3914
+ updates: {
3915
+ type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(updateManyInput)))
3916
+ }
3917
+ };
3918
+ const pkNames = pgPrimaryKeyPropNames(table);
3919
+ return {
3920
+ name: fieldName,
3921
+ resolver: async (_source, args, context, info) => {
3922
+ try {
3923
+ const { updates } = args;
3924
+ if (!updates.length) {
3925
+ throw new GraphQLError6("No updates were provided!");
3926
+ }
3927
+ const parsedInfo = parseResolveInfo3(info, {
3928
+ deep: true
3929
+ });
3930
+ const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
3931
+ relationMap,
3932
+ tables,
3933
+ tableName,
3934
+ typeName,
3935
+ typeNameMapper,
3936
+ table,
3937
+ pkNames,
3938
+ parsedInfo
3939
+ });
3940
+ const entries = updates.map(({ where, set }) => {
3941
+ const input = remapFromGraphQLSingleInput(set, table);
3942
+ if (!Object.keys(input).length) {
3943
+ throw new GraphQLError6("Unable to update with no values specified!");
3944
+ }
3945
+ return {
3946
+ set: input,
3947
+ filters: where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
3948
+ };
3949
+ });
3950
+ const executor = resolveExecutor(db, context);
3951
+ const perEntry = await executor.transaction(async (tx) => {
3952
+ const results = [];
3953
+ for (const entry of entries) {
3954
+ let query = tx.update(table).set(entry.set);
3955
+ if (entry.filters) {
3956
+ query = query.where(entry.filters);
3957
+ }
3958
+ results.push(await query.returning(columns));
3959
+ }
3960
+ return results;
3961
+ });
3962
+ const flatRows = perEntry.flat();
3963
+ const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, flatRows, pkNames, withParams) : flatRows;
3964
+ const output = [];
3965
+ let offset = 0;
3966
+ for (const rows of perEntry) {
3967
+ if (!rows.length) {
3968
+ output.push(null);
3969
+ continue;
3970
+ }
3971
+ for (let i = 0; i < rows.length; i++) {
3972
+ output.push(remapToGraphQLSingleOutput(enriched[offset + i], tableName, table, relationMap));
3973
+ }
3974
+ offset += rows.length;
3975
+ }
3976
+ return output;
3977
+ } catch (e) {
3978
+ throw toGraphQLError(e);
3979
+ }
3980
+ },
3981
+ args: queryArgs
3982
+ };
3983
+ };
3840
3984
  var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
3841
3985
  const queryArgs = {
3842
3986
  where: {
@@ -3955,6 +4099,7 @@ function generateSchemaData2(db, schema, relations, options) {
3955
4099
  upsertArrayFieldName,
3956
4100
  upsertSingleFieldName,
3957
4101
  updateFieldName,
4102
+ updateManyFieldName,
3958
4103
  updateSingleFieldName,
3959
4104
  deleteFieldName,
3960
4105
  deleteSingleFieldName
@@ -4076,6 +4221,19 @@ function generateSchemaData2(db, schema, relations, options) {
4076
4221
  typeNameMapper,
4077
4222
  filterCtx
4078
4223
  ) : void 0;
4224
+ const updateManyInput = features.update && features.updateMany ? generateUpdateManyInput({ typeName, updatePrefix: prefixes.update, updateInput, tableFilters }) : void 0;
4225
+ const updateManyGenerated = updateManyInput ? generateUpdateMany2(
4226
+ db,
4227
+ tableName,
4228
+ schema[tableName],
4229
+ tables,
4230
+ eagerRelations,
4231
+ updateManyInput,
4232
+ updateManyFieldName,
4233
+ typeName,
4234
+ typeNameMapper,
4235
+ filterCtx
4236
+ ) : void 0;
4079
4237
  const deleteGenerated = features.delete ? generateDelete2(
4080
4238
  db,
4081
4239
  tableName,
@@ -4186,6 +4344,14 @@ function generateSchemaData2(db, schema, relations, options) {
4186
4344
  resolve: updateGenerated.resolver
4187
4345
  };
4188
4346
  }
4347
+ if (updateManyGenerated) {
4348
+ mutations[updateManyGenerated.name] = {
4349
+ // Nullable items: a no-match entry yields `null` in its slot.
4350
+ type: new GraphQLNonNull5(new GraphQLList5(singleTableItemOutput)),
4351
+ args: updateManyGenerated.args,
4352
+ resolve: updateManyGenerated.resolver
4353
+ };
4354
+ }
4189
4355
  if (updateSingleGenerated) {
4190
4356
  mutations[updateSingleGenerated.name] = {
4191
4357
  type: singleTableItemOutput,
@@ -4212,6 +4378,7 @@ function generateSchemaData2(db, schema, relations, options) {
4212
4378
  ...features.insert || onConflictInput ? [insertInput] : [],
4213
4379
  ...onConflictInput ? [onConflictInput] : [],
4214
4380
  ...features.update ? [updateInput] : [],
4381
+ ...updateManyInput ? [updateManyInput] : [],
4215
4382
  tableFilters,
4216
4383
  tableOrder
4217
4384
  ];
@@ -4538,6 +4705,91 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
4538
4705
  args: queryArgs
4539
4706
  };
4540
4707
  };
4708
+ var generateUpdateMany3 = (db, tableName, table, tables, relationMap, updateManyInput, fieldName, typeName, typeNameMapper, filterCtx) => {
4709
+ const queryArgs = {
4710
+ updates: {
4711
+ type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(updateManyInput)))
4712
+ }
4713
+ };
4714
+ const pkNames = sqlitePrimaryKeyPropNames(table);
4715
+ return {
4716
+ name: fieldName,
4717
+ resolver: async (_source, args, context, info) => {
4718
+ try {
4719
+ const { updates } = args;
4720
+ if (!updates.length) {
4721
+ throw new GraphQLError7("No updates were provided!");
4722
+ }
4723
+ const parsedInfo = parseResolveInfo4(info, {
4724
+ deep: true
4725
+ });
4726
+ const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
4727
+ relationMap,
4728
+ tables,
4729
+ tableName,
4730
+ typeName,
4731
+ typeNameMapper,
4732
+ table,
4733
+ pkNames,
4734
+ parsedInfo
4735
+ });
4736
+ const entries = updates.map(({ where, set }) => {
4737
+ const input = remapFromGraphQLSingleInput(set, table);
4738
+ if (!Object.keys(input).length) {
4739
+ throw new GraphQLError7("Unable to update with no values specified!");
4740
+ }
4741
+ return {
4742
+ set: input,
4743
+ filters: where ? extractFilters(table, tableName, where, relationFilterCtx(filterCtx, tableName)) : void 0
4744
+ };
4745
+ });
4746
+ const runEntry = (tx, entry) => {
4747
+ let query = tx.update(table).set(entry.set);
4748
+ if (entry.filters) {
4749
+ query = query.where(entry.filters);
4750
+ }
4751
+ return query.returning(columns).all();
4752
+ };
4753
+ const executor = resolveExecutor(db, context);
4754
+ const perEntry = await executor.transaction((tx) => {
4755
+ const first = runEntry(tx, entries[0]);
4756
+ if (typeof first?.then === "function") {
4757
+ return (async () => {
4758
+ const results2 = [await first];
4759
+ for (let i = 1; i < entries.length; i++) {
4760
+ results2.push(await runEntry(tx, entries[i]));
4761
+ }
4762
+ return results2;
4763
+ })();
4764
+ }
4765
+ const results = [first];
4766
+ for (let i = 1; i < entries.length; i++) {
4767
+ results.push(runEntry(tx, entries[i]));
4768
+ }
4769
+ return results;
4770
+ });
4771
+ const flatRows = perEntry.flat();
4772
+ const enriched = hasRelations ? await eagerLoadMutationRelations(executor, tableName, flatRows, pkNames, withParams) : flatRows;
4773
+ const output = [];
4774
+ let offset = 0;
4775
+ for (const rows of perEntry) {
4776
+ if (!rows.length) {
4777
+ output.push(null);
4778
+ continue;
4779
+ }
4780
+ for (let i = 0; i < rows.length; i++) {
4781
+ output.push(remapToGraphQLSingleOutput(enriched[offset + i], tableName, table, relationMap));
4782
+ }
4783
+ offset += rows.length;
4784
+ }
4785
+ return output;
4786
+ } catch (e) {
4787
+ throw toGraphQLError(e);
4788
+ }
4789
+ },
4790
+ args: queryArgs
4791
+ };
4792
+ };
4541
4793
  var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, single, requireWhere, filterCtx, selectionCtx) => {
4542
4794
  const queryArgs = {
4543
4795
  where: {
@@ -4657,6 +4909,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
4657
4909
  upsertArrayFieldName,
4658
4910
  upsertSingleFieldName,
4659
4911
  updateFieldName,
4912
+ updateManyFieldName,
4660
4913
  updateSingleFieldName,
4661
4914
  deleteFieldName,
4662
4915
  deleteSingleFieldName
@@ -4778,6 +5031,19 @@ var generateSchemaData3 = (db, schema, relations, options) => {
4778
5031
  typeNameMapper,
4779
5032
  filterCtx
4780
5033
  ) : void 0;
5034
+ const updateManyInput = features.update && features.updateMany ? generateUpdateManyInput({ typeName, updatePrefix: prefixes.update, updateInput, tableFilters }) : void 0;
5035
+ const updateManyGenerated = updateManyInput ? generateUpdateMany3(
5036
+ db,
5037
+ tableName,
5038
+ schema[tableName],
5039
+ tables,
5040
+ eagerRelations,
5041
+ updateManyInput,
5042
+ updateManyFieldName,
5043
+ typeName,
5044
+ typeNameMapper,
5045
+ filterCtx
5046
+ ) : void 0;
4781
5047
  const deleteGenerated = features.delete ? generateDelete3(
4782
5048
  db,
4783
5049
  tableName,
@@ -4888,6 +5154,14 @@ var generateSchemaData3 = (db, schema, relations, options) => {
4888
5154
  resolve: updateGenerated.resolver
4889
5155
  };
4890
5156
  }
5157
+ if (updateManyGenerated) {
5158
+ mutations[updateManyGenerated.name] = {
5159
+ // Nullable items: a no-match entry yields `null` in its slot.
5160
+ type: new GraphQLNonNull6(new GraphQLList6(singleTableItemOutput)),
5161
+ args: updateManyGenerated.args,
5162
+ resolve: updateManyGenerated.resolver
5163
+ };
5164
+ }
4891
5165
  if (updateSingleGenerated) {
4892
5166
  mutations[updateSingleGenerated.name] = {
4893
5167
  type: singleTableItemOutput,
@@ -4914,6 +5188,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
4914
5188
  ...features.insert || onConflictInput ? [insertInput] : [],
4915
5189
  ...onConflictInput ? [onConflictInput] : [],
4916
5190
  ...features.update ? [updateInput] : [],
5191
+ ...updateManyInput ? [updateManyInput] : [],
4917
5192
  tableFilters,
4918
5193
  tableOrder
4919
5194
  ];
@@ -4976,6 +5251,7 @@ var buildSchema = (db, config) => {
4976
5251
  distinct: config?.features?.distinct ?? true,
4977
5252
  insert: config?.features?.insert ?? true,
4978
5253
  update: config?.features?.update ?? true,
5254
+ updateMany: config?.features?.updateMany ?? true,
4979
5255
  delete: config?.features?.delete ?? true,
4980
5256
  upsert: config?.features?.upsert ?? false,
4981
5257
  requireWhere: config?.features?.requireWhere ?? false