@vantreeseba/drizzle-graphql 4.0.0 → 4.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/dist/index.d.cts CHANGED
@@ -419,6 +419,26 @@ type SchemaFeatures = {
419
419
  */
420
420
  upsert?: boolean;
421
421
  };
422
+ /**
423
+ * Per-field cost hints for `graphql-query-complexity` (or any estimator that reads
424
+ * `extensions.complexity`). See {@link BuildSchemaConfig.complexity}.
425
+ */
426
+ type ComplexityConfig = {
427
+ /**
428
+ * Rows a list field is assumed to return when the query passes no `limit`. Raise it if your
429
+ * tables are large and clients routinely omit `limit`.
430
+ *
431
+ * @default 10
432
+ */
433
+ defaultListSize?: number;
434
+ /**
435
+ * Flat cost charged for an aggregate field, on top of whatever is selected inside it. An
436
+ * aggregate returns one row but reads however many match, so it is priced as a scan.
437
+ *
438
+ * @default 10
439
+ */
440
+ aggregateCost?: number;
441
+ };
422
442
  type BuildSchemaConfig = {
423
443
  /**
424
444
  * Determines whether generated mutations will be passed to returned schema.
@@ -487,6 +507,31 @@ type BuildSchemaConfig = {
487
507
  * until the next major.
488
508
  */
489
509
  conflictDoNothing?: boolean;
510
+ /**
511
+ * Cost hints published as `extensions.complexity` on the generated fields, for
512
+ * `graphql-query-complexity`'s `fieldExtensionsEstimator`.
513
+ *
514
+ * The generator knows which fields are paginated and which are aggregates, so a list field is
515
+ * priced at `(limit ?? defaultListSize) * childComplexity` and an aggregate at
516
+ * `aggregateCost + childComplexity`. Everything else is left alone and falls through to your
517
+ * estimator's default. The hints are inert until you install a complexity rule, so they are on
518
+ * by default; pass `false` to omit them.
519
+ *
520
+ * Cost is not a depth bound — a cyclic relation graph still lets a client nest arbitrarily
521
+ * deep. Put a depth limit in front of a publicly exposed schema as well.
522
+ *
523
+ * ```ts
524
+ * import { createComplexityRule, fieldExtensionsEstimator, simpleEstimator } from 'graphql-query-complexity';
525
+ *
526
+ * const rule = createComplexityRule({
527
+ * maximumComplexity: 1000,
528
+ * estimators: [fieldExtensionsEstimator(), simpleEstimator({ defaultComplexity: 1 })],
529
+ * });
530
+ * ```
531
+ *
532
+ * @default true
533
+ */
534
+ complexity?: boolean | ComplexityConfig;
490
535
  /**
491
536
  * Turns individual generated features off.
492
537
  *
@@ -594,4 +639,4 @@ declare const GraphQLBigIntString: GraphQLScalarType<string, string>;
594
639
 
595
640
  declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
596
641
 
597
- export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type DeleteResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
642
+ export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ComplexityConfig, type DeleteResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
package/dist/index.d.ts CHANGED
@@ -419,6 +419,26 @@ type SchemaFeatures = {
419
419
  */
420
420
  upsert?: boolean;
421
421
  };
422
+ /**
423
+ * Per-field cost hints for `graphql-query-complexity` (or any estimator that reads
424
+ * `extensions.complexity`). See {@link BuildSchemaConfig.complexity}.
425
+ */
426
+ type ComplexityConfig = {
427
+ /**
428
+ * Rows a list field is assumed to return when the query passes no `limit`. Raise it if your
429
+ * tables are large and clients routinely omit `limit`.
430
+ *
431
+ * @default 10
432
+ */
433
+ defaultListSize?: number;
434
+ /**
435
+ * Flat cost charged for an aggregate field, on top of whatever is selected inside it. An
436
+ * aggregate returns one row but reads however many match, so it is priced as a scan.
437
+ *
438
+ * @default 10
439
+ */
440
+ aggregateCost?: number;
441
+ };
422
442
  type BuildSchemaConfig = {
423
443
  /**
424
444
  * Determines whether generated mutations will be passed to returned schema.
@@ -487,6 +507,31 @@ type BuildSchemaConfig = {
487
507
  * until the next major.
488
508
  */
489
509
  conflictDoNothing?: boolean;
510
+ /**
511
+ * Cost hints published as `extensions.complexity` on the generated fields, for
512
+ * `graphql-query-complexity`'s `fieldExtensionsEstimator`.
513
+ *
514
+ * The generator knows which fields are paginated and which are aggregates, so a list field is
515
+ * priced at `(limit ?? defaultListSize) * childComplexity` and an aggregate at
516
+ * `aggregateCost + childComplexity`. Everything else is left alone and falls through to your
517
+ * estimator's default. The hints are inert until you install a complexity rule, so they are on
518
+ * by default; pass `false` to omit them.
519
+ *
520
+ * Cost is not a depth bound — a cyclic relation graph still lets a client nest arbitrarily
521
+ * deep. Put a depth limit in front of a publicly exposed schema as well.
522
+ *
523
+ * ```ts
524
+ * import { createComplexityRule, fieldExtensionsEstimator, simpleEstimator } from 'graphql-query-complexity';
525
+ *
526
+ * const rule = createComplexityRule({
527
+ * maximumComplexity: 1000,
528
+ * estimators: [fieldExtensionsEstimator(), simpleEstimator({ defaultComplexity: 1 })],
529
+ * });
530
+ * ```
531
+ *
532
+ * @default true
533
+ */
534
+ complexity?: boolean | ComplexityConfig;
490
535
  /**
491
536
  * Turns individual generated features off.
492
537
  *
@@ -594,4 +639,4 @@ declare const GraphQLBigIntString: GraphQLScalarType<string, string>;
594
639
 
595
640
  declare const buildSchema: <TDbClient extends AnyDrizzleDB<any>>(db: TDbClient, config?: BuildSchemaConfig) => GeneratedData<TDbClient>;
596
641
 
597
- export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type DeleteResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
642
+ export { type AggregateResolver, type AnyDrizzleDB, type BuildSchemaConfig, type ComplexityConfig, type DeleteResolver, type ExtractRelations, type ExtractTableByName, type ExtractTableRelations, type ExtractTables, type GeneratedData, type GeneratedEntities, type GeneratedInputs, type GeneratedOutputs, GraphQLBigIntString, type InsertArrResolver, type InsertResolver, type MutationReturnlessResult, type MutationsCore, type QueriesCore, type RelationResolverFactory, type SchemaFeatures, type SelectResolver, type SelectSingleResolver, type TableNamedRelations, type UpdateResolver, type UpsertArgs, type UpsertArrResolver, type UpsertConflictArgs, type UpsertResolver, buildSchema, createRelationResolverFactory, defaultErrorMapper, drizzleExecutorKey, extractFilters, extractOrderBy, extractRelationJoinColumns };
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
  }
@@ -2394,7 +2402,7 @@ var generateDelete = (db, tableName, table, filterArgs, fieldName, filterCtx) =>
2394
2402
  };
2395
2403
  var mysqlPrimaryKeyPropNames = (table) => getPrimaryKeyPropNamesFromConfig(table, getTableConfig);
2396
2404
  var generateSchemaData = (db, schema, relations, options) => {
2397
- const { relationsDepthLimit, prefixes, suffixes, typeNameMapper, shouldEagerLoad, features } = options;
2405
+ const { relationsDepthLimit, prefixes, suffixes, typeNameMapper, shouldEagerLoad, features, complexity } = options;
2398
2406
  const rawSchema = schema;
2399
2407
  const schemaEntries = Object.entries(rawSchema);
2400
2408
  const tableEntries = schemaEntries.filter(([_key, value]) => is4(value, MySqlTable));
@@ -2418,7 +2426,8 @@ var generateSchemaData = (db, schema, relations, options) => {
2418
2426
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
2419
2427
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
2420
2428
  listRelationFilterCache: /* @__PURE__ */ new Map(),
2421
- aggregateTypeCache: /* @__PURE__ */ new Map()
2429
+ aggregateTypeCache: /* @__PURE__ */ new Map(),
2430
+ complexity
2422
2431
  };
2423
2432
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
2424
2433
  const queries = {};
@@ -2528,7 +2537,8 @@ var generateSchemaData = (db, schema, relations, options) => {
2528
2537
  queries[selectArrGenerated.name] = {
2529
2538
  type: selectArrOutput,
2530
2539
  args: selectArrGenerated.args,
2531
- resolve: selectArrGenerated.resolver
2540
+ resolve: selectArrGenerated.resolver,
2541
+ ...complexity ? { extensions: { complexity: listFieldComplexity(complexity) } } : {}
2532
2542
  };
2533
2543
  queries[selectSingleGenerated.name] = {
2534
2544
  type: selectSingleOutput,
@@ -2539,7 +2549,8 @@ var generateSchemaData = (db, schema, relations, options) => {
2539
2549
  queries[aggregateGenerated.name] = {
2540
2550
  type: new GraphQLNonNull4(aggregateType),
2541
2551
  args: aggregateGenerated.args,
2542
- resolve: aggregateGenerated.resolver
2552
+ resolve: aggregateGenerated.resolver,
2553
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
2543
2554
  };
2544
2555
  }
2545
2556
  for (const generated of [
@@ -2970,7 +2981,16 @@ var generateDelete2 = (db, tableName, table, filterArgs, fieldName, typeName, fi
2970
2981
  };
2971
2982
  };
2972
2983
  function generateSchemaData2(db, schema, relations, options) {
2973
- const { relationsDepthLimit, prefixes, suffixes, conflictDoNothing, typeNameMapper, shouldEagerLoad, features } = options;
2984
+ const {
2985
+ relationsDepthLimit,
2986
+ prefixes,
2987
+ suffixes,
2988
+ conflictDoNothing,
2989
+ typeNameMapper,
2990
+ shouldEagerLoad,
2991
+ features,
2992
+ complexity
2993
+ } = options;
2974
2994
  const schemaEntries = Object.entries(schema);
2975
2995
  const tableEntries = schemaEntries.filter(([_key, value]) => is5(value, PgTable));
2976
2996
  const tables = Object.fromEntries(tableEntries);
@@ -2993,7 +3013,8 @@ function generateSchemaData2(db, schema, relations, options) {
2993
3013
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
2994
3014
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
2995
3015
  listRelationFilterCache: /* @__PURE__ */ new Map(),
2996
- aggregateTypeCache: /* @__PURE__ */ new Map()
3016
+ aggregateTypeCache: /* @__PURE__ */ new Map(),
3017
+ complexity
2997
3018
  };
2998
3019
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
2999
3020
  const queries = {};
@@ -3156,7 +3177,8 @@ function generateSchemaData2(db, schema, relations, options) {
3156
3177
  queries[selectArrGenerated.name] = {
3157
3178
  type: selectArrOutput,
3158
3179
  args: selectArrGenerated.args,
3159
- resolve: selectArrGenerated.resolver
3180
+ resolve: selectArrGenerated.resolver,
3181
+ ...complexity ? { extensions: { complexity: listFieldComplexity(complexity) } } : {}
3160
3182
  };
3161
3183
  queries[selectSingleGenerated.name] = {
3162
3184
  type: selectSingleOutput,
@@ -3167,7 +3189,8 @@ function generateSchemaData2(db, schema, relations, options) {
3167
3189
  queries[aggregateGenerated.name] = {
3168
3190
  type: new GraphQLNonNull5(aggregateType),
3169
3191
  args: aggregateGenerated.args,
3170
- resolve: aggregateGenerated.resolver
3192
+ resolve: aggregateGenerated.resolver,
3193
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
3171
3194
  };
3172
3195
  }
3173
3196
  if (insertArrGenerated) {
@@ -3563,7 +3586,16 @@ var generateDelete3 = (db, tableName, table, filterArgs, fieldName, typeName, fi
3563
3586
  };
3564
3587
  };
3565
3588
  var generateSchemaData3 = (db, schema, relations, options) => {
3566
- const { relationsDepthLimit, prefixes, suffixes, conflictDoNothing, typeNameMapper, shouldEagerLoad, features } = options;
3589
+ const {
3590
+ relationsDepthLimit,
3591
+ prefixes,
3592
+ suffixes,
3593
+ conflictDoNothing,
3594
+ typeNameMapper,
3595
+ shouldEagerLoad,
3596
+ features,
3597
+ complexity
3598
+ } = options;
3567
3599
  const rawSchema = schema;
3568
3600
  const schemaEntries = Object.entries(rawSchema);
3569
3601
  const tableEntries = schemaEntries.filter(([_key, value]) => is6(value, SQLiteTable));
@@ -3587,7 +3619,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3587
3619
  orderTypeCache: /* @__PURE__ */ new WeakMap(),
3588
3620
  filterTypeCache: /* @__PURE__ */ new WeakMap(),
3589
3621
  listRelationFilterCache: /* @__PURE__ */ new Map(),
3590
- aggregateTypeCache: /* @__PURE__ */ new Map()
3622
+ aggregateTypeCache: /* @__PURE__ */ new Map(),
3623
+ complexity
3591
3624
  };
3592
3625
  const relationAggregateFactory = features.relationAggregates ? createRelationAggregateFactory(db, tables, cacheCtx, typeNameMapper, filterCtx) : void 0;
3593
3626
  const queries = {};
@@ -3750,7 +3783,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3750
3783
  queries[selectArrGenerated.name] = {
3751
3784
  type: selectArrOutput,
3752
3785
  args: selectArrGenerated.args,
3753
- resolve: selectArrGenerated.resolver
3786
+ resolve: selectArrGenerated.resolver,
3787
+ ...complexity ? { extensions: { complexity: listFieldComplexity(complexity) } } : {}
3754
3788
  };
3755
3789
  queries[selectSingleGenerated.name] = {
3756
3790
  type: selectSingleOutput,
@@ -3761,7 +3795,8 @@ var generateSchemaData3 = (db, schema, relations, options) => {
3761
3795
  queries[aggregateGenerated.name] = {
3762
3796
  type: new GraphQLNonNull6(aggregateType),
3763
3797
  args: aggregateGenerated.args,
3764
- resolve: aggregateGenerated.resolver
3798
+ resolve: aggregateGenerated.resolver,
3799
+ ...complexity ? { extensions: { complexity: aggregateFieldComplexity(complexity) } } : {}
3765
3800
  };
3766
3801
  }
3767
3802
  if (insertArrGenerated) {
@@ -3871,6 +3906,11 @@ var buildSchema = (db, config) => {
3871
3906
  delete: config?.features?.delete ?? true,
3872
3907
  upsert: config?.features?.upsert ?? false
3873
3908
  };
3909
+ const complexityConfig = config?.complexity ?? true;
3910
+ const complexity = complexityConfig === false ? void 0 : {
3911
+ defaultListSize: (complexityConfig === true ? void 0 : complexityConfig.defaultListSize) ?? 10,
3912
+ aggregateCost: (complexityConfig === true ? void 0 : complexityConfig.aggregateCost) ?? 10
3913
+ };
3874
3914
  const eagerOpt = config?.eagerLoadRelations;
3875
3915
  const shouldEagerLoad = eagerOpt === void 0 || eagerOpt === true ? () => true : eagerOpt === false ? () => false : eagerOpt;
3876
3916
  if (!typeNameMapper && suffixes.list === suffixes.single) {
@@ -3897,7 +3937,8 @@ var buildSchema = (db, config) => {
3897
3937
  conflictDoNothing: config?.conflictDoNothing ?? false,
3898
3938
  typeNameMapper,
3899
3939
  shouldEagerLoad,
3900
- features
3940
+ features,
3941
+ complexity
3901
3942
  };
3902
3943
  let generatorOutput;
3903
3944
  if (is7(db, MySqlDatabase)) {