@baeta/extension-complexity 1.0.11 → 2.0.0-next.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @baeta/extension-complexity
2
2
 
3
+ ## 2.0.0-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix release version
8
+
9
+ - Updated dependencies []:
10
+ - @baeta/core@2.0.0-next.1
11
+
12
+ ## 2.0.0-next.0
13
+
14
+ ### Major Changes
15
+
16
+ - [#214](https://github.com/andreisergiu98/baeta/pull/214) [`31d1a50`](https://github.com/andreisergiu98/baeta/commit/31d1a509f96535b43ae85d19c770eb1a5f09dc94) Thanks [@andreisergiu98](https://github.com/andreisergiu98)! - Baeta v2 – major refactor
17
+ - **Side-effect-free type generation & resolver definitions.**
18
+ The types generator and resolver definitions were reworked to be side-effect free, improving type safety.
19
+ - **Stricter type safety.**
20
+ You must now **explicitly define resolvers for every field** during development—breakages that used to surface at runtime are now caught at compile time.
21
+ - **Removed `@baeta/compiler`.**
22
+ Since modern runtimes can execute TypeScript natively, the separate compiler package is no longer needed. Use your runtime’s native TS support or your existing build setup.
23
+ - **Subscriptions update.**
24
+ `@baeta/subscriptions-pubsub` now targets **`graphql-subscriptions` v3**.
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [[`31d1a50`](https://github.com/andreisergiu98/baeta/commit/31d1a509f96535b43ae85d19c770eb1a5f09dc94)]:
29
+ - @baeta/core@2.0.0-next.0
30
+
3
31
  ## 1.0.11
4
32
 
5
33
  ### Patch Changes
package/dist/index.js CHANGED
@@ -43,35 +43,37 @@ var ComplexityError = class extends GraphQLError {
43
43
  });
44
44
  }
45
45
  };
46
- var ComplexityErrorKind = /* @__PURE__ */ ((ComplexityErrorKind2) => {
47
- ComplexityErrorKind2["Depth"] = "DepthExceeded";
48
- ComplexityErrorKind2["Breadth"] = "BreadthExceeded";
49
- ComplexityErrorKind2["Complexity"] = "ComplexityExceeded";
50
- return ComplexityErrorKind2;
51
- })(ComplexityErrorKind || {});
46
+ var ComplexityErrorKind = {
47
+ /** Query exceeds maximum allowed depth */
48
+ Depth: "DepthExceeded",
49
+ /** Query exceeds maximum allowed breadth (fields per level) */
50
+ Breadth: "BreadthExceeded",
51
+ /** Query exceeds total complexity score limit */
52
+ Complexity: "ComplexityExceeded"
53
+ };
52
54
  function getDefaultComplexityError(kind, limit, result) {
53
- if (kind === "DepthExceeded" /* Depth */) {
55
+ if (kind === ComplexityErrorKind.Depth) {
54
56
  return new ComplexityError(`Depth limit of ${limit} exceeded, got: ${result}`, {
55
57
  extensions: {
56
- kind: "DepthExceeded" /* Depth */,
58
+ kind: ComplexityErrorKind.Depth,
57
59
  limit,
58
60
  got: result
59
61
  }
60
62
  });
61
63
  }
62
- if (kind === "BreadthExceeded" /* Breadth */) {
64
+ if (kind === ComplexityErrorKind.Breadth) {
63
65
  return new ComplexityError(`Breadth limit of ${limit} exceeded, got: ${result}`, {
64
66
  extensions: {
65
- kind: "BreadthExceeded" /* Breadth */,
67
+ kind: ComplexityErrorKind.Breadth,
66
68
  limit,
67
69
  got: result
68
70
  }
69
71
  });
70
72
  }
71
- if (kind === "ComplexityExceeded" /* Complexity */) {
73
+ if (kind === ComplexityErrorKind.Complexity) {
72
74
  return new ComplexityError(`Complexity limit of ${limit} exceeded, got: ${result}`, {
73
75
  extensions: {
74
- kind: "ComplexityExceeded" /* Complexity */,
76
+ kind: ComplexityErrorKind.Complexity,
75
77
  limit,
76
78
  got: result
77
79
  }
@@ -272,89 +274,113 @@ function loadComplexityStore(ctx, getLimits, defaultLimits2) {
272
274
 
273
275
  // lib/complexity-middleware.ts
274
276
  function createComplexityMiddleware(options, fieldSettingsMap) {
275
- return (next) => async (root, args, ctx, info) => {
276
- loadComplexityStore(ctx, options.limit, defaultLimits);
277
- const store = await getComplexityStore(ctx);
277
+ return async (next, params) => {
278
+ loadComplexityStore(params.ctx, options.limit, defaultLimits);
279
+ const store = await getComplexityStore(params.ctx);
278
280
  const limits = store.limits;
279
281
  const results = store.cacheComplexity(() => {
280
- return calculateComplexity(ctx, info, fieldSettingsMap, {
282
+ return calculateComplexity(params.ctx, params.info, fieldSettingsMap, {
281
283
  complexity: options.defaultComplexity,
282
284
  multiplier: options.defaultListMultiplier
283
285
  });
284
286
  });
285
287
  if (results.complexity > limits.complexity) {
286
288
  throw options.complexityError(
287
- "ComplexityExceeded" /* Complexity */,
289
+ ComplexityErrorKind.Complexity,
288
290
  limits.complexity,
289
291
  results.complexity
290
292
  );
291
293
  }
292
294
  if (results.depth > limits.depth) {
293
- throw options.complexityError("DepthExceeded" /* Depth */, limits.depth, results.depth);
295
+ throw options.complexityError(ComplexityErrorKind.Depth, limits.depth, results.depth);
294
296
  }
295
297
  if (results.breadth > limits.breadth) {
296
- throw options.complexityError("BreadthExceeded" /* Breadth */, limits.breadth, results.breadth);
298
+ throw options.complexityError(ComplexityErrorKind.Breadth, limits.breadth, results.breadth);
297
299
  }
298
- return next(root, args, ctx, info);
300
+ return next();
299
301
  };
300
302
  }
301
303
 
302
304
  // lib/complexity-extension.ts
303
305
  var ComplexityExtension = class extends Extension {
306
+ stateKey = Symbol("complexity-settings");
304
307
  options;
305
308
  constructor(options = {}) {
306
309
  super();
307
310
  this.options = normalizeOptions(options);
308
311
  }
309
- fieldSettingsMap = {};
310
- getTypeExtensions = (_module, type) => {
312
+ getTypeExtensions = (builder) => {
311
313
  return {
312
314
  $complexity: (fn) => {
313
- registerFieldSettingsSetter(type, "*", fn, this.fieldSettingsMap);
315
+ const editable = builder.edit();
316
+ this.setState(editable, {
317
+ fieldSettings: fn
318
+ });
319
+ return editable.commitToMethods();
314
320
  }
315
321
  };
316
322
  };
317
- getResolverExtensions = (_module, type, field) => {
323
+ getFieldExtensions = (builder) => {
318
324
  return {
319
325
  $complexity: (fn) => {
320
- registerFieldSettingsSetter(type, field, fn, this.fieldSettingsMap);
326
+ const editable = builder.edit();
327
+ this.setState(editable, {
328
+ fieldSettings: fn
329
+ });
330
+ return editable.commitToMethods();
321
331
  }
322
332
  };
323
333
  };
324
- getSubscriptionExtensions = (_module, field) => {
334
+ getSubscriptionExtensions = (builder) => {
325
335
  return {
326
336
  $complexity: (fn) => {
327
- registerFieldSettingsSetter("Subscription", field, fn, this.fieldSettingsMap);
337
+ const editable = builder.edit();
338
+ this.setState(editable, {
339
+ fieldSettings: fn
340
+ });
341
+ return editable.commitToMethods();
328
342
  }
329
343
  };
330
344
  };
331
- createComplexityMiddleware() {
332
- return createComplexityMiddleware(
345
+ mutate(compilers) {
346
+ const fieldSettingsMap = {};
347
+ for (const compiler of compilers) {
348
+ for (const typeCompiler of compiler.types) {
349
+ const state = this.getState(typeCompiler);
350
+ if (!state) continue;
351
+ registerFieldSettingsSetter(typeCompiler.type, "*", state.fieldSettings, fieldSettingsMap);
352
+ for (const fieldCompiler of typeCompiler.fields) {
353
+ const state2 = this.getState(fieldCompiler);
354
+ if (!state2) continue;
355
+ registerFieldSettingsSetter(
356
+ typeCompiler.type,
357
+ fieldCompiler.field,
358
+ state2.fieldSettings,
359
+ fieldSettingsMap
360
+ );
361
+ }
362
+ }
363
+ }
364
+ const middleware = createComplexityMiddleware(
333
365
  this.options,
334
- this.fieldSettingsMap
366
+ fieldSettingsMap
335
367
  );
336
- }
337
- build = (_module, mapper) => {
338
- for (const type of mapper.getTypes()) {
339
- if (type !== "Query" && type !== "Mutation" && type !== "Subscription") {
340
- continue;
341
- }
342
- if (type !== "Subscription") {
343
- for (const field of mapper.getTypeFields(type)) {
344
- mapper.prependMiddleware(type, field, this.createComplexityMiddleware());
368
+ for (const compiler of compilers) {
369
+ for (const typeCompiler of compiler.types) {
370
+ if (!["Query", "Mutation", "Subscription"].includes(typeCompiler.type)) {
371
+ continue;
372
+ }
373
+ for (const fieldCompiler of typeCompiler.fields) {
374
+ fieldCompiler.addInitialMiddleware(middleware);
345
375
  }
346
- continue;
347
- }
348
- for (const field of mapper.getTypeFields(type)) {
349
- mapper.prependMiddleware(type, `${field}.subscribe`, this.createComplexityMiddleware());
350
376
  }
351
377
  }
352
- };
378
+ }
353
379
  };
354
380
 
355
381
  // index.ts
356
382
  function complexityExtension(options) {
357
- return () => new ComplexityExtension(options);
383
+ return new ComplexityExtension(options);
358
384
  }
359
385
  export {
360
386
  ComplexityError,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/complexity-extension.ts","../lib/complexity-calculator.ts","../utils/graphlq.ts","../utils/string.ts","../lib/complexity-errors.ts","../lib/field-settings.ts","../lib/complexity-options.ts","../lib/store.ts","../lib/store-loader.ts","../lib/complexity-middleware.ts","../index.ts"],"sourcesContent":["import {\n\tExtension,\n\ttype ModuleBuilder,\n\ttype NativeMiddleware,\n\ttype ResolverMapper,\n} from '@baeta/core/sdk';\nimport { createComplexityMiddleware } from './complexity-middleware.ts';\nimport { type ComplexityExtensionOptions, normalizeOptions } from './complexity-options.ts';\nimport { type FieldSettingsMap, registerFieldSettingsSetter } from './field-settings.ts';\n\nexport class ComplexityExtension<Ctx> extends Extension {\n\tprivate readonly options: Required<ComplexityExtensionOptions<Ctx>>;\n\n\tconstructor(options: ComplexityExtensionOptions<Ctx> = {}) {\n\t\tsuper();\n\t\tthis.options = normalizeOptions(options);\n\t}\n\n\tprivate fieldSettingsMap: FieldSettingsMap = {};\n\n\tgetTypeExtensions = <Root, Context>(\n\t\t_module: ModuleBuilder,\n\t\ttype: string,\n\t): BaetaExtensions.TypeExtensions<Root, Context> => {\n\t\treturn {\n\t\t\t$complexity: (fn) => {\n\t\t\t\tregisterFieldSettingsSetter(type, '*', fn, this.fieldSettingsMap);\n\t\t\t},\n\t\t};\n\t};\n\n\tgetResolverExtensions = <Result, Root, Context, Args>(\n\t\t_module: ModuleBuilder,\n\t\ttype: string,\n\t\tfield: string,\n\t): BaetaExtensions.ResolverExtensions<Result, Root, Context, Args> => {\n\t\treturn {\n\t\t\t$complexity: (fn) => {\n\t\t\t\tregisterFieldSettingsSetter(type, field, fn, this.fieldSettingsMap);\n\t\t\t},\n\t\t};\n\t};\n\n\tgetSubscriptionExtensions = <Root, Context, Args>(\n\t\t_module: ModuleBuilder,\n\t\tfield: string,\n\t): BaetaExtensions.SubscriptionExtensions<Root, Context, Args> => {\n\t\treturn {\n\t\t\t$complexity: (fn) => {\n\t\t\t\tregisterFieldSettingsSetter('Subscription', field, fn, this.fieldSettingsMap);\n\t\t\t},\n\t\t};\n\t};\n\n\tcreateComplexityMiddleware<Result, Root, Context, Args>(): NativeMiddleware<\n\t\tResult,\n\t\tRoot,\n\t\tContext,\n\t\tArgs\n\t> {\n\t\treturn createComplexityMiddleware<Result, Root, Context, Args>(\n\t\t\tthis.options as Required<ComplexityExtensionOptions<Context>>,\n\t\t\tthis.fieldSettingsMap,\n\t\t);\n\t}\n\n\tbuild = (_module: ModuleBuilder, mapper: ResolverMapper) => {\n\t\tfor (const type of mapper.getTypes()) {\n\t\t\tif (type !== 'Query' && type !== 'Mutation' && type !== 'Subscription') {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (type !== 'Subscription') {\n\t\t\t\tfor (const field of mapper.getTypeFields(type)) {\n\t\t\t\t\tmapper.prependMiddleware(type, field, this.createComplexityMiddleware());\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor (const field of mapper.getTypeFields(type)) {\n\t\t\t\tmapper.prependMiddleware(type, `${field}.subscribe`, this.createComplexityMiddleware());\n\t\t\t}\n\t\t}\n\t};\n}\n","/**\n * Originally based on plugin-complexity of Pothos\n * Source: https://github.com/hayes/pothos/blob/main/packages/plugin-complexity/src/calculate-complexity.ts\n * Copyright (c) 2021 Michael Hayes\n * Adapted by Baeta developers\n */\nimport {\n\ttype FieldNode,\n\ttype FragmentDefinitionNode,\n\ttype GraphQLNamedType,\n\ttype GraphQLResolveInfo,\n\tgetNamedType,\n\ttype InlineFragmentNode,\n\tisInterfaceType,\n\tisObjectType,\n\tisOutputType,\n\tKind,\n\ttype SelectionNode,\n\ttype SelectionSetNode,\n} from 'graphql';\nimport { isListOrNullableList } from '../utils/graphlq.ts';\nimport { capitalize } from '../utils/string.ts';\nimport { ComplexityError } from './complexity-errors.ts';\nimport { type FieldSettingsMap, getFieldComplexitySettings } from './field-settings.ts';\n\ninterface ComplexityDefaults {\n\tcomplexity: number;\n\tmultiplier: number;\n}\n\nexport function calculateComplexity<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\tfieldSettingsMap: FieldSettingsMap,\n\tdefaults: ComplexityDefaults,\n) {\n\tconst operationName = capitalize(info.operation.operation);\n\tconst operationType = info.schema.getType(operationName);\n\n\tif (!operationType || !isOutputType(operationType)) {\n\t\tthrow new ComplexityError(`Unsupported operation ${operationName}`);\n\t}\n\n\treturn complexityFromSelectionSet(\n\t\tctx,\n\t\tinfo,\n\t\toperationType,\n\t\tinfo.operation.selectionSet,\n\t\tfieldSettingsMap,\n\t\tdefaults,\n\t);\n}\n\nfunction complexityFromSelectionSet<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\ttype: GraphQLNamedType,\n\tselectionSet: SelectionSetNode,\n\tfieldSettingsMap: FieldSettingsMap,\n\tdefaults: ComplexityDefaults,\n) {\n\tconst result = {\n\t\tdepth: 0,\n\t\tbreadth: 0,\n\t\tcomplexity: 0,\n\t};\n\n\tfor (const selection of selectionSet.selections) {\n\t\tconst selectionResult = complexityFromSelection(\n\t\t\tctx,\n\t\t\tinfo,\n\t\t\ttype,\n\t\t\tselection,\n\t\t\tfieldSettingsMap,\n\t\t\tdefaults,\n\t\t);\n\t\tresult.complexity += selectionResult.complexity;\n\t\tresult.breadth += selectionResult.breadth;\n\t\tresult.depth = Math.max(result.depth, selectionResult.depth);\n\t}\n\n\treturn result;\n}\n\nfunction complexityFromSelection<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\ttype: GraphQLNamedType,\n\tselection: SelectionNode,\n\tfieldSettingsMap: FieldSettingsMap,\n\tdefaults: ComplexityDefaults,\n) {\n\tif (selection.kind === Kind.FIELD) {\n\t\treturn complexityFromField(ctx, info, type, selection, fieldSettingsMap, defaults);\n\t}\n\n\tif (selection.kind === Kind.FRAGMENT_SPREAD) {\n\t\tconst fragment = info.fragments[selection.name.value];\n\n\t\tif (!fragment) {\n\t\t\tthrow new ComplexityError(`Fragment ${selection.name.value} not found`);\n\t\t}\n\n\t\treturn complexityFromFragment(ctx, info, type, fragment, fieldSettingsMap, defaults);\n\t}\n\n\treturn complexityFromFragment(ctx, info, type, selection, fieldSettingsMap, defaults);\n}\n\nfunction complexityFromFragment<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\ttype: GraphQLNamedType,\n\tfragment: FragmentDefinitionNode | InlineFragmentNode,\n\tfieldSettingsMap: FieldSettingsMap,\n\tdefaults: ComplexityDefaults,\n) {\n\tconst fragmentType = fragment.typeCondition\n\t\t? info.schema.getType(fragment.typeCondition.name.value)\n\t\t: type;\n\n\tif (!isOutputType(fragmentType)) {\n\t\tthrow new ComplexityError(`Unsupported fragment type ${fragmentType}`);\n\t}\n\n\tif (!fragmentType) {\n\t\tthrow new ComplexityError(`Fragment type ${fragmentType} not found`);\n\t}\n\n\treturn complexityFromSelectionSet(\n\t\tctx,\n\t\tinfo,\n\t\tfragmentType,\n\t\tfragment.selectionSet,\n\t\tfieldSettingsMap,\n\t\tdefaults,\n\t);\n}\n\nfunction complexityFromField<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\ttype: GraphQLNamedType,\n\tselection: FieldNode,\n\tfieldSettingsMap: FieldSettingsMap,\n\tdefaults: ComplexityDefaults,\n) {\n\tconst fieldName = selection.name.value;\n\n\tconst field =\n\t\tisObjectType(type) || isInterfaceType(type) ? type.getFields()[fieldName] : undefined;\n\n\tif (!field && !fieldName.startsWith('__')) {\n\t\tthrow new ComplexityError(`Field ${fieldName} not found on type ${type.name}`);\n\t}\n\n\tif (!field) {\n\t\treturn {\n\t\t\tdepth: 1,\n\t\t\tbreadth: 1,\n\t\t\tcomplexity: 1,\n\t\t};\n\t}\n\n\tconst fieldComplexitySettings = getFieldComplexitySettings(\n\t\tctx,\n\t\tinfo,\n\t\ttype,\n\t\tfield,\n\t\tselection,\n\t\tfieldName,\n\t\tfieldSettingsMap,\n\t);\n\n\tif (fieldComplexitySettings === false) {\n\t\treturn {\n\t\t\tdepth: 0,\n\t\t\tbreadth: 0,\n\t\t\tcomplexity: 0,\n\t\t};\n\t}\n\n\tlet depth = 1;\n\tlet breadth = 1;\n\tlet complexity = 0;\n\n\tconst listMultiplier = fieldComplexitySettings?.multiplier ?? defaults.multiplier;\n\tconst multiplier = field && isListOrNullableList(field.type) ? listMultiplier : 1;\n\n\tcomplexity += (fieldComplexitySettings?.complexity ?? defaults.complexity) * multiplier;\n\n\tif (!field || !selection.selectionSet) {\n\t\treturn {\n\t\t\tdepth,\n\t\t\tbreadth,\n\t\t\tcomplexity,\n\t\t};\n\t}\n\n\tconst subSelection = complexityFromSelectionSet(\n\t\tctx,\n\t\tinfo,\n\t\tgetNamedType(field.type),\n\t\tselection.selectionSet,\n\t\tfieldSettingsMap,\n\t\tdefaults,\n\t);\n\n\tdepth += subSelection.depth;\n\tbreadth += subSelection.breadth;\n\tcomplexity += subSelection.complexity * Math.max(multiplier, 1);\n\n\treturn {\n\t\tdepth,\n\t\tbreadth,\n\t\tcomplexity,\n\t};\n}\n","import { GraphQLList, GraphQLNonNull, type GraphQLOutputType } from 'graphql';\n\nexport function isListOrNullableList(type: GraphQLOutputType): boolean {\n\tif (type instanceof GraphQLList) {\n\t\treturn true;\n\t}\n\n\tif (type instanceof GraphQLNonNull) {\n\t\treturn isListOrNullableList(type.ofType);\n\t}\n\n\treturn false;\n}\n","export function capitalize(str: string) {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n}\n","import { GraphQLError, type GraphQLErrorOptions } from 'graphql';\n\n/** Complexity error code */\nexport const ComplexityErrorCode = 'COMPLEXITY_ERROR';\n\n/**\n * Thrown when a query exceeds the complexity limits.\n */\nexport class ComplexityError extends GraphQLError {\n\tconstructor(\n\t\tmessage = \"Complexity limit exceeded! Please reduce the query's complexity.\",\n\t\toptions?: GraphQLErrorOptions,\n\t) {\n\t\tsuper(message, {\n\t\t\t...options,\n\t\t\textensions: {\n\t\t\t\tcode: ComplexityErrorCode,\n\t\t\t\t...options?.extensions,\n\t\t\t},\n\t\t});\n\t}\n}\n\n/**\n * Types of complexity validation errors that can occur during query analysis.\n */\nexport enum ComplexityErrorKind {\n\t/** Query exceeds maximum allowed depth */\n\tDepth = 'DepthExceeded',\n\t/** Query exceeds maximum allowed breadth (fields per level) */\n\tBreadth = 'BreadthExceeded',\n\t/** Query exceeds total complexity score limit */\n\tComplexity = 'ComplexityExceeded',\n}\n\n/**\n * Function type for creating custom complexity error messages.\n *\n * @param kind - The type of complexity limit that was exceeded\n * @param limits - The maximum allowed value\n * @param results - The actual value that exceeded the limit\n * @returns A GraphQL error with a custom message\n */\nexport type GetComplexityError = (\n\tkind: ComplexityErrorKind,\n\tlimits: number,\n\tresults: number,\n) => GraphQLError;\n\nexport function getDefaultComplexityError(\n\tkind: ComplexityErrorKind,\n\tlimit: number,\n\tresult: number,\n): GraphQLError {\n\tif (kind === ComplexityErrorKind.Depth) {\n\t\treturn new ComplexityError(`Depth limit of ${limit} exceeded, got: ${result}`, {\n\t\t\textensions: {\n\t\t\t\tkind: ComplexityErrorKind.Depth,\n\t\t\t\tlimit,\n\t\t\t\tgot: result,\n\t\t\t},\n\t\t});\n\t}\n\n\tif (kind === ComplexityErrorKind.Breadth) {\n\t\treturn new ComplexityError(`Breadth limit of ${limit} exceeded, got: ${result}`, {\n\t\t\textensions: {\n\t\t\t\tkind: ComplexityErrorKind.Breadth,\n\t\t\t\tlimit,\n\t\t\t\tgot: result,\n\t\t\t},\n\t\t});\n\t}\n\n\tif (kind === ComplexityErrorKind.Complexity) {\n\t\treturn new ComplexityError(`Complexity limit of ${limit} exceeded, got: ${result}`, {\n\t\t\textensions: {\n\t\t\t\tkind: ComplexityErrorKind.Complexity,\n\t\t\t\tlimit,\n\t\t\t\tgot: result,\n\t\t\t},\n\t\t});\n\t}\n\n\tthrow new Error('Unknown complexity error kind');\n}\n","import {\n\ttype FieldNode,\n\ttype GraphQLField,\n\ttype GraphQLNamedType,\n\ttype GraphQLResolveInfo,\n\tgetArgumentValues,\n} from 'graphql';\n\nexport type FieldSettingsMap = Record<\n\tstring,\n\t// biome-ignore lint/suspicious/noExplicitAny: Match any type from the original code\n\tRecord<string, GetFieldSettings<any, any> | undefined> | undefined\n>;\n\n/**\n * Configuration for field complexity calculation.\n */\nexport type FieldSettings = {\n\tcomplexity?: number;\n\tmultiplier?: number;\n};\n\n/**\n * Arguments passed to field settings functions.\n */\nexport type GetFieldSettingsArgs<Context, Args> = {\n\t/** Arguments passed to the GraphQL field */\n\targs: Args;\n\t/** Request context */\n\tctx: Context;\n};\n\n/**\n * Function to determine complexity settings for a field.\n * Returns either field settings or false to disable complexity calculation.\n *\n * @param params - Object containing field arguments and context\n * @returns Field settings object or false\n */\nexport type GetFieldSettings<Context, Args> = (\n\tparams: GetFieldSettingsArgs<Context, Args>,\n) => FieldSettings | false;\n\nexport function getFieldComplexitySettings<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\ttype: GraphQLNamedType,\n\tfield: GraphQLField<unknown, unknown>,\n\tselection: FieldNode,\n\tfieldName: string,\n\tfieldSettingsMap: FieldSettingsMap,\n) {\n\tconst args = getArgumentValues(field, selection, info.variableValues);\n\tconst customComplexity = fieldSettingsMap[type.name]?.[fieldName];\n\n\tif (customComplexity) {\n\t\treturn customComplexity({ args, ctx });\n\t}\n\n\tconst wildCardComplexity = fieldSettingsMap[type.name]?.['*'];\n\n\tif (wildCardComplexity) {\n\t\treturn wildCardComplexity({ args, ctx });\n\t}\n}\n\nexport function registerFieldSettingsSetter<Context, Args>(\n\ttype: string,\n\tfield: string,\n\tfn: GetFieldSettings<Context, Args>,\n\tmap: FieldSettingsMap,\n) {\n\tmap[type] ??= {};\n\tmap[type][field] = fn;\n}\n","import { type GetComplexityError, getDefaultComplexityError } from './complexity-errors.ts';\nimport type { GetComplexityLimit } from './complexity-limits.ts';\n\n/**\n * Configuration options for the complexity extension.\n */\nexport interface ComplexityExtensionOptions<Context> {\n\t/** Static limits or function to determine limits based on context */\n\tlimit?: GetComplexityLimit<Context>;\n\t/**\n\t * Base complexity score for fields\n\t * @defaultValue 1\n\t */\n\tdefaultComplexity?: number;\n\t/**\n\t * Multiplier applied to list fields\n\t * @defaultValue 10\n\t */\n\tdefaultListMultiplier?: number;\n\t/** Custom error message generator */\n\tcomplexityError?: GetComplexityError;\n}\n\nexport const defaultLimits = {\n\tdepth: 10,\n\tbreadth: 50,\n\tcomplexity: 1000,\n};\n\nexport type NormalizedOptions<Context> = Required<ComplexityExtensionOptions<Context>>;\n\nexport function normalizeOptions<Context>(\n\toptions: ComplexityExtensionOptions<Context>,\n): NormalizedOptions<Context> {\n\treturn {\n\t\tlimit: options.limit ?? defaultLimits,\n\t\tdefaultComplexity: options.defaultComplexity ?? 1,\n\t\tdefaultListMultiplier: options.defaultListMultiplier ?? 10,\n\t\tcomplexityError: options.complexityError ?? getDefaultComplexityError,\n\t};\n}\n","import { createContextStore } from '@baeta/core';\nimport type { ComplexityLimit } from './complexity-limits.ts';\n\nexport interface ComplexityStore {\n\tlimits: Required<ComplexityLimit>;\n\tcacheComplexity: (fn: () => Required<ComplexityLimit>) => Required<ComplexityLimit>;\n}\n\nexport const complexityStoreKey = Symbol('complexity-extension');\n\nexport const [getComplexityStore, setComplexityStoreLoader] =\n\tcreateContextStore<ComplexityStore>(complexityStoreKey);\n","import type { ComplexityLimit } from './complexity-limits.ts';\nimport { setComplexityStoreLoader } from './store.ts';\n\nexport function loadComplexityStore<T>(\n\tctx: T,\n\tgetLimits: ComplexityLimit | ((ctx: T) => ComplexityLimit | Promise<ComplexityLimit>) | undefined,\n\tdefaultLimits: Required<ComplexityLimit>,\n) {\n\tsetComplexityStoreLoader(ctx, async () => {\n\t\tconst limits = typeof getLimits === 'function' ? await getLimits(ctx) : getLimits;\n\n\t\tlet cache: Required<ComplexityLimit> | undefined;\n\n\t\tconst cacheComplexity = (fn: () => Required<ComplexityLimit>) => {\n\t\t\tif (cache) {\n\t\t\t\treturn cache;\n\t\t\t}\n\n\t\t\tcache = fn();\n\t\t\treturn cache;\n\t\t};\n\n\t\treturn {\n\t\t\tlimits: {\n\t\t\t\tdepth: limits?.depth ?? defaultLimits.depth,\n\t\t\t\tbreadth: limits?.breadth ?? defaultLimits.breadth,\n\t\t\t\tcomplexity: limits?.complexity ?? defaultLimits.complexity,\n\t\t\t},\n\t\t\tcacheComplexity,\n\t\t};\n\t});\n}\n","import type { NativeMiddleware } from '@baeta/core/sdk';\nimport { calculateComplexity } from './complexity-calculator.ts';\nimport { ComplexityErrorKind } from './complexity-errors.ts';\nimport { type ComplexityExtensionOptions, defaultLimits } from './complexity-options.ts';\nimport type { FieldSettingsMap } from './field-settings.ts';\nimport { getComplexityStore } from './store.ts';\nimport { loadComplexityStore } from './store-loader.ts';\n\nexport function createComplexityMiddleware<Result, Root, Context, Args>(\n\toptions: Required<ComplexityExtensionOptions<Context>>,\n\tfieldSettingsMap: FieldSettingsMap,\n): NativeMiddleware<Result, Root, Context, Args> {\n\treturn (next) => async (root, args, ctx, info) => {\n\t\tloadComplexityStore(ctx, options.limit, defaultLimits);\n\n\t\tconst store = await getComplexityStore(ctx);\n\n\t\tconst limits = store.limits;\n\n\t\tconst results = store.cacheComplexity(() => {\n\t\t\treturn calculateComplexity(ctx, info, fieldSettingsMap, {\n\t\t\t\tcomplexity: options.defaultComplexity,\n\t\t\t\tmultiplier: options.defaultListMultiplier,\n\t\t\t});\n\t\t});\n\n\t\tif (results.complexity > limits.complexity) {\n\t\t\tthrow options.complexityError(\n\t\t\t\tComplexityErrorKind.Complexity,\n\t\t\t\tlimits.complexity,\n\t\t\t\tresults.complexity,\n\t\t\t);\n\t\t}\n\n\t\tif (results.depth > limits.depth) {\n\t\t\tthrow options.complexityError(ComplexityErrorKind.Depth, limits.depth, results.depth);\n\t\t}\n\n\t\tif (results.breadth > limits.breadth) {\n\t\t\tthrow options.complexityError(ComplexityErrorKind.Breadth, limits.breadth, results.breadth);\n\t\t}\n\n\t\treturn next(root, args, ctx, info);\n\t};\n}\n","import './lib/global-types.ts';\n\nimport type { Extension } from '@baeta/core/sdk';\nimport { ComplexityExtension } from './lib/complexity-extension.ts';\nimport type { ComplexityExtensionOptions } from './lib/complexity-options.ts';\n\nexport {\n\tComplexityError,\n\tComplexityErrorCode,\n\tComplexityErrorKind,\n\ttype GetComplexityError,\n} from './lib/complexity-errors.ts';\nexport type { ComplexityLimit, GetComplexityLimit } from './lib/complexity-limits.ts';\nexport type { ComplexityExtensionOptions } from './lib/complexity-options.ts';\nexport type {\n\tFieldSettings,\n\tGetFieldSettings,\n\tGetFieldSettingsArgs,\n} from './lib/field-settings.ts';\n\n/**\n * Creates a complexity analysis extension for GraphQL queries.\n *\n * @param options - Configuration options for complexity analysis\n * @returns Extension factory function\n *\n * @example\n * ```typescript\n * const complexity = complexityExtension<Context>({\n * defaultComplexity: 1,\n * defaultListMultiplier: 10,\n * limit: {\n * depth: 5,\n * breadth: 10,\n * complexity: 100\n * }\n * });\n * ```\n */\nexport function complexityExtension<Ctx>(options?: ComplexityExtensionOptions<Ctx>) {\n\treturn (): Extension => new ComplexityExtension(options);\n}\n"],"mappings":"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","names":["ComplexityErrorKind","defaultLimits"]}
1
+ {"version":3,"sources":["../lib/complexity-extension.ts","../lib/complexity-calculator.ts","../utils/graphlq.ts","../utils/string.ts","../lib/complexity-errors.ts","../lib/field-settings.ts","../lib/complexity-options.ts","../lib/store.ts","../lib/store-loader.ts","../lib/complexity-middleware.ts","../index.ts"],"sourcesContent":["import {\n\tExtension,\n\ttype FieldBuilder,\n\ttype ModuleCompiler,\n\ttype SubscriptionBuilder,\n\ttype TypeBuilder,\n} from '@baeta/core/sdk';\nimport { createComplexityMiddleware } from './complexity-middleware.ts';\nimport { type ComplexityExtensionOptions, normalizeOptions } from './complexity-options.ts';\nimport {\n\ttype FieldSettingsMap,\n\ttype GetFieldSettings,\n\tregisterFieldSettingsSetter,\n} from './field-settings.ts';\n\ninterface ComplexityState {\n\tfieldSettings: GetFieldSettings<unknown, unknown>;\n}\n\ndeclare global {\n\texport namespace BaetaExtensions {\n\t\texport interface Extensions {\n\t\t\tcomplexityExtension: ComplexityExtension<unknown>;\n\t\t}\n\t}\n}\n\nexport class ComplexityExtension<Ctx> extends Extension<ComplexityState> {\n\treadonly stateKey = Symbol('complexity-settings');\n\tprivate readonly options: Required<ComplexityExtensionOptions<unknown>>;\n\n\tconstructor(options: ComplexityExtensionOptions<Ctx> = {}) {\n\t\tsuper();\n\t\tthis.options = normalizeOptions(options as ComplexityExtensionOptions<unknown>);\n\t}\n\n\tgetTypeExtensions = <Source, Context, Info>(\n\t\tbuilder: TypeBuilder<Source, Context, Info>,\n\t): BaetaExtensions.TypeExtensions<Source, Context, Info, TypeBuilder<Source, Context, Info>> => {\n\t\treturn {\n\t\t\t$complexity: (fn) => {\n\t\t\t\tconst editable = builder.edit();\n\t\t\t\tthis.setState(editable, {\n\t\t\t\t\tfieldSettings: fn as GetFieldSettings<unknown, unknown>,\n\t\t\t\t});\n\t\t\t\treturn editable.commitToMethods();\n\t\t\t},\n\t\t};\n\t};\n\n\tgetFieldExtensions = <Result, Source, Context, Args, Info>(\n\t\tbuilder: FieldBuilder<Result, Source, Context, Args, Info>,\n\t): BaetaExtensions.FieldExtensions<\n\t\tResult,\n\t\tSource,\n\t\tContext,\n\t\tArgs,\n\t\tInfo,\n\t\tFieldBuilder<Result, Source, Context, Args, Info>\n\t> => {\n\t\treturn {\n\t\t\t$complexity: (fn) => {\n\t\t\t\tconst editable = builder.edit();\n\t\t\t\tthis.setState(editable, {\n\t\t\t\t\tfieldSettings: fn as GetFieldSettings<unknown, unknown>,\n\t\t\t\t});\n\t\t\t\treturn editable.commitToMethods();\n\t\t\t},\n\t\t};\n\t};\n\n\tgetSubscriptionExtensions = <Result, Source, Context, Args, Info>(\n\t\tbuilder: SubscriptionBuilder<Result, Source, Context, Args, Info>,\n\t): BaetaExtensions.SubscriptionExtensions<\n\t\tResult,\n\t\tSource,\n\t\tContext,\n\t\tArgs,\n\t\tInfo,\n\t\tSubscriptionBuilder<Result, Source, Context, Args, Info>\n\t> => {\n\t\treturn {\n\t\t\t$complexity: (fn) => {\n\t\t\t\tconst editable = builder.edit();\n\t\t\t\tthis.setState(editable, {\n\t\t\t\t\tfieldSettings: fn as GetFieldSettings<unknown, unknown>,\n\t\t\t\t});\n\t\t\t\treturn editable.commitToMethods();\n\t\t\t},\n\t\t};\n\t};\n\n\tmutate(compilers: ModuleCompiler[]): void {\n\t\tconst fieldSettingsMap: FieldSettingsMap = {};\n\n\t\tfor (const compiler of compilers) {\n\t\t\tfor (const typeCompiler of compiler.types) {\n\t\t\t\tconst state = this.getState(typeCompiler);\n\t\t\t\tif (!state) continue;\n\t\t\t\tregisterFieldSettingsSetter(typeCompiler.type, '*', state.fieldSettings, fieldSettingsMap);\n\t\t\t\tfor (const fieldCompiler of typeCompiler.fields) {\n\t\t\t\t\tconst state = this.getState(fieldCompiler);\n\t\t\t\t\tif (!state) continue;\n\t\t\t\t\tregisterFieldSettingsSetter(\n\t\t\t\t\t\ttypeCompiler.type,\n\t\t\t\t\t\tfieldCompiler.field,\n\t\t\t\t\t\tstate.fieldSettings,\n\t\t\t\t\t\tfieldSettingsMap,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst middleware = createComplexityMiddleware<unknown, unknown, unknown, unknown, unknown>(\n\t\t\tthis.options,\n\t\t\tfieldSettingsMap,\n\t\t);\n\n\t\tfor (const compiler of compilers) {\n\t\t\tfor (const typeCompiler of compiler.types) {\n\t\t\t\tif (!['Query', 'Mutation', 'Subscription'].includes(typeCompiler.type)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tfor (const fieldCompiler of typeCompiler.fields) {\n\t\t\t\t\tfieldCompiler.addInitialMiddleware(middleware);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","/**\n * Originally based on plugin-complexity of Pothos\n * Source: https://github.com/hayes/pothos/blob/main/packages/plugin-complexity/src/calculate-complexity.ts\n * Copyright (c) 2021 Michael Hayes\n * Adapted by Baeta developers\n */\nimport {\n\ttype FieldNode,\n\ttype FragmentDefinitionNode,\n\ttype GraphQLNamedType,\n\ttype GraphQLResolveInfo,\n\tgetNamedType,\n\ttype InlineFragmentNode,\n\tisInterfaceType,\n\tisObjectType,\n\tisOutputType,\n\tKind,\n\ttype SelectionNode,\n\ttype SelectionSetNode,\n} from 'graphql';\nimport { isListOrNullableList } from '../utils/graphlq.ts';\nimport { capitalize } from '../utils/string.ts';\nimport { ComplexityError } from './complexity-errors.ts';\nimport { type FieldSettingsMap, getFieldComplexitySettings } from './field-settings.ts';\n\ninterface ComplexityDefaults {\n\tcomplexity: number;\n\tmultiplier: number;\n}\n\nexport function calculateComplexity<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\tfieldSettingsMap: FieldSettingsMap,\n\tdefaults: ComplexityDefaults,\n) {\n\tconst operationName = capitalize(info.operation.operation);\n\tconst operationType = info.schema.getType(operationName);\n\n\tif (!operationType || !isOutputType(operationType)) {\n\t\tthrow new ComplexityError(`Unsupported operation ${operationName}`);\n\t}\n\n\treturn complexityFromSelectionSet(\n\t\tctx,\n\t\tinfo,\n\t\toperationType,\n\t\tinfo.operation.selectionSet,\n\t\tfieldSettingsMap,\n\t\tdefaults,\n\t);\n}\n\nfunction complexityFromSelectionSet<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\ttype: GraphQLNamedType,\n\tselectionSet: SelectionSetNode,\n\tfieldSettingsMap: FieldSettingsMap,\n\tdefaults: ComplexityDefaults,\n) {\n\tconst result = {\n\t\tdepth: 0,\n\t\tbreadth: 0,\n\t\tcomplexity: 0,\n\t};\n\n\tfor (const selection of selectionSet.selections) {\n\t\tconst selectionResult = complexityFromSelection(\n\t\t\tctx,\n\t\t\tinfo,\n\t\t\ttype,\n\t\t\tselection,\n\t\t\tfieldSettingsMap,\n\t\t\tdefaults,\n\t\t);\n\t\tresult.complexity += selectionResult.complexity;\n\t\tresult.breadth += selectionResult.breadth;\n\t\tresult.depth = Math.max(result.depth, selectionResult.depth);\n\t}\n\n\treturn result;\n}\n\nfunction complexityFromSelection<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\ttype: GraphQLNamedType,\n\tselection: SelectionNode,\n\tfieldSettingsMap: FieldSettingsMap,\n\tdefaults: ComplexityDefaults,\n) {\n\tif (selection.kind === Kind.FIELD) {\n\t\treturn complexityFromField(ctx, info, type, selection, fieldSettingsMap, defaults);\n\t}\n\n\tif (selection.kind === Kind.FRAGMENT_SPREAD) {\n\t\tconst fragment = info.fragments[selection.name.value];\n\n\t\tif (!fragment) {\n\t\t\tthrow new ComplexityError(`Fragment ${selection.name.value} not found`);\n\t\t}\n\n\t\treturn complexityFromFragment(ctx, info, type, fragment, fieldSettingsMap, defaults);\n\t}\n\n\treturn complexityFromFragment(ctx, info, type, selection, fieldSettingsMap, defaults);\n}\n\nfunction complexityFromFragment<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\ttype: GraphQLNamedType,\n\tfragment: FragmentDefinitionNode | InlineFragmentNode,\n\tfieldSettingsMap: FieldSettingsMap,\n\tdefaults: ComplexityDefaults,\n) {\n\tconst fragmentType = fragment.typeCondition\n\t\t? info.schema.getType(fragment.typeCondition.name.value)\n\t\t: type;\n\n\tif (!isOutputType(fragmentType)) {\n\t\tthrow new ComplexityError(`Unsupported fragment type ${fragmentType}`);\n\t}\n\n\tif (!fragmentType) {\n\t\tthrow new ComplexityError(`Fragment type ${fragmentType} not found`);\n\t}\n\n\treturn complexityFromSelectionSet(\n\t\tctx,\n\t\tinfo,\n\t\tfragmentType,\n\t\tfragment.selectionSet,\n\t\tfieldSettingsMap,\n\t\tdefaults,\n\t);\n}\n\nfunction complexityFromField<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\ttype: GraphQLNamedType,\n\tselection: FieldNode,\n\tfieldSettingsMap: FieldSettingsMap,\n\tdefaults: ComplexityDefaults,\n) {\n\tconst fieldName = selection.name.value;\n\n\tconst field =\n\t\tisObjectType(type) || isInterfaceType(type) ? type.getFields()[fieldName] : undefined;\n\n\tif (!field && !fieldName.startsWith('__')) {\n\t\tthrow new ComplexityError(`Field ${fieldName} not found on type ${type.name}`);\n\t}\n\n\tif (!field) {\n\t\treturn {\n\t\t\tdepth: 1,\n\t\t\tbreadth: 1,\n\t\t\tcomplexity: 1,\n\t\t};\n\t}\n\n\tconst fieldComplexitySettings = getFieldComplexitySettings(\n\t\tctx,\n\t\tinfo,\n\t\ttype,\n\t\tfield,\n\t\tselection,\n\t\tfieldName,\n\t\tfieldSettingsMap,\n\t);\n\n\tif (fieldComplexitySettings === false) {\n\t\treturn {\n\t\t\tdepth: 0,\n\t\t\tbreadth: 0,\n\t\t\tcomplexity: 0,\n\t\t};\n\t}\n\n\tlet depth = 1;\n\tlet breadth = 1;\n\tlet complexity = 0;\n\n\tconst listMultiplier = fieldComplexitySettings?.multiplier ?? defaults.multiplier;\n\tconst multiplier = field && isListOrNullableList(field.type) ? listMultiplier : 1;\n\n\tcomplexity += (fieldComplexitySettings?.complexity ?? defaults.complexity) * multiplier;\n\n\tif (!field || !selection.selectionSet) {\n\t\treturn {\n\t\t\tdepth,\n\t\t\tbreadth,\n\t\t\tcomplexity,\n\t\t};\n\t}\n\n\tconst subSelection = complexityFromSelectionSet(\n\t\tctx,\n\t\tinfo,\n\t\tgetNamedType(field.type),\n\t\tselection.selectionSet,\n\t\tfieldSettingsMap,\n\t\tdefaults,\n\t);\n\n\tdepth += subSelection.depth;\n\tbreadth += subSelection.breadth;\n\tcomplexity += subSelection.complexity * Math.max(multiplier, 1);\n\n\treturn {\n\t\tdepth,\n\t\tbreadth,\n\t\tcomplexity,\n\t};\n}\n","import { GraphQLList, GraphQLNonNull, type GraphQLOutputType } from 'graphql';\n\nexport function isListOrNullableList(type: GraphQLOutputType): boolean {\n\tif (type instanceof GraphQLList) {\n\t\treturn true;\n\t}\n\n\tif (type instanceof GraphQLNonNull) {\n\t\treturn isListOrNullableList(type.ofType);\n\t}\n\n\treturn false;\n}\n","export function capitalize(str: string) {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n}\n","import { GraphQLError, type GraphQLErrorOptions } from 'graphql';\n\n/** Complexity error code */\nexport const ComplexityErrorCode = 'COMPLEXITY_ERROR';\n\n/**\n * Thrown when a query exceeds the complexity limits.\n */\nexport class ComplexityError extends GraphQLError {\n\tconstructor(\n\t\tmessage = \"Complexity limit exceeded! Please reduce the query's complexity.\",\n\t\toptions?: GraphQLErrorOptions,\n\t) {\n\t\tsuper(message, {\n\t\t\t...options,\n\t\t\textensions: {\n\t\t\t\tcode: ComplexityErrorCode,\n\t\t\t\t...options?.extensions,\n\t\t\t},\n\t\t});\n\t}\n}\n\n/**\n * Types of complexity validation errors that can occur during query analysis.\n */\nexport const ComplexityErrorKind = {\n\t/** Query exceeds maximum allowed depth */\n\tDepth: 'DepthExceeded',\n\t/** Query exceeds maximum allowed breadth (fields per level) */\n\tBreadth: 'BreadthExceeded',\n\t/** Query exceeds total complexity score limit */\n\tComplexity: 'ComplexityExceeded',\n};\n\ntype ComplexityErrorKind = (typeof ComplexityErrorKind)[keyof typeof ComplexityErrorKind];\n\n/**\n * Function type for creating custom complexity error messages.\n *\n * @param kind - The type of complexity limit that was exceeded\n * @param limits - The maximum allowed value\n * @param results - The actual value that exceeded the limit\n * @returns A GraphQL error with a custom message\n */\nexport type GetComplexityError = (\n\tkind: ComplexityErrorKind,\n\tlimits: number,\n\tresults: number,\n) => GraphQLError;\n\nexport function getDefaultComplexityError(\n\tkind: ComplexityErrorKind,\n\tlimit: number,\n\tresult: number,\n): GraphQLError {\n\tif (kind === ComplexityErrorKind.Depth) {\n\t\treturn new ComplexityError(`Depth limit of ${limit} exceeded, got: ${result}`, {\n\t\t\textensions: {\n\t\t\t\tkind: ComplexityErrorKind.Depth,\n\t\t\t\tlimit,\n\t\t\t\tgot: result,\n\t\t\t},\n\t\t});\n\t}\n\n\tif (kind === ComplexityErrorKind.Breadth) {\n\t\treturn new ComplexityError(`Breadth limit of ${limit} exceeded, got: ${result}`, {\n\t\t\textensions: {\n\t\t\t\tkind: ComplexityErrorKind.Breadth,\n\t\t\t\tlimit,\n\t\t\t\tgot: result,\n\t\t\t},\n\t\t});\n\t}\n\n\tif (kind === ComplexityErrorKind.Complexity) {\n\t\treturn new ComplexityError(`Complexity limit of ${limit} exceeded, got: ${result}`, {\n\t\t\textensions: {\n\t\t\t\tkind: ComplexityErrorKind.Complexity,\n\t\t\t\tlimit,\n\t\t\t\tgot: result,\n\t\t\t},\n\t\t});\n\t}\n\n\tthrow new Error('Unknown complexity error kind');\n}\n","import {\n\ttype FieldNode,\n\ttype GraphQLField,\n\ttype GraphQLNamedType,\n\ttype GraphQLResolveInfo,\n\tgetArgumentValues,\n} from 'graphql';\n\nexport type FieldSettingsMap = Record<\n\tstring,\n\tRecord<string, GetFieldSettings<unknown, unknown> | undefined> | undefined\n>;\n\n/**\n * Configuration for field complexity calculation.\n */\nexport type FieldSettings = {\n\tcomplexity?: number;\n\tmultiplier?: number;\n};\n\n/**\n * Arguments passed to field settings functions.\n */\nexport type GetFieldSettingsArgs<Context, Args> = {\n\t/** Arguments passed to the GraphQL field */\n\targs: Args;\n\t/** Request context */\n\tctx: Context;\n};\n\n/**\n * Function to determine complexity settings for a field.\n * Returns either field settings or false to disable complexity calculation.\n *\n * @param params - Object containing field arguments and context\n * @returns Field settings object or false\n */\nexport type GetFieldSettings<Context, Args> = (\n\tparams: GetFieldSettingsArgs<Context, Args>,\n) => FieldSettings | false;\n\nexport function getFieldComplexitySettings<Context>(\n\tctx: Context,\n\tinfo: GraphQLResolveInfo,\n\ttype: GraphQLNamedType,\n\tfield: GraphQLField<unknown, unknown>,\n\tselection: FieldNode,\n\tfieldName: string,\n\tfieldSettingsMap: FieldSettingsMap,\n) {\n\tconst args = getArgumentValues(field, selection, info.variableValues);\n\tconst customComplexity = fieldSettingsMap[type.name]?.[fieldName];\n\n\tif (customComplexity) {\n\t\treturn customComplexity({ args, ctx });\n\t}\n\n\tconst wildCardComplexity = fieldSettingsMap[type.name]?.['*'];\n\n\tif (wildCardComplexity) {\n\t\treturn wildCardComplexity({ args, ctx });\n\t}\n}\n\nexport function registerFieldSettingsSetter<Context, Args>(\n\ttype: string,\n\tfield: string,\n\tfn: GetFieldSettings<Context, Args>,\n\tmap: FieldSettingsMap,\n) {\n\tmap[type] ??= {};\n\tmap[type][field] = fn as GetFieldSettings<unknown, unknown>;\n}\n","import { type GetComplexityError, getDefaultComplexityError } from './complexity-errors.ts';\nimport type { GetComplexityLimit } from './complexity-limits.ts';\n\n/**\n * Configuration options for the complexity extension.\n */\nexport interface ComplexityExtensionOptions<Context> {\n\t/** Static limits or function to determine limits based on context */\n\tlimit?: GetComplexityLimit<Context>;\n\t/**\n\t * Base complexity score for fields\n\t * @defaultValue 1\n\t */\n\tdefaultComplexity?: number;\n\t/**\n\t * Multiplier applied to list fields\n\t * @defaultValue 10\n\t */\n\tdefaultListMultiplier?: number;\n\t/** Custom error message generator */\n\tcomplexityError?: GetComplexityError;\n}\n\nexport const defaultLimits = {\n\tdepth: 10,\n\tbreadth: 50,\n\tcomplexity: 1000,\n};\n\nexport type NormalizedOptions = Required<ComplexityExtensionOptions<unknown>>;\n\nexport function normalizeOptions(options: ComplexityExtensionOptions<unknown>): NormalizedOptions {\n\treturn {\n\t\tlimit: options.limit ?? defaultLimits,\n\t\tdefaultComplexity: options.defaultComplexity ?? 1,\n\t\tdefaultListMultiplier: options.defaultListMultiplier ?? 10,\n\t\tcomplexityError: options.complexityError ?? getDefaultComplexityError,\n\t};\n}\n","import { createContextStore } from '@baeta/core';\nimport type { ComplexityLimit } from './complexity-limits.ts';\n\nexport interface ComplexityStore {\n\tlimits: Required<ComplexityLimit>;\n\tcacheComplexity: (fn: () => Required<ComplexityLimit>) => Required<ComplexityLimit>;\n}\n\nexport const complexityStoreKey = Symbol('complexity-extension');\n\nexport const [getComplexityStore, setComplexityStoreLoader] =\n\tcreateContextStore<ComplexityStore>(complexityStoreKey);\n","import type { ComplexityLimit } from './complexity-limits.ts';\nimport { setComplexityStoreLoader } from './store.ts';\n\nexport function loadComplexityStore<T>(\n\tctx: T,\n\tgetLimits:\n\t\t| ComplexityLimit\n\t\t| ((ctx: T) => ComplexityLimit | PromiseLike<ComplexityLimit>)\n\t\t| undefined,\n\tdefaultLimits: Required<ComplexityLimit>,\n) {\n\tsetComplexityStoreLoader(ctx, async () => {\n\t\tconst limits = typeof getLimits === 'function' ? await getLimits(ctx) : getLimits;\n\n\t\tlet cache: Required<ComplexityLimit> | undefined;\n\n\t\tconst cacheComplexity = (fn: () => Required<ComplexityLimit>) => {\n\t\t\tif (cache) {\n\t\t\t\treturn cache;\n\t\t\t}\n\n\t\t\tcache = fn();\n\t\t\treturn cache;\n\t\t};\n\n\t\treturn {\n\t\t\tlimits: {\n\t\t\t\tdepth: limits?.depth ?? defaultLimits.depth,\n\t\t\t\tbreadth: limits?.breadth ?? defaultLimits.breadth,\n\t\t\t\tcomplexity: limits?.complexity ?? defaultLimits.complexity,\n\t\t\t},\n\t\t\tcacheComplexity,\n\t\t};\n\t});\n}\n","import type { Middleware } from '@baeta/core';\nimport type { GraphQLResolveInfo } from 'graphql';\nimport { calculateComplexity } from './complexity-calculator.ts';\nimport { ComplexityErrorKind } from './complexity-errors.ts';\nimport { type ComplexityExtensionOptions, defaultLimits } from './complexity-options.ts';\nimport type { FieldSettingsMap } from './field-settings.ts';\nimport { getComplexityStore } from './store.ts';\nimport { loadComplexityStore } from './store-loader.ts';\n\nexport function createComplexityMiddleware<Result, Root, Context, Args, Info>(\n\toptions: Required<ComplexityExtensionOptions<Context>>,\n\tfieldSettingsMap: FieldSettingsMap,\n): Middleware<Result, Root, Context, Args, Info> {\n\treturn async (next, params) => {\n\t\tloadComplexityStore(params.ctx, options.limit, defaultLimits);\n\n\t\tconst store = await getComplexityStore(params.ctx);\n\n\t\tconst limits = store.limits;\n\n\t\tconst results = store.cacheComplexity(() => {\n\t\t\treturn calculateComplexity(params.ctx, params.info as GraphQLResolveInfo, fieldSettingsMap, {\n\t\t\t\tcomplexity: options.defaultComplexity,\n\t\t\t\tmultiplier: options.defaultListMultiplier,\n\t\t\t});\n\t\t});\n\n\t\tif (results.complexity > limits.complexity) {\n\t\t\tthrow options.complexityError(\n\t\t\t\tComplexityErrorKind.Complexity,\n\t\t\t\tlimits.complexity,\n\t\t\t\tresults.complexity,\n\t\t\t);\n\t\t}\n\n\t\tif (results.depth > limits.depth) {\n\t\t\tthrow options.complexityError(ComplexityErrorKind.Depth, limits.depth, results.depth);\n\t\t}\n\n\t\tif (results.breadth > limits.breadth) {\n\t\t\tthrow options.complexityError(ComplexityErrorKind.Breadth, limits.breadth, results.breadth);\n\t\t}\n\n\t\treturn next();\n\t};\n}\n","import './lib/global-types.ts';\n\nimport { ComplexityExtension } from './lib/complexity-extension.ts';\nimport type { ComplexityExtensionOptions } from './lib/complexity-options.ts';\n\nexport {\n\tComplexityError,\n\tComplexityErrorCode,\n\tComplexityErrorKind,\n\ttype GetComplexityError,\n} from './lib/complexity-errors.ts';\nexport type { ComplexityLimit, GetComplexityLimit } from './lib/complexity-limits.ts';\nexport type { ComplexityExtensionOptions } from './lib/complexity-options.ts';\nexport type {\n\tFieldSettings,\n\tGetFieldSettings,\n\tGetFieldSettingsArgs,\n} from './lib/field-settings.ts';\n\n/**\n * Creates a complexity analysis extension for GraphQL queries.\n *\n * @param options - Configuration options for complexity analysis\n * @returns Extension factory function\n *\n * @example\n * ```typescript\n * const complexity = complexityExtension<Context>({\n * defaultComplexity: 1,\n * defaultListMultiplier: 10,\n * limit: {\n * depth: 5,\n * breadth: 10,\n * complexity: 100\n * }\n * });\n * ```\n */\nexport function complexityExtension<Ctx>(options?: ComplexityExtensionOptions<Ctx>) {\n\treturn new ComplexityExtension(options);\n}\n"],"mappings":"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","names":["defaultLimits","state"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baeta/extension-complexity",
3
- "version": "1.0.11",
3
+ "version": "2.0.0-next.1",
4
4
  "keywords": [
5
5
  "baeta",
6
6
  "graphql",
@@ -45,18 +45,18 @@
45
45
  },
46
46
  "devDependencies": {
47
47
  "@baeta/builder": "^0.0.0",
48
- "@baeta/core": "^1.0.11",
48
+ "@baeta/core": "^2.0.0-next.1",
49
49
  "@baeta/testing": "^0.0.0",
50
50
  "@baeta/tsconfig": "^0.0.0",
51
51
  "graphql": "^16.11.0",
52
- "typescript": "^5.8.3"
52
+ "typescript": "^5.9.3"
53
53
  },
54
54
  "peerDependencies": {
55
- "@baeta/core": "^1.0.11",
55
+ "@baeta/core": "^2.0.0-next.1",
56
56
  "graphql": "^16.6.0"
57
57
  },
58
58
  "engines": {
59
- "node": ">=22.12.0"
59
+ "node": ">=22.20.0"
60
60
  },
61
61
  "publishConfig": {
62
62
  "access": "public",
package/dist/index.d.ts DELETED
@@ -1,173 +0,0 @@
1
- import { Extension } from '@baeta/core/sdk';
2
- import { GraphQLError, GraphQLErrorOptions } from 'graphql';
3
-
4
- /**
5
- * Configuration for field complexity calculation.
6
- */
7
- type FieldSettings = {
8
- complexity?: number;
9
- multiplier?: number;
10
- };
11
- /**
12
- * Arguments passed to field settings functions.
13
- */
14
- type GetFieldSettingsArgs<Context, Args> = {
15
- /** Arguments passed to the GraphQL field */
16
- args: Args;
17
- /** Request context */
18
- ctx: Context;
19
- };
20
- /**
21
- * Function to determine complexity settings for a field.
22
- * Returns either field settings or false to disable complexity calculation.
23
- *
24
- * @param params - Object containing field arguments and context
25
- * @returns Field settings object or false
26
- */
27
- type GetFieldSettings<Context, Args> = (params: GetFieldSettingsArgs<Context, Args>) => FieldSettings | false;
28
-
29
- /** biome-ignore-all lint/correctness/noUnusedVariables: arguments used for inference */
30
-
31
- declare global {
32
- export namespace BaetaExtensions {
33
- interface ResolverExtensions<Result, Root, Context, Args> {
34
- /**
35
- * Configures complexity calculation for a type field.
36
- *
37
- * @param fn - Function to determine complexity settings
38
- *
39
- * @example
40
- * ```typescript
41
- * Query.users.$complexity(({ args }) => ({
42
- * complexity: 1,
43
- * multiplier: args.limit || 10
44
- * }));
45
- *
46
- * // Disable complexity calculation
47
- * Query.simple.$complexity(() => false);
48
- * ```
49
- */
50
- $complexity: (fn: GetFieldSettings<Context, Args>) => void;
51
- }
52
- interface TypeExtensions<Root, Context> {
53
- /**
54
- * Configures complexity calculation for all fields of a type.
55
- *
56
- * @param fn - Function to determine complexity settings
57
- *
58
- * @example
59
- * ```typescript
60
- * User.$complexity(() => ({
61
- * complexity: 2, // Higher base complexity for all User fields
62
- * multiplier: 5
63
- * }));
64
- * ```
65
- */
66
- $complexity: (fn: GetFieldSettings<Context, unknown>) => void;
67
- }
68
- interface SubscriptionExtensions<Root, Context, Args> {
69
- /**
70
- * Configures complexity calculation for subscription fields.
71
- *
72
- * @param fn - Function to determine complexity settings
73
- *
74
- * @example
75
- * ```typescript
76
- * Subscription.userUpdates.$complexity(({ args }) => ({
77
- * complexity: 5,
78
- * multiplier: args.batchSize || 1
79
- * }));
80
- * ```
81
- */
82
- $complexity: (fn: GetFieldSettings<Context, Args>) => void;
83
- }
84
- }
85
- }
86
-
87
- /** Complexity error code */
88
- declare const ComplexityErrorCode = "COMPLEXITY_ERROR";
89
- /**
90
- * Thrown when a query exceeds the complexity limits.
91
- */
92
- declare class ComplexityError extends GraphQLError {
93
- constructor(message?: string, options?: GraphQLErrorOptions);
94
- }
95
- /**
96
- * Types of complexity validation errors that can occur during query analysis.
97
- */
98
- declare enum ComplexityErrorKind {
99
- /** Query exceeds maximum allowed depth */
100
- Depth = "DepthExceeded",
101
- /** Query exceeds maximum allowed breadth (fields per level) */
102
- Breadth = "BreadthExceeded",
103
- /** Query exceeds total complexity score limit */
104
- Complexity = "ComplexityExceeded"
105
- }
106
- /**
107
- * Function type for creating custom complexity error messages.
108
- *
109
- * @param kind - The type of complexity limit that was exceeded
110
- * @param limits - The maximum allowed value
111
- * @param results - The actual value that exceeded the limit
112
- * @returns A GraphQL error with a custom message
113
- */
114
- type GetComplexityError = (kind: ComplexityErrorKind, limits: number, results: number) => GraphQLError;
115
-
116
- /**
117
- * Configuration for query complexity limits.
118
- */
119
- interface ComplexityLimit {
120
- /** Maximum allowed query depth */
121
- depth?: number;
122
- /** Maximum allowed fields per level */
123
- breadth?: number;
124
- /** Maximum allowed total complexity score */
125
- complexity?: number;
126
- }
127
- /**
128
- * Function to determine complexity limits, can be static or context-based.
129
- */
130
- type GetComplexityLimit<Context> = ComplexityLimit | ((ctx: Context) => ComplexityLimit | Promise<ComplexityLimit>);
131
-
132
- /**
133
- * Configuration options for the complexity extension.
134
- */
135
- interface ComplexityExtensionOptions<Context> {
136
- /** Static limits or function to determine limits based on context */
137
- limit?: GetComplexityLimit<Context>;
138
- /**
139
- * Base complexity score for fields
140
- * @defaultValue 1
141
- */
142
- defaultComplexity?: number;
143
- /**
144
- * Multiplier applied to list fields
145
- * @defaultValue 10
146
- */
147
- defaultListMultiplier?: number;
148
- /** Custom error message generator */
149
- complexityError?: GetComplexityError;
150
- }
151
-
152
- /**
153
- * Creates a complexity analysis extension for GraphQL queries.
154
- *
155
- * @param options - Configuration options for complexity analysis
156
- * @returns Extension factory function
157
- *
158
- * @example
159
- * ```typescript
160
- * const complexity = complexityExtension<Context>({
161
- * defaultComplexity: 1,
162
- * defaultListMultiplier: 10,
163
- * limit: {
164
- * depth: 5,
165
- * breadth: 10,
166
- * complexity: 100
167
- * }
168
- * });
169
- * ```
170
- */
171
- declare function complexityExtension<Ctx>(options?: ComplexityExtensionOptions<Ctx>): () => Extension;
172
-
173
- export { ComplexityError, ComplexityErrorCode, ComplexityErrorKind, type ComplexityExtensionOptions, type ComplexityLimit, type FieldSettings, type GetComplexityError, type GetComplexityLimit, type GetFieldSettings, type GetFieldSettingsArgs, complexityExtension };