@vantreeseba/drizzle-graphql 4.0.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.js CHANGED
@@ -655,6 +655,12 @@ var createRelationResolverFactory = (db, tables, filterCtx) => ({ tableName, rel
655
655
  return loader.load(localValue);
656
656
  };
657
657
  };
658
+ var listFieldComplexity = (options) => ({ args, childComplexity }) => {
659
+ const limit = args["limit"];
660
+ const rows = typeof limit === "number" && limit > 0 ? limit : options.defaultListSize;
661
+ return rows * Math.max(childComplexity, 1);
662
+ };
663
+ var aggregateFieldComplexity = (options) => ({ childComplexity }) => options.aggregateCost + childComplexity;
658
664
  var AGGREGATE_FIELD_SUFFIX = "Aggregate";
659
665
  var relationAggregateJoinColumns = (tree, table, selectionCtx) => {
660
666
  const relations = selectionCtx?.relationMap[selectionCtx.tableName];
@@ -1076,7 +1082,8 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1076
1082
  offset: { type: GraphQLInt2 },
1077
1083
  limit: { type: GraphQLInt2 }
1078
1084
  },
1079
- resolve
1085
+ resolve,
1086
+ ...cacheCtx.complexity ? { extensions: { complexity: listFieldComplexity(cacheCtx.complexity) } } : {}
1080
1087
  }
1081
1088
  ]);
1082
1089
  const aggregateFieldName = `${relationName}Aggregate`;
@@ -1094,7 +1101,8 @@ var generateSelectFields = (tables, tableName, relationMap, fromTableName, fromR
1094
1101
  args: {
1095
1102
  where: { type: relSelectData.filters }
1096
1103
  },
1097
- resolve: relationAggregate.resolve
1104
+ resolve: relationAggregate.resolve,
1105
+ ...cacheCtx.complexity ? { extensions: { complexity: aggregateFieldComplexity(cacheCtx.complexity) } } : {}
1098
1106
  }
1099
1107
  ]);
1100
1108
  }
@@ -1717,6 +1725,7 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
1717
1725
  const listFieldName = (mapped?.plural ?? uncapitalize(tableName)) + suffixes.list;
1718
1726
  const singleFieldName = mapped?.singular ?? uncapitalize(tableName) + suffixes.single;
1719
1727
  const aggregateFieldName = `${mapped?.plural ?? uncapitalize(tableName)}Aggregate`;
1728
+ const groupByFieldName = `${mapped?.plural ?? uncapitalize(tableName)}GroupBy`;
1720
1729
  const createArrayFieldName = `${prefixes.insert}${mapped ? capitalize(mapped.plural) : capitalize(tableName)}`;
1721
1730
  const createSingleFieldName = mapped ? `${prefixes.insert}${capitalize(mapped.singular)}` : `${prefixes.insert}${capitalize(tableName)}${suffixes.single}`;
1722
1731
  const upsertPrefix = prefixes.upsert ?? "upsert";
@@ -1729,6 +1738,7 @@ var computeResolverFieldNames = (tableName, typeNameMapper, prefixes, suffixes)
1729
1738
  listFieldName,
1730
1739
  singleFieldName,
1731
1740
  aggregateFieldName,
1741
+ groupByFieldName,
1732
1742
  createArrayFieldName,
1733
1743
  createSingleFieldName,
1734
1744
  upsertArrayFieldName,
@@ -1884,7 +1894,7 @@ import { is as is4, One as One3 } from "drizzle-orm";
1884
1894
  import { getTableConfig, MySqlTable } from "drizzle-orm/mysql-core";
1885
1895
  import {
1886
1896
  GraphQLBoolean as GraphQLBoolean3,
1887
- GraphQLError as GraphQLError4,
1897
+ GraphQLError as GraphQLError5,
1888
1898
  GraphQLList as GraphQLList4,
1889
1899
  GraphQLNonNull as GraphQLNonNull4,
1890
1900
  GraphQLObjectType as GraphQLObjectType4
@@ -1897,15 +1907,23 @@ import {
1897
1907
  avg,
1898
1908
  count,
1899
1909
  countDistinct,
1910
+ eq as eq2,
1900
1911
  extractExtendedColumnType as extractExtendedColumnType2,
1901
1912
  getColumns as getColumns2,
1913
+ gt as gt2,
1914
+ gte as gte2,
1902
1915
  inArray as inArray2,
1916
+ lt as lt2,
1917
+ lte as lte2,
1903
1918
  max,
1904
1919
  min,
1920
+ ne as ne2,
1905
1921
  sum
1906
1922
  } from "drizzle-orm";
1907
1923
  import {
1924
+ GraphQLError as GraphQLError4,
1908
1925
  GraphQLFloat as GraphQLFloat2,
1926
+ GraphQLInputObjectType as GraphQLInputObjectType3,
1909
1927
  GraphQLInt as GraphQLInt3,
1910
1928
  GraphQLList as GraphQLList3,
1911
1929
  GraphQLNonNull as GraphQLNonNull3,
@@ -2026,9 +2044,9 @@ var aggregateTarget = (table, tableName, typeName) => {
2026
2044
  )
2027
2045
  };
2028
2046
  };
2029
- var parseAggregateRequest = (info, target) => {
2047
+ var parseAggregateRequest = (info, target, rootTypeName = `${target.typeName}Aggregate`) => {
2030
2048
  const parsedInfo = parseResolveInfo(info, { deep: true });
2031
- const selectionTree = parsedInfo.fieldsByTypeName[`${target.typeName}Aggregate`] ?? {};
2049
+ const selectionTree = parsedInfo.fieldsByTypeName[rootTypeName] ?? {};
2032
2050
  const request = {
2033
2051
  count: false,
2034
2052
  ops: { avg: [], sum: [], min: [], max: [], countNonNull: [], countDistinct: [] },
@@ -2166,6 +2184,184 @@ var createRelationAggregateFactory = (db, tables, cacheCtx, typeNameMapper, filt
2166
2184
  return { type, resolve };
2167
2185
  };
2168
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
+ };
2169
2365
 
2170
2366
  // src/util/builders/mysql.ts
2171
2367
  var generateSelectArray = (db, tableName, tables, relationMap, orderArgs, filterArgs, fieldName, typeName, typeNameMapper, filterCtx, distinctEnabled = true) => {
@@ -2260,7 +2456,7 @@ var generateInsertArray = (db, _tableName, table, baseType, fieldName) => {
2260
2456
  try {
2261
2457
  const input = remapFromGraphQLArrayInput(args.values, table);
2262
2458
  if (!input.length) {
2263
- throw new GraphQLError4("No values were provided!");
2459
+ throw new GraphQLError5("No values were provided!");
2264
2460
  }
2265
2461
  await resolveExecutor(db, context).insert(table).values(input);
2266
2462
  return { isSuccess: true };
@@ -2308,7 +2504,7 @@ var generateUpsert = (db, table, baseType, onConflictType, fieldName, single) =>
2308
2504
  try {
2309
2505
  const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
2310
2506
  if (!input.length) {
2311
- throw new GraphQLError4("No values were provided!");
2507
+ throw new GraphQLError5("No values were provided!");
2312
2508
  }
2313
2509
  const plan = resolveConflictPlan({
2314
2510
  table,
@@ -2349,7 +2545,7 @@ var generateUpdate = (db, tableName, table, setArgs, filterArgs, fieldName, filt
2349
2545
  const { where, set } = args;
2350
2546
  const input = remapFromGraphQLSingleInput(set, table);
2351
2547
  if (!Object.keys(input).length) {
2352
- throw new GraphQLError4("Unable to update with no values specified!");
2548
+ throw new GraphQLError5("Unable to update with no values specified!");
2353
2549
  }
2354
2550
  const executor = resolveExecutor(db, context);
2355
2551
  let query = executor.update(table).set(input);
@@ -2394,7 +2590,7 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) =>
2394
2590
  };
2395
2591
  var mysqlPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig);
2396
2592
  var generateSchemaData = (db, schema, relations, options) => {
2397
- const { relationsDepthLimit, prefixes, suffixes, typeNameMapper, shouldEagerLoad, features } = options;
2593
+ const { relationsDepthLimit, prefixes, suffixes, typeNameMapper, shouldEagerLoad, features, complexity } = options;
2398
2594
  const rawSchema = schema;
2399
2595
  const schemaEntries = Object.entries(rawSchema);
2400
2596
  const tableEntries = schemaEntries.filter(([_key, value]) => is4(value, MySqlTable));
@@ -2418,7 +2614,8 @@ var generateSchemaData = (db, schema, relations, options) => {
2418
2614
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
2419
2615
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
2420
2616
  listRelationFilterCache: /* @__PURE__ */ new Map(),
2421
- aggregateTypeCache: /* @__PURE__ */ new Map()
2617
+ aggregateTypeCache: /* @__PURE__ */ new Map(),
2618
+ complexity
2422
2619
  };
2423
2620
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
2424
2621
  const queries = {};
@@ -2462,6 +2659,7 @@ var generateSchemaData = (db, schema, relations, options) => {
2462
2659
  listFieldName,
2463
2660
  singleFieldName,
2464
2661
  aggregateFieldName,
2662
+ groupByFieldName,
2465
2663
  createArrayFieldName,
2466
2664
  createSingleFieldName,
2467
2665
  upsertArrayFieldName,
@@ -2525,10 +2723,25 @@ var generateSchemaData = (db, schema, relations, options) => {
2525
2723
  tableFilters,
2526
2724
  filterCtx
2527
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;
2528
2740
  queries[selectArrGenerated.name] = {
2529
2741
  type: selectArrOutput,
2530
2742
  args: selectArrGenerated.args,
2531
- resolve: selectArrGenerated.resolver
2743
+ resolve: selectArrGenerated.resolver,
2744
+ ...complexity ? { extensions: { complexity: listFieldComplexity(complexity) } } : {}
2532
2745
  };
2533
2746
  queries[selectSingleGenerated.name] = {
2534
2747
  type: selectSingleOutput,
@@ -2539,7 +2752,16 @@ var generateSchemaData = (db, schema, relations, options) => {
2539
2752
  queries[aggregateGenerated.name] = {
2540
2753
  type: new GraphQLNonNull4(aggregateType),
2541
2754
  args: aggregateGenerated.args,
2542
- resolve: aggregateGenerated.resolver
2755
+ resolve: aggregateGenerated.resolver,
2756
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
2757
+ };
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) } } : {}
2543
2765
  };
2544
2766
  }
2545
2767
  for (const generated of [
@@ -2573,6 +2795,10 @@ var generateSchemaData = (db, schema, relations, options) => {
2573
2795
  if (aggregateType) {
2574
2796
  outputs[aggregateType.name] = aggregateType;
2575
2797
  }
2798
+ if (groupByType && havingInput) {
2799
+ outputs[groupByType.name] = groupByType;
2800
+ inputs[havingInput.name] = havingInput;
2801
+ }
2576
2802
  }
2577
2803
  const fieldResolvers = {};
2578
2804
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -2595,7 +2821,7 @@ var generateSchemaData = (db, schema, relations, options) => {
2595
2821
  import { is as is5, One as One4 } from "drizzle-orm";
2596
2822
  import { getTableConfig as getTableConfig2, PgTable } from "drizzle-orm/pg-core";
2597
2823
  import {
2598
- GraphQLError as GraphQLError5,
2824
+ GraphQLError as GraphQLError6,
2599
2825
  GraphQLList as GraphQLList5,
2600
2826
  GraphQLNonNull as GraphQLNonNull5
2601
2827
  } from "graphql";
@@ -2756,7 +2982,7 @@ var generateInsertArray2 = (db, tableName, table, tables, relationMap, baseType,
2756
2982
  try {
2757
2983
  const input = remapFromGraphQLArrayInput(args.values, table);
2758
2984
  if (!input.length) {
2759
- throw new GraphQLError5("No values were provided!");
2985
+ throw new GraphQLError6("No values were provided!");
2760
2986
  }
2761
2987
  const parsedInfo = parseResolveInfo3(info, {
2762
2988
  deep: true
@@ -2846,7 +3072,7 @@ var generateUpsert2 = (db, tableName, table, tables, relationMap, baseType, onCo
2846
3072
  try {
2847
3073
  const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
2848
3074
  if (!input.length) {
2849
- throw new GraphQLError5("No values were provided!");
3075
+ throw new GraphQLError6("No values were provided!");
2850
3076
  }
2851
3077
  const parsedInfo = parseResolveInfo3(info, { deep: true });
2852
3078
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -2915,7 +3141,7 @@ var generateUpdate2 = (db, tableName, table, tables, relationMap, setArgs, filte
2915
3141
  });
2916
3142
  const input = remapFromGraphQLSingleInput(set, table);
2917
3143
  if (!Object.keys(input).length) {
2918
- throw new GraphQLError5("Unable to update with no values specified!");
3144
+ throw new GraphQLError6("Unable to update with no values specified!");
2919
3145
  }
2920
3146
  const executor = resolveExecutor(db, context);
2921
3147
  let query = executor.update(table).set(input);
@@ -2970,7 +3196,16 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, fi
2970
3196
  };
2971
3197
  };
2972
3198
  function generateSchemaData2(db, schema, relations, options) {
2973
- const { relationsDepthLimit, prefixes, suffixes, conflictDoNothing, typeNameMapper, shouldEagerLoad, features } = options;
3199
+ const {
3200
+ relationsDepthLimit,
3201
+ prefixes,
3202
+ suffixes,
3203
+ conflictDoNothing,
3204
+ typeNameMapper,
3205
+ shouldEagerLoad,
3206
+ features,
3207
+ complexity
3208
+ } = options;
2974
3209
  const schemaEntries = Object.entries(schema);
2975
3210
  const tableEntries = schemaEntries.filter(([_key, value]) => is5(value, PgTable));
2976
3211
  const tables = Object.fromEntries(tableEntries);
@@ -2993,7 +3228,8 @@ function generateSchemaData2(db, schema, relations, options) {
2993
3228
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
2994
3229
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
2995
3230
  listRelationFilterCache: /* @__PURE__ */ new Map(),
2996
- aggregateTypeCache: /* @__PURE__ */ new Map()
3231
+ aggregateTypeCache: /* @__PURE__ */ new Map(),
3232
+ complexity
2997
3233
  };
2998
3234
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
2999
3235
  const queries = {};
@@ -3026,6 +3262,7 @@ function generateSchemaData2(db, schema, relations, options) {
3026
3262
  listFieldName,
3027
3263
  singleFieldName,
3028
3264
  aggregateFieldName,
3265
+ groupByFieldName,
3029
3266
  createArrayFieldName,
3030
3267
  createSingleFieldName,
3031
3268
  upsertArrayFieldName,
@@ -3153,10 +3390,25 @@ function generateSchemaData2(db, schema, relations, options) {
3153
3390
  tableFilters,
3154
3391
  filterCtx
3155
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;
3156
3407
  queries[selectArrGenerated.name] = {
3157
3408
  type: selectArrOutput,
3158
3409
  args: selectArrGenerated.args,
3159
- resolve: selectArrGenerated.resolver
3410
+ resolve: selectArrGenerated.resolver,
3411
+ ...complexity ? { extensions: { complexity: listFieldComplexity(complexity) } } : {}
3160
3412
  };
3161
3413
  queries[selectSingleGenerated.name] = {
3162
3414
  type: selectSingleOutput,
@@ -3167,7 +3419,16 @@ function generateSchemaData2(db, schema, relations, options) {
3167
3419
  queries[aggregateGenerated.name] = {
3168
3420
  type: new GraphQLNonNull5(aggregateType),
3169
3421
  args: aggregateGenerated.args,
3170
- resolve: aggregateGenerated.resolver
3422
+ resolve: aggregateGenerated.resolver,
3423
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
3424
+ };
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) } } : {}
3171
3432
  };
3172
3433
  }
3173
3434
  if (insertArrGenerated) {
@@ -3228,6 +3489,10 @@ function generateSchemaData2(db, schema, relations, options) {
3228
3489
  if (aggregateType) {
3229
3490
  outputs[aggregateType.name] = aggregateType;
3230
3491
  }
3492
+ if (groupByType && havingInput) {
3493
+ outputs[groupByType.name] = groupByType;
3494
+ inputs[havingInput.name] = havingInput;
3495
+ }
3231
3496
  }
3232
3497
  const fieldResolvers = {};
3233
3498
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -3250,7 +3515,7 @@ function generateSchemaData2(db, schema, relations, options) {
3250
3515
  import { is as is6, One as One5 } from "drizzle-orm";
3251
3516
  import { getTableConfig as getTableConfig3, SQLiteTable } from "drizzle-orm/sqlite-core";
3252
3517
  import {
3253
- GraphQLError as GraphQLError6,
3518
+ GraphQLError as GraphQLError7,
3254
3519
  GraphQLList as GraphQLList6,
3255
3520
  GraphQLNonNull as GraphQLNonNull6
3256
3521
  } from "graphql";
@@ -3349,7 +3614,7 @@ var generateInsertArray3 = (db, tableName, table, tables, relationMap, baseType,
3349
3614
  try {
3350
3615
  const input = remapFromGraphQLArrayInput(args.values, table);
3351
3616
  if (!input.length) {
3352
- throw new GraphQLError6("No values were provided!");
3617
+ throw new GraphQLError7("No values were provided!");
3353
3618
  }
3354
3619
  const parsedInfo = parseResolveInfo4(info, {
3355
3620
  deep: true
@@ -3439,7 +3704,7 @@ var generateUpsert3 = (db, tableName, table, tables, relationMap, baseType, onCo
3439
3704
  try {
3440
3705
  const input = single ? [remapFromGraphQLSingleInput(args.values, table)] : remapFromGraphQLArrayInput(args.values, table);
3441
3706
  if (!input.length) {
3442
- throw new GraphQLError6("No values were provided!");
3707
+ throw new GraphQLError7("No values were provided!");
3443
3708
  }
3444
3709
  const parsedInfo = parseResolveInfo4(info, { deep: true });
3445
3710
  const { columns, hasRelations, withParams } = prepareMutationRelationColumns({
@@ -3508,7 +3773,7 @@ var generateUpdate3 = (db, tableName, table, tables, relationMap, setArgs, filte
3508
3773
  });
3509
3774
  const input = remapFromGraphQLSingleInput(set, table);
3510
3775
  if (!Object.keys(input).length) {
3511
- throw new GraphQLError6("Unable to update with no values specified!");
3776
+ throw new GraphQLError7("Unable to update with no values specified!");
3512
3777
  }
3513
3778
  const executor = resolveExecutor(db, context);
3514
3779
  let query = executor.update(table).set(input);
@@ -3563,7 +3828,16 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, fi
3563
3828
  };
3564
3829
  };
3565
3830
  var generateSchemaData3 = (db, schema, relations, options) => {
3566
- const { relationsDepthLimit, prefixes, suffixes, conflictDoNothing, typeNameMapper, shouldEagerLoad, features } = options;
3831
+ const {
3832
+ relationsDepthLimit,
3833
+ prefixes,
3834
+ suffixes,
3835
+ conflictDoNothing,
3836
+ typeNameMapper,
3837
+ shouldEagerLoad,
3838
+ features,
3839
+ complexity
3840
+ } = options;
3567
3841
  const rawSchema = schema;
3568
3842
  const schemaEntries = Object.entries(rawSchema);
3569
3843
  const tableEntries = schemaEntries.filter(([_key, value]) => is6(value, SQLiteTable));
@@ -3587,7 +3861,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3587
3861
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
3588
3862
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
3589
3863
  listRelationFilterCache: /* @__PURE__ */ new Map(),
3590
- aggregateTypeCache: /* @__PURE__ */ new Map()
3864
+ aggregateTypeCache: /* @__PURE__ */ new Map(),
3865
+ complexity
3591
3866
  };
3592
3867
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
3593
3868
  const queries = {};
@@ -3620,6 +3895,7 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3620
3895
  listFieldName,
3621
3896
  singleFieldName,
3622
3897
  aggregateFieldName,
3898
+ groupByFieldName,
3623
3899
  createArrayFieldName,
3624
3900
  createSingleFieldName,
3625
3901
  upsertArrayFieldName,
@@ -3747,10 +4023,25 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3747
4023
  tableFilters,
3748
4024
  filterCtx
3749
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;
3750
4040
  queries[selectArrGenerated.name] = {
3751
4041
  type: selectArrOutput,
3752
4042
  args: selectArrGenerated.args,
3753
- resolve: selectArrGenerated.resolver
4043
+ resolve: selectArrGenerated.resolver,
4044
+ ...complexity ? { extensions: { complexity: listFieldComplexity(complexity) } } : {}
3754
4045
  };
3755
4046
  queries[selectSingleGenerated.name] = {
3756
4047
  type: selectSingleOutput,
@@ -3761,7 +4052,16 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3761
4052
  queries[aggregateGenerated.name] = {
3762
4053
  type: new GraphQLNonNull6(aggregateType),
3763
4054
  args: aggregateGenerated.args,
3764
- resolve: aggregateGenerated.resolver
4055
+ resolve: aggregateGenerated.resolver,
4056
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
4057
+ };
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) } } : {}
3765
4065
  };
3766
4066
  }
3767
4067
  if (insertArrGenerated) {
@@ -3822,6 +4122,10 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3822
4122
  if (aggregateType) {
3823
4123
  outputs[aggregateType.name] = aggregateType;
3824
4124
  }
4125
+ if (groupByType && havingInput) {
4126
+ outputs[groupByType.name] = groupByType;
4127
+ inputs[havingInput.name] = havingInput;
4128
+ }
3825
4129
  }
3826
4130
  const fieldResolvers = {};
3827
4131
  for (const [tableName, tableRelations] of Object.entries(namedRelations)) {
@@ -3864,6 +4168,7 @@ var buildSchema = (db, config) => {
3864
4168
  const typeNameMapper = config?.typeNameMapper;
3865
4169
  const features = {
3866
4170
  aggregates: config?.features?.aggregates ?? true,
4171
+ groupBy: config?.features?.groupBy ?? true,
3867
4172
  relationAggregates: config?.features?.relationAggregates ?? true,
3868
4173
  distinct: config?.features?.distinct ?? true,
3869
4174
  insert: config?.features?.insert ?? true,
@@ -3871,6 +4176,11 @@ var buildSchema = (db, config) => {
3871
4176
  delete: config?.features?.delete ?? true,
3872
4177
  upsert: config?.features?.upsert ?? false
3873
4178
  };
4179
+ const complexityConfig = config?.complexity ?? true;
4180
+ const complexity = complexityConfig === false ? void 0 : {
4181
+ defaultListSize: (complexityConfig === true ? void 0 : complexityConfig.defaultListSize) ?? 10,
4182
+ aggregateCost: (complexityConfig === true ? void 0 : complexityConfig.aggregateCost) ?? 10
4183
+ };
3874
4184
  const eagerOpt = config?.eagerLoadRelations;
3875
4185
  const shouldEagerLoad = eagerOpt === void 0 || eagerOpt === true ? () => true : eagerOpt === false ? () => false : eagerOpt;
3876
4186
  if (!typeNameMapper && suffixes.list === suffixes.single) {
@@ -3897,7 +4207,8 @@ var buildSchema = (db, config) => {
3897
4207
  conflictDoNothing: config?.conflictDoNothing ?? false,
3898
4208
  typeNameMapper,
3899
4209
  shouldEagerLoad,
3900
- features
4210
+ features,
4211
+ complexity
3901
4212
  };
3902
4213
  let generatorOutput;
3903
4214
  if (is7(db, MySqlDatabase)) {