@vantreeseba/drizzle-graphql 4.1.0 → 4.2.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
@@ -400,6 +400,13 @@ type GeneratedData<TDatabase extends AnyDrizzleDB<any>> = {
400
400
  type SchemaFeatures = {
401
401
  /** `<plural>Aggregate` root queries and the aggregate output types. @default true */
402
402
  aggregates?: boolean;
403
+ /**
404
+ * `<plural>GroupBy` root queries — the same aggregates, one row per group. Requires
405
+ * `aggregates`, whose output types the grouped result reuses.
406
+ *
407
+ * @default true
408
+ */
409
+ groupBy?: boolean;
403
410
  /** `<relation>Aggregate` fields on object types, for to-many relations. @default true */
404
411
  relationAggregates?: boolean;
405
412
  /** The `distinct` argument on list queries. @default true */
package/dist/index.d.ts CHANGED
@@ -400,6 +400,13 @@ type GeneratedData<TDatabase extends AnyDrizzleDB<any>> = {
400
400
  type SchemaFeatures = {
401
401
  /** `<plural>Aggregate` root queries and the aggregate output types. @default true */
402
402
  aggregates?: boolean;
403
+ /**
404
+ * `<plural>GroupBy` root queries — the same aggregates, one row per group. Requires
405
+ * `aggregates`, whose output types the grouped result reuses.
406
+ *
407
+ * @default true
408
+ */
409
+ groupBy?: boolean;
403
410
  /** `<relation>Aggregate` fields on object types, for to-many relations. @default true */
404
411
  relationAggregates?: boolean;
405
412
  /** The `distinct` argument on list queries. @default true */
package/dist/index.js CHANGED
@@ -1725,6 +1725,7 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
1725
1725
  const listFieldName = (mapped?.plural ?? uncapitalize(tableName)) + suffixes.list;
1726
1726
  const singleFieldName = mapped?.singular ?? uncapitalize(tableName) + suffixes.single;
1727
1727
  const aggregateFieldName = `${mapped?.plural ?? uncapitalize(tableName)}Aggregate`;
1728
+ const groupByFieldName = `${mapped?.plural ?? uncapitalize(tableName)}GroupBy`;
1728
1729
  const createArrayFieldName = `${prefixes.insert}${mapped ? capitalize(mapped.plural) : capitalize(tableName)}`;
1729
1730
  const createSingleFieldName = mapped ? `${prefixes.insert}${capitalize(mapped.singular)}` : `${prefixes.insert}${capitalize(tableName)}${suffixes.single}`;
1730
1731
  const upsertPrefix = prefixes.upsert ?? "upsert";
@@ -1737,6 +1738,7 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
1737
1738
  listFieldName,
1738
1739
  singleFieldName,
1739
1740
  aggregateFieldName,
1741
+ groupByFieldName,
1740
1742
  createArrayFieldName,
1741
1743
  createSingleFieldName,
1742
1744
  upsertArrayFieldName,
@@ -1892,7 +1894,7 @@ import { is as is4, One as One3 } from "drizzle-orm";
1892
1894
  import { getTableConfig, MySqlTable } from "drizzle-orm/mysql-core";
1893
1895
  import {
1894
1896
  GraphQLBoolean as GraphQLBoolean3,
1895
- GraphQLError as GraphQLError4,
1897
+ GraphQLError as GraphQLError5,
1896
1898
  GraphQLList as GraphQLList4,
1897
1899
  GraphQLNonNull as GraphQLNonNull4,
1898
1900
  GraphQLObjectType as GraphQLObjectType4
@@ -1905,15 +1907,23 @@ import {
1905
1907
  avg,
1906
1908
  count,
1907
1909
  countDistinct,
1910
+ eq as eq2,
1908
1911
  extractExtendedColumnType as extractExtendedColumnType2,
1909
1912
  getColumns as getColumns2,
1913
+ gt as gt2,
1914
+ gte as gte2,
1910
1915
  inArray as inArray2,
1916
+ lt as lt2,
1917
+ lte as lte2,
1911
1918
  max,
1912
1919
  min,
1920
+ ne as ne2,
1913
1921
  sum
1914
1922
  } from "drizzle-orm";
1915
1923
  import {
1924
+ GraphQLError as GraphQLError4,
1916
1925
  GraphQLFloat as GraphQLFloat2,
1926
+ GraphQLInputObjectType as GraphQLInputObjectType3,
1917
1927
  GraphQLInt as GraphQLInt3,
1918
1928
  GraphQLList as GraphQLList3,
1919
1929
  GraphQLNonNull as GraphQLNonNull3,
@@ -2034,9 +2044,9 @@ var aggregateTarget = (table, tableName, typeName) => {
2034
2044
  )
2035
2045
  };
2036
2046
  };
2037
- var parseAggregateRequest = (info, target) => {
2047
+ var parseAggregateRequest = (info, target, rootTypeName = `${target.typeName}Aggregate`) => {
2038
2048
  const parsedInfo = parseResolveInfo(info, { deep: true });
2039
- const selectionTree = parsedInfo.fieldsByTypeName[`${target.typeName}Aggregate`] ?? {};
2049
+ const selectionTree = parsedInfo.fieldsByTypeName[rootTypeName] ?? {};
2040
2050
  const request = {
2041
2051
  count: false,
2042
2052
  ops: { avg: [], sum: [], min: [], max: [], countNonNull: [], countDistinct: [] },
@@ -2174,6 +2184,184 @@ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filt
2174
2184
  return { type, resolve };
2175
2185
  };
2176
2186
  };
2187
+ var GROUP_COL = `group${SEP}`;
2188
+ var HAVING_OPS = { eq: eq2, ne: ne2, gt: gt2, gte: gte2, lt: lt2, lte: lte2 };
2189
+ var groupableColumns = (table, tableName) => {
2190
+ const { orderable } = classifyAggregateColumns(table, tableName);
2191
+ const groupable = { ...orderable };
2192
+ for (const [columnName, column] of Object.entries(getColumns2(table))) {
2193
+ if (groupable[columnName]) {
2194
+ continue;
2195
+ }
2196
+ const { type: dataType } = extractExtendedColumnType2(column);
2197
+ if (dataType !== "boolean") {
2198
+ continue;
2199
+ }
2200
+ groupable[columnName] = {
2201
+ column,
2202
+ converted: drizzleColumnToGraphQLType(column, columnName, tableName, true, false, false)
2203
+ };
2204
+ }
2205
+ return groupable;
2206
+ };
2207
+ var generateGroupByEnum = (table, tableName, typeName) => {
2208
+ const groupable = groupableColumns(table, tableName);
2209
+ return generateColumnEnum(
2210
+ table,
2211
+ `${typeName}GroupByColumn`,
2212
+ `Columns of ${typeName} that a query can group by`,
2213
+ (_column, columnName) => Boolean(groupable[columnName])
2214
+ );
2215
+ };
2216
+ var aggregateNumberFilter = new GraphQLInputObjectType3({
2217
+ name: "AggregateNumberFilter",
2218
+ description: "Compares an aggregated value. Several operators in one filter are ANDed together.",
2219
+ fields: Object.fromEntries(Object.keys(HAVING_OPS).map((op) => [op, { type: GraphQLFloat2 }]))
2220
+ });
2221
+ var generateHavingInput = (table, tableName, typeName) => {
2222
+ const { numeric, orderable, all } = classifyAggregateColumns(table, tableName);
2223
+ const fields = {
2224
+ count: { type: aggregateNumberFilter, description: "Filters groups by how many rows they contain" }
2225
+ };
2226
+ const opColumns = {
2227
+ avg: numeric,
2228
+ sum: numeric,
2229
+ min: numeric,
2230
+ max: numeric,
2231
+ countNonNull: all,
2232
+ countDistinct: orderable
2233
+ };
2234
+ for (const [op, columns] of Object.entries(opColumns)) {
2235
+ const columnNames = Object.keys(columns);
2236
+ if (!columnNames.length) {
2237
+ continue;
2238
+ }
2239
+ fields[op] = {
2240
+ type: new GraphQLInputObjectType3({
2241
+ name: `${typeName}${capitalize(op)}Having`,
2242
+ fields: Object.fromEntries(columnNames.map((columnName) => [columnName, { type: aggregateNumberFilter }]))
2243
+ })
2244
+ };
2245
+ }
2246
+ return new GraphQLInputObjectType3({
2247
+ name: `${typeName}Having`,
2248
+ description: `Filters ${typeName} groups by their aggregated values`,
2249
+ fields
2250
+ });
2251
+ };
2252
+ var generateGroupByType = (table, tableName, typeName, cacheCtx) => {
2253
+ const groupable = groupableColumns(table, tableName);
2254
+ if (!Object.keys(groupable).length) {
2255
+ return void 0;
2256
+ }
2257
+ const keysType = new GraphQLObjectType3({
2258
+ name: `${typeName}GroupKeys`,
2259
+ description: `The grouped column values of one ${typeName} group. A column the query did not group by is null.`,
2260
+ fields: Object.fromEntries(
2261
+ Object.entries(groupable).map(([columnName, { converted }]) => [
2262
+ columnName,
2263
+ { type: converted.type, description: converted.description }
2264
+ ])
2265
+ )
2266
+ });
2267
+ const aggregateType = generateAggregateTypes(table, tableName, typeName, cacheCtx);
2268
+ const aggregateFields = Object.fromEntries(
2269
+ Object.values(aggregateType.getFields()).map((field) => [
2270
+ field.name,
2271
+ { type: field.type, description: field.description ?? void 0 }
2272
+ ])
2273
+ );
2274
+ return new GraphQLObjectType3({
2275
+ name: `${typeName}GroupBy`,
2276
+ fields: { group: { type: new GraphQLNonNull3(keysType) }, ...aggregateFields }
2277
+ });
2278
+ };
2279
+ var havingComparisons = (expression, filter) => Object.entries(filter).filter(([op, value]) => value != null && op in HAVING_OPS).map(([op, value]) => HAVING_OPS[op](expression, value));
2280
+ var buildHavingCondition = (having, columns) => {
2281
+ if (!having) {
2282
+ return void 0;
2283
+ }
2284
+ const conditions = [];
2285
+ for (const [key, value] of Object.entries(having)) {
2286
+ if (value == null) {
2287
+ continue;
2288
+ }
2289
+ if (key === "count") {
2290
+ conditions.push(...havingComparisons(count(), value));
2291
+ continue;
2292
+ }
2293
+ if (!AGGREGATE_OPS.includes(key)) {
2294
+ continue;
2295
+ }
2296
+ for (const [columnName, filter] of Object.entries(value)) {
2297
+ const column = columns[columnName];
2298
+ if (!column || filter == null) {
2299
+ continue;
2300
+ }
2301
+ conditions.push(...havingComparisons(OP_FNS[key](column), filter));
2302
+ }
2303
+ }
2304
+ return conditions.length ? and2(...conditions) : void 0;
2305
+ };
2306
+ var generateGroupBy = (db, tableName, table, typeName, fieldName, filterArgs, groupByEnum, havingInput, filterCtx) => {
2307
+ const target = aggregateTarget(table, tableName, typeName);
2308
+ const groupable = groupableColumns(table, tableName);
2309
+ const columns = getColumns2(table);
2310
+ const rootTypeName = `${typeName}GroupBy`;
2311
+ const queryArgs = {
2312
+ groupBy: {
2313
+ type: new GraphQLNonNull3(new GraphQLList3(new GraphQLNonNull3(groupByEnum))),
2314
+ description: "Columns to group by. One result row per distinct combination of their values."
2315
+ },
2316
+ where: { type: filterArgs, description: "Filters the rows before they are grouped." },
2317
+ having: { type: havingInput, description: "Filters the groups after they are aggregated." }
2318
+ };
2319
+ return {
2320
+ name: fieldName,
2321
+ resolver: async (_source, args, context, info) => {
2322
+ try {
2323
+ const requestedKeys = [...new Set(args.groupBy ?? [])];
2324
+ if (!requestedKeys.length) {
2325
+ throw new GraphQLError4("At least one column to group by is required!");
2326
+ }
2327
+ const keyColumns = requestedKeys.map((columnName) => {
2328
+ const groupableColumn = groupable[columnName];
2329
+ if (!groupableColumn) {
2330
+ throw new GraphQLError4(`Cannot group ${typeName} by ${columnName}!`);
2331
+ }
2332
+ return [columnName, groupableColumn.column];
2333
+ });
2334
+ const request = parseAggregateRequest(info, target, rootTypeName);
2335
+ const selection = {
2336
+ ...Object.fromEntries(keyColumns.map(([columnName, column]) => [`${GROUP_COL}${columnName}`, column])),
2337
+ ...request.selection
2338
+ };
2339
+ let query = resolveExecutor(db, context).select(selection).from(table);
2340
+ if (args.where) {
2341
+ query = query.where(extractFilters(table, tableName, args.where, relationFilterCtx(filterCtx, tableName)));
2342
+ }
2343
+ query = query.groupBy(...keyColumns.map(([, column]) => column));
2344
+ const havingCondition = buildHavingCondition(args.having, columns);
2345
+ if (havingCondition) {
2346
+ query = query.having(havingCondition);
2347
+ }
2348
+ const rows = await query;
2349
+ return rows.map((row) => {
2350
+ const group = {};
2351
+ for (const [columnName, column] of keyColumns) {
2352
+ const value = row[`${GROUP_COL}${columnName}`];
2353
+ const decoded = typeof value === "string" && target.dateTimeColumns.has(columnName) ? parseDriverDateTime(value) : value;
2354
+ group[columnName] = value == null ? null : remapToGraphQLCore(columnName, decoded, tableName, column);
2355
+ }
2356
+ return { group, ...assembleAggregateRow(row, request, target) };
2357
+ });
2358
+ } catch (e) {
2359
+ throw toGraphQLError(e);
2360
+ }
2361
+ },
2362
+ args: queryArgs
2363
+ };
2364
+ };
2177
2365
 
2178
2366
  // src/util/builders/mysql.ts
2179
2367
  var generateSelectArray = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
@@ -2268,7 +2456,7 @@ var generateInsertArray = (db, _tableName, table, baseType, fieldName) => {
2268
2456
  try {
2269
2457
  const input = remapFromGraphQLArrayInput(args.values, table);
2270
2458
  if (!input.length) {
2271
- throw new GraphQLError4("No values were provided!");
2459
+ throw new GraphQLError5("No values were provided!");
2272
2460
  }
2273
2461
  await resolveExecutor(db, context).insert(table).values(input);
2274
2462
  return { isSuccess: true };
@@ -2316,7 +2504,7 @@ var generateUpsert = (db, table, baseType, onConflictType, fieldName, single) =>
2316
2504
  try {
2317
2505
  const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
2318
2506
  if (!input.length) {
2319
- throw new GraphQLError4("No values were provided!");
2507
+ throw new GraphQLError5("No values were provided!");
2320
2508
  }
2321
2509
  const plan = resolveConflictPlan({
2322
2510
  table,
@@ -2357,7 +2545,7 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
2357
2545
  const { where, set } = args;
2358
2546
  const input = remapFromGraphQLSingleInput(set, table);
2359
2547
  if (!Object.keys(input).length) {
2360
- throw new GraphQLError4("Unable to update with no values specified!");
2548
+ throw new GraphQLError5("Unable to update with no values specified!");
2361
2549
  }
2362
2550
  const executor = resolveExecutor(db, context);
2363
2551
  let query = executor.update(table).set(input);
@@ -2471,6 +2659,7 @@ var generateSchemaData = (db, schema, relations, options) => {
2471
2659
  listFieldName,
2472
2660
  singleFieldName,
2473
2661
  aggregateFieldName,
2662
+ groupByFieldName,
2474
2663
  createArrayFieldName,
2475
2664
  createSingleFieldName,
2476
2665
  upsertArrayFieldName,
@@ -2534,6 +2723,20 @@ var generateSchemaData = (db, schema, relations, options) => {
2534
2723
  tableFilters,
2535
2724
  filterCtx
2536
2725
  ) : void 0;
2726
+ const groupByType = features.aggregates && features.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
2727
+ const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
2728
+ const havingInput = groupByEnum ? generateHavingInput(schema[tableName], tableName, typeName) : void 0;
2729
+ const groupByGenerated = groupByType && groupByEnum && havingInput ? generateGroupBy(
2730
+ db,
2731
+ tableName,
2732
+ schema[tableName],
2733
+ typeName,
2734
+ groupByFieldName,
2735
+ tableFilters,
2736
+ groupByEnum,
2737
+ havingInput,
2738
+ filterCtx
2739
+ ) : void 0;
2537
2740
  queries[selectArrGenerated.name] = {
2538
2741
  type: selectArrOutput,
2539
2742
  args: selectArrGenerated.args,
@@ -2553,6 +2756,14 @@ var generateSchemaData = (db, schema, relations, options) => {
2553
2756
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
2554
2757
  };
2555
2758
  }
2759
+ if (groupByGenerated && groupByType) {
2760
+ queries[groupByGenerated.name] = {
2761
+ type: new GraphQLNonNull4(new GraphQLList4(new GraphQLNonNull4(groupByType))),
2762
+ args: groupByGenerated.args,
2763
+ resolve: groupByGenerated.resolver,
2764
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
2765
+ };
2766
+ }
2556
2767
  for (const generated of [
2557
2768
  insertArrGenerated,
2558
2769
  insertSingleGenerated,
@@ -2584,6 +2795,10 @@ var generateSchemaData = (db, schema, relations, options) => {
2584
2795
  if (aggregateType) {
2585
2796
  outputs[aggregateType.name] = aggregateType;
2586
2797
  }
2798
+ if (groupByType && havingInput) {
2799
+ outputs[groupByType.name] = groupByType;
2800
+ inputs[havingInput.name] = havingInput;
2801
+ }
2587
2802
  }
2588
2803
  const fieldResolvers = {};
2589
2804
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -2606,7 +2821,7 @@ var generateSchemaData = (db, schema, relations, options) => {
2606
2821
  import { is as is5, One as One4 } from "drizzle-orm";
2607
2822
  import { getTableConfig as getTableConfig2, PgTable } from "drizzle-orm/pg-core";
2608
2823
  import {
2609
- GraphQLError as GraphQLError5,
2824
+ GraphQLError as GraphQLError6,
2610
2825
  GraphQLList as GraphQLList5,
2611
2826
  GraphQLNonNull as GraphQLNonNull5
2612
2827
  } from "graphql";
@@ -2767,7 +2982,7 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
2767
2982
  try {
2768
2983
  const input = remapFromGraphQLArrayInput(args.values, table);
2769
2984
  if (!input.length) {
2770
- throw new GraphQLError5("No values were provided!");
2985
+ throw new GraphQLError6("No values were provided!");
2771
2986
  }
2772
2987
  const parsedInfo = parseResolveInfo3(info, {
2773
2988
  deep: true
@@ -2857,7 +3072,7 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
2857
3072
  try {
2858
3073
  const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
2859
3074
  if (!input.length) {
2860
- throw new GraphQLError5("No values were provided!");
3075
+ throw new GraphQLError6("No values were provided!");
2861
3076
  }
2862
3077
  const parsedInfo = parseResolveInfo3(info, { deep: true });
2863
3078
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -2926,7 +3141,7 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
2926
3141
  });
2927
3142
  const input = remapFromGraphQLSingleInput(set, table);
2928
3143
  if (!Object.keys(input).length) {
2929
- throw new GraphQLError5("Unable to update with no values specified!");
3144
+ throw new GraphQLError6("Unable to update with no values specified!");
2930
3145
  }
2931
3146
  const executor = resolveExecutor(db, context);
2932
3147
  let query = executor.update(table).set(input);
@@ -3047,6 +3262,7 @@ function generateSchemaData2(db, schema, relations, options) {
3047
3262
  listFieldName,
3048
3263
  singleFieldName,
3049
3264
  aggregateFieldName,
3265
+ groupByFieldName,
3050
3266
  createArrayFieldName,
3051
3267
  createSingleFieldName,
3052
3268
  upsertArrayFieldName,
@@ -3174,6 +3390,20 @@ function generateSchemaData2(db, schema, relations, options) {
3174
3390
  tableFilters,
3175
3391
  filterCtx
3176
3392
  ) : void 0;
3393
+ const groupByType = features.aggregates && features.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
3394
+ const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
3395
+ const havingInput = groupByEnum ? generateHavingInput(schema[tableName], tableName, typeName) : void 0;
3396
+ const groupByGenerated = groupByType && groupByEnum && havingInput ? generateGroupBy(
3397
+ db,
3398
+ tableName,
3399
+ schema[tableName],
3400
+ typeName,
3401
+ groupByFieldName,
3402
+ tableFilters,
3403
+ groupByEnum,
3404
+ havingInput,
3405
+ filterCtx
3406
+ ) : void 0;
3177
3407
  queries[selectArrGenerated.name] = {
3178
3408
  type: selectArrOutput,
3179
3409
  args: selectArrGenerated.args,
@@ -3193,6 +3423,14 @@ function generateSchemaData2(db, schema, relations, options) {
3193
3423
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
3194
3424
  };
3195
3425
  }
3426
+ if (groupByGenerated && groupByType) {
3427
+ queries[groupByGenerated.name] = {
3428
+ type: new GraphQLNonNull5(new GraphQLList5(new GraphQLNonNull5(groupByType))),
3429
+ args: groupByGenerated.args,
3430
+ resolve: groupByGenerated.resolver,
3431
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
3432
+ };
3433
+ }
3196
3434
  if (insertArrGenerated) {
3197
3435
  mutations[insertArrGenerated.name] = {
3198
3436
  type: arrTableItemOutput,
@@ -3251,6 +3489,10 @@ function generateSchemaData2(db, schema, relations, options) {
3251
3489
  if (aggregateType) {
3252
3490
  outputs[aggregateType.name] = aggregateType;
3253
3491
  }
3492
+ if (groupByType && havingInput) {
3493
+ outputs[groupByType.name] = groupByType;
3494
+ inputs[havingInput.name] = havingInput;
3495
+ }
3254
3496
  }
3255
3497
  const fieldResolvers = {};
3256
3498
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -3273,7 +3515,7 @@ function generateSchemaData2(db, schema, relations, options) {
3273
3515
  import { is as is6, One as One5 } from "drizzle-orm";
3274
3516
  import { getTableConfig as getTableConfig3, SQLiteTable } from "drizzle-orm/sqlite-core";
3275
3517
  import {
3276
- GraphQLError as GraphQLError6,
3518
+ GraphQLError as GraphQLError7,
3277
3519
  GraphQLList as GraphQLList6,
3278
3520
  GraphQLNonNull as GraphQLNonNull6
3279
3521
  } from "graphql";
@@ -3372,7 +3614,7 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
3372
3614
  try {
3373
3615
  const input = remapFromGraphQLArrayInput(args.values, table);
3374
3616
  if (!input.length) {
3375
- throw new GraphQLError6("No values were provided!");
3617
+ throw new GraphQLError7("No values were provided!");
3376
3618
  }
3377
3619
  const parsedInfo = parseResolveInfo4(info, {
3378
3620
  deep: true
@@ -3462,7 +3704,7 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
3462
3704
  try {
3463
3705
  const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
3464
3706
  if (!input.length) {
3465
- throw new GraphQLError6("No values were provided!");
3707
+ throw new GraphQLError7("No values were provided!");
3466
3708
  }
3467
3709
  const parsedInfo = parseResolveInfo4(info, { deep: true });
3468
3710
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -3531,7 +3773,7 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
3531
3773
  });
3532
3774
  const input = remapFromGraphQLSingleInput(set, table);
3533
3775
  if (!Object.keys(input).length) {
3534
- throw new GraphQLError6("Unable to update with no values specified!");
3776
+ throw new GraphQLError7("Unable to update with no values specified!");
3535
3777
  }
3536
3778
  const executor = resolveExecutor(db, context);
3537
3779
  let query = executor.update(table).set(input);
@@ -3653,6 +3895,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3653
3895
  listFieldName,
3654
3896
  singleFieldName,
3655
3897
  aggregateFieldName,
3898
+ groupByFieldName,
3656
3899
  createArrayFieldName,
3657
3900
  createSingleFieldName,
3658
3901
  upsertArrayFieldName,
@@ -3780,6 +4023,20 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3780
4023
  tableFilters,
3781
4024
  filterCtx
3782
4025
  ) : void 0;
4026
+ const groupByType = features.aggregates && features.groupBy ? generateGroupByType(schema[tableName], tableName, typeName, cacheCtx) : void 0;
4027
+ const groupByEnum = groupByType ? generateGroupByEnum(schema[tableName], tableName, typeName) : void 0;
4028
+ const havingInput = groupByEnum ? generateHavingInput(schema[tableName], tableName, typeName) : void 0;
4029
+ const groupByGenerated = groupByType && groupByEnum && havingInput ? generateGroupBy(
4030
+ db,
4031
+ tableName,
4032
+ schema[tableName],
4033
+ typeName,
4034
+ groupByFieldName,
4035
+ tableFilters,
4036
+ groupByEnum,
4037
+ havingInput,
4038
+ filterCtx
4039
+ ) : void 0;
3783
4040
  queries[selectArrGenerated.name] = {
3784
4041
  type: selectArrOutput,
3785
4042
  args: selectArrGenerated.args,
@@ -3799,6 +4056,14 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3799
4056
  ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
3800
4057
  };
3801
4058
  }
4059
+ if (groupByGenerated && groupByType) {
4060
+ queries[groupByGenerated.name] = {
4061
+ type: new GraphQLNonNull6(new GraphQLList6(new GraphQLNonNull6(groupByType))),
4062
+ args: groupByGenerated.args,
4063
+ resolve: groupByGenerated.resolver,
4064
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
4065
+ };
4066
+ }
3802
4067
  if (insertArrGenerated) {
3803
4068
  mutations[insertArrGenerated.name] = {
3804
4069
  type: arrTableItemOutput,
@@ -3857,6 +4122,10 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3857
4122
  if (aggregateType) {
3858
4123
  outputs[aggregateType.name] = aggregateType;
3859
4124
  }
4125
+ if (groupByType && havingInput) {
4126
+ outputs[groupByType.name] = groupByType;
4127
+ inputs[havingInput.name] = havingInput;
4128
+ }
3860
4129
  }
3861
4130
  const fieldResolvers = {};
3862
4131
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -3899,6 +4168,7 @@ var buildSchema = (db, config) => {
3899
4168
  const typeNameMapper = config?.typeNameMapper;
3900
4169
  const features = {
3901
4170
  aggregates: config?.features?.aggregates ?? true,
4171
+ groupBy: config?.features?.groupBy ?? true,
3902
4172
  relationAggregates: config?.features?.relationAggregates ?? true,
3903
4173
  distinct: config?.features?.distinct ?? true,
3904
4174
  insert: config?.features?.insert ?? true,