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

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,21 @@
1
1
  # @baeta/extension-complexity
2
2
 
3
+ ## 2.0.0-next.7
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies []:
8
+ - @baeta/core@2.0.0-next.7
9
+
10
+ ## 2.0.0-next.2
11
+
12
+ ### Patch Changes
13
+
14
+ - Fix broken types
15
+
16
+ - Updated dependencies []:
17
+ - @baeta/core@2.0.0-next.2
18
+
3
19
  ## 2.0.0-next.1
4
20
 
5
21
  ### Patch Changes
package/README.md CHANGED
@@ -77,43 +77,68 @@ type Query {
77
77
  #### 2. Implement your resolvers
78
78
 
79
79
  ```typescript
80
- import { getUserModule } from "./typedef";
80
+ import { UserModule } from "./typedef.ts";
81
81
 
82
- const { Query } = getUserModule();
82
+ const { Query } = UserModule;
83
83
 
84
- Query.user(({ args }) => {
84
+ const userQuery = Query.user.resolve(({ args }) => {
85
85
  return dataSource.user.find(args.where);
86
86
  });
87
87
 
88
- Query.users(() => {
88
+ const usersQuery = Query.users.resolve(() => {
89
89
  return dataSource.user.findMany();
90
90
  });
91
+
92
+ Query.$fields({
93
+ user: userQuery,
94
+ users: usersQuery,
95
+ });
91
96
  ```
92
97
 
93
98
  #### 3. Add authorization
94
99
 
95
100
  ```typescript
96
- const { Query, Mutation } = getUserModule();
97
-
98
- Query.users.$auth({
99
- $or: {
100
- isPublic: true,
101
- isLoggedIn: true,
102
- },
103
- });
101
+ import { UserModule } from "./typedef.ts";
102
+
103
+ const { Query } = UserModule;
104
+
105
+ const userQuery = Query.user
106
+ .auth({
107
+ $or: {
108
+ isPublic: true,
109
+ isLoggedIn: true,
110
+ },
111
+ })
112
+ .resolve(async ({ args }) => {
113
+ // ...
114
+ });
104
115
  ```
105
116
 
106
117
  #### 4. Add caching
107
118
 
108
119
  ```typescript
109
- import { getUserModule } from "./typedef";
110
-
111
- const { User, Query } = getUserModule();
120
+ const { Query, Mutation, User } = UserModule;
112
121
 
113
122
  export const userCache = User.$createCache();
114
123
 
115
- Query.user.$useCache(userCache);
116
- Query.users.$useCache(userCache);
124
+ const userQuery = Query.user
125
+ .auth({
126
+ // ...
127
+ })
128
+ .useCache(userCache)
129
+ .resolve(async ({ args }) => {
130
+ // ...
131
+ });
132
+
133
+ const updateUserMutation = Mutation.updateUser
134
+ .$use(async (next) => {
135
+ const user = await next();
136
+ await userCache.save(user);
137
+ return user;
138
+ })
139
+ .resolve(async ({ args }) => {
140
+ // ...
141
+ });
117
142
  ```
118
143
 
119
144
  ## Compatibility
@@ -0,0 +1,208 @@
1
+ import * as _baeta_core_sdk0 from "@baeta/core/sdk";
2
+ import { Extension, FieldBuilder, ModuleCompiler, SubscriptionBuilder, TypeBuilder } from "@baeta/core/sdk";
3
+ import { GraphQLError, GraphQLErrorOptions } from "graphql";
4
+
5
+ //#region lib/field-settings.d.ts
6
+ /**
7
+ * Configuration for field complexity calculation.
8
+ */
9
+ type FieldSettings = {
10
+ complexity?: number;
11
+ multiplier?: number;
12
+ };
13
+ /**
14
+ * Arguments passed to field settings functions.
15
+ */
16
+ type GetFieldSettingsArgs<Context, Args> = {
17
+ /** Arguments passed to the GraphQL field */
18
+ args: Args;
19
+ /** Request context */
20
+ ctx: Context;
21
+ };
22
+ /**
23
+ * Function to determine complexity settings for a field.
24
+ * Returns either field settings or false to disable complexity calculation.
25
+ *
26
+ * @param params - Object containing field arguments and context
27
+ * @returns Field settings object or false
28
+ */
29
+ type GetFieldSettings<Context, Args> = (params: GetFieldSettingsArgs<Context, Args>) => FieldSettings | false;
30
+ //#endregion
31
+ //#region lib/global-types.d.ts
32
+ declare global {
33
+ export namespace BaetaExtensions {
34
+ interface FieldExtensions<Result, Source, Context, Args, Info, Builder extends FieldBuilder<Result, Source, Context, Args, Info>> {
35
+ /**
36
+ * Configures complexity calculation for a type field.
37
+ *
38
+ * @param fn - Function to determine complexity settings
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * Query.users.$complexity((_, args) => ({
43
+ * complexity: 1,
44
+ * multiplier: args.limit || 10
45
+ * })).resolve(...);
46
+ *
47
+ * // Disable complexity calculation
48
+ * Query.simple.$complexity(() => false);
49
+ * ```
50
+ */
51
+ $complexity: (fn: GetFieldSettings<Context, Args>) => ReturnType<Builder['toMethods']>;
52
+ }
53
+ interface TypeExtensions<Source, Context, Info, Builder extends TypeBuilder<Source, Context, Info>> {
54
+ /**
55
+ * Configures complexity calculation for a type field.
56
+ *
57
+ * @param fn - Function to determine complexity settings
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * Query.users.$complexity((_, args) => ({
62
+ * complexity: 1,
63
+ * multiplier: args.limit || 10
64
+ * })).resolve(...);
65
+ *
66
+ * // Disable complexity calculation
67
+ * Query.simple.$complexity(() => false);
68
+ * ```
69
+ */
70
+ $complexity: (fn: GetFieldSettings<Context, unknown>) => ReturnType<Builder['toMethods']>;
71
+ }
72
+ interface SubscriptionExtensions<Result, Source, Context, Args, Info, Builder extends SubscriptionBuilder<Result, Source, Context, Args, Info>> {
73
+ /**
74
+ * Configures complexity calculation for a type field.
75
+ *
76
+ * @param fn - Function to determine complexity settings
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * Query.users.$complexity((_, args) => ({
81
+ * complexity: 1,
82
+ * multiplier: args.limit || 10
83
+ * })).resolve(...);
84
+ *
85
+ * // Disable complexity calculation
86
+ * Query.simple.$complexity(() => false);
87
+ * ```
88
+ */
89
+ $complexity: (fn: GetFieldSettings<Context, Args>) => ReturnType<Builder['toMethods']>;
90
+ }
91
+ }
92
+ }
93
+ //#endregion
94
+ //#region lib/complexity-errors.d.ts
95
+ /** Complexity error code */
96
+ declare const ComplexityErrorCode = "COMPLEXITY_ERROR";
97
+ /**
98
+ * Thrown when a query exceeds the complexity limits.
99
+ */
100
+ declare class ComplexityError extends GraphQLError {
101
+ constructor(message?: string, options?: GraphQLErrorOptions);
102
+ }
103
+ /**
104
+ * Types of complexity validation errors that can occur during query analysis.
105
+ */
106
+ declare const ComplexityErrorKind: {
107
+ /** Query exceeds maximum allowed depth */
108
+ Depth: string;
109
+ /** Query exceeds maximum allowed breadth (fields per level) */
110
+ Breadth: string;
111
+ /** Query exceeds total complexity score limit */
112
+ Complexity: string;
113
+ };
114
+ type ComplexityErrorKind = (typeof ComplexityErrorKind)[keyof typeof ComplexityErrorKind];
115
+ /**
116
+ * Function type for creating custom complexity error messages.
117
+ *
118
+ * @param kind - The type of complexity limit that was exceeded
119
+ * @param limits - The maximum allowed value
120
+ * @param results - The actual value that exceeded the limit
121
+ * @returns A GraphQL error with a custom message
122
+ */
123
+ type GetComplexityError = (kind: ComplexityErrorKind, limits: number, results: number) => GraphQLError;
124
+ //#endregion
125
+ //#region lib/complexity-limits.d.ts
126
+ /**
127
+ * Configuration for query complexity limits.
128
+ */
129
+ interface ComplexityLimit {
130
+ /** Maximum allowed query depth */
131
+ depth?: number;
132
+ /** Maximum allowed fields per level */
133
+ breadth?: number;
134
+ /** Maximum allowed total complexity score */
135
+ complexity?: number;
136
+ }
137
+ /**
138
+ * Function to determine complexity limits, can be static or context-based.
139
+ */
140
+ type GetComplexityLimit<Context> = ComplexityLimit | ((ctx: Context) => ComplexityLimit | PromiseLike<ComplexityLimit>);
141
+ //#endregion
142
+ //#region lib/complexity-options.d.ts
143
+ /**
144
+ * Configuration options for the complexity extension.
145
+ */
146
+ interface ComplexityExtensionOptions<Context> {
147
+ /** Static limits or function to determine limits based on context */
148
+ limit?: GetComplexityLimit<Context>;
149
+ /**
150
+ * Base complexity score for fields
151
+ * @defaultValue 1
152
+ */
153
+ defaultComplexity?: number;
154
+ /**
155
+ * Multiplier applied to list fields
156
+ * @defaultValue 10
157
+ */
158
+ defaultListMultiplier?: number;
159
+ /** Custom error message generator */
160
+ complexityError?: GetComplexityError;
161
+ }
162
+ //#endregion
163
+ //#region lib/complexity-extension.d.ts
164
+ interface ComplexityState {
165
+ fieldSettings: GetFieldSettings<unknown, unknown>;
166
+ }
167
+ declare global {
168
+ export namespace BaetaExtensions {
169
+ interface Extensions {
170
+ complexityExtension: ComplexityExtension<unknown>;
171
+ }
172
+ }
173
+ }
174
+ declare class ComplexityExtension<Ctx> extends Extension<ComplexityState> {
175
+ readonly stateKey: symbol;
176
+ private readonly options;
177
+ constructor(options?: ComplexityExtensionOptions<Ctx>);
178
+ getTypeExtensions: <Source, Context, Info>(builder: TypeBuilder<Source, Context, Info>) => BaetaExtensions.TypeExtensions<Source, Context, Info, TypeBuilder<Source, Context, Info>>;
179
+ getFieldExtensions: <Result, Source, Context, Args, Info>(builder: FieldBuilder<Result, Source, Context, Args, Info>) => BaetaExtensions.FieldExtensions<Result, Source, Context, Args, Info, FieldBuilder<Result, Source, Context, Args, Info>>;
180
+ getSubscriptionExtensions: <Result, Source, Context, Args, Info>(builder: SubscriptionBuilder<Result, Source, Context, Args, Info>) => BaetaExtensions.SubscriptionExtensions<Result, Source, Context, Args, Info, SubscriptionBuilder<Result, Source, Context, Args, Info>>;
181
+ mutate(compilers: ModuleCompiler[]): void;
182
+ protected iterateTypes(compilers: ModuleCompiler[]): Generator<_baeta_core_sdk0.TypeCompiler<unknown, unknown, unknown, _baeta_core_sdk0.FieldsResolversMap<unknown, unknown, unknown>>, void, unknown>;
183
+ }
184
+ //#endregion
185
+ //#region index.d.ts
186
+ /**
187
+ * Creates a complexity analysis extension for GraphQL queries.
188
+ *
189
+ * @param options - Configuration options for complexity analysis
190
+ * @returns Extension factory function
191
+ *
192
+ * @example
193
+ * ```typescript
194
+ * const complexity = complexityExtension<Context>({
195
+ * defaultComplexity: 1,
196
+ * defaultListMultiplier: 10,
197
+ * limit: {
198
+ * depth: 5,
199
+ * breadth: 10,
200
+ * complexity: 100
201
+ * }
202
+ * });
203
+ * ```
204
+ */
205
+ declare function complexityExtension<Ctx>(options?: ComplexityExtensionOptions<Ctx>): ComplexityExtension<Ctx>;
206
+ //#endregion
207
+ export { ComplexityError, ComplexityErrorCode, ComplexityErrorKind, type ComplexityExtensionOptions, type ComplexityLimit, type FieldSettings, type GetComplexityError, type GetComplexityLimit, type GetFieldSettings, type GetFieldSettingsArgs, complexityExtension };
208
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,391 +1,309 @@
1
- // lib/complexity-extension.ts
2
- import {
3
- Extension
4
- } from "@baeta/core/sdk";
5
-
6
- // lib/complexity-calculator.ts
7
- import {
8
- getNamedType,
9
- isInterfaceType,
10
- isObjectType,
11
- isOutputType,
12
- Kind
13
- } from "graphql";
1
+ import { Extension } from "@baeta/core/sdk";
2
+ import { GraphQLError, GraphQLList, GraphQLNonNull, Kind, getArgumentValues, getNamedType, isInterfaceType, isObjectType, isOutputType } from "graphql";
3
+ import { createContextStore } from "@baeta/core";
14
4
 
15
- // utils/graphlq.ts
16
- import { GraphQLList, GraphQLNonNull } from "graphql";
5
+ //#region utils/graphlq.ts
17
6
  function isListOrNullableList(type) {
18
- if (type instanceof GraphQLList) {
19
- return true;
20
- }
21
- if (type instanceof GraphQLNonNull) {
22
- return isListOrNullableList(type.ofType);
23
- }
24
- return false;
7
+ if (type instanceof GraphQLList) return true;
8
+ if (type instanceof GraphQLNonNull) return isListOrNullableList(type.ofType);
9
+ return false;
25
10
  }
26
11
 
27
- // utils/string.ts
12
+ //#endregion
13
+ //#region utils/string.ts
28
14
  function capitalize(str) {
29
- return str.charAt(0).toUpperCase() + str.slice(1);
15
+ return str.charAt(0).toUpperCase() + str.slice(1);
30
16
  }
31
17
 
32
- // lib/complexity-errors.ts
33
- import { GraphQLError } from "graphql";
34
- var ComplexityErrorCode = "COMPLEXITY_ERROR";
18
+ //#endregion
19
+ //#region lib/complexity-errors.ts
20
+ /** Complexity error code */
21
+ const ComplexityErrorCode = "COMPLEXITY_ERROR";
22
+ /**
23
+ * Thrown when a query exceeds the complexity limits.
24
+ */
35
25
  var ComplexityError = class extends GraphQLError {
36
- constructor(message = "Complexity limit exceeded! Please reduce the query's complexity.", options) {
37
- super(message, {
38
- ...options,
39
- extensions: {
40
- code: ComplexityErrorCode,
41
- ...options?.extensions
42
- }
43
- });
44
- }
26
+ constructor(message = "Complexity limit exceeded! Please reduce the query's complexity.", options) {
27
+ super(message, {
28
+ ...options,
29
+ extensions: {
30
+ code: ComplexityErrorCode,
31
+ ...options?.extensions
32
+ }
33
+ });
34
+ }
45
35
  };
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"
36
+ /**
37
+ * Types of complexity validation errors that can occur during query analysis.
38
+ */
39
+ const ComplexityErrorKind = {
40
+ Depth: "DepthExceeded",
41
+ Breadth: "BreadthExceeded",
42
+ Complexity: "ComplexityExceeded"
53
43
  };
54
44
  function getDefaultComplexityError(kind, limit, result) {
55
- if (kind === ComplexityErrorKind.Depth) {
56
- return new ComplexityError(`Depth limit of ${limit} exceeded, got: ${result}`, {
57
- extensions: {
58
- kind: ComplexityErrorKind.Depth,
59
- limit,
60
- got: result
61
- }
62
- });
63
- }
64
- if (kind === ComplexityErrorKind.Breadth) {
65
- return new ComplexityError(`Breadth limit of ${limit} exceeded, got: ${result}`, {
66
- extensions: {
67
- kind: ComplexityErrorKind.Breadth,
68
- limit,
69
- got: result
70
- }
71
- });
72
- }
73
- if (kind === ComplexityErrorKind.Complexity) {
74
- return new ComplexityError(`Complexity limit of ${limit} exceeded, got: ${result}`, {
75
- extensions: {
76
- kind: ComplexityErrorKind.Complexity,
77
- limit,
78
- got: result
79
- }
80
- });
81
- }
82
- throw new Error("Unknown complexity error kind");
45
+ if (kind === ComplexityErrorKind.Depth) return new ComplexityError(`Depth limit of ${limit} exceeded, got: ${result}`, { extensions: {
46
+ kind: ComplexityErrorKind.Depth,
47
+ limit,
48
+ got: result
49
+ } });
50
+ if (kind === ComplexityErrorKind.Breadth) return new ComplexityError(`Breadth limit of ${limit} exceeded, got: ${result}`, { extensions: {
51
+ kind: ComplexityErrorKind.Breadth,
52
+ limit,
53
+ got: result
54
+ } });
55
+ if (kind === ComplexityErrorKind.Complexity) return new ComplexityError(`Complexity limit of ${limit} exceeded, got: ${result}`, { extensions: {
56
+ kind: ComplexityErrorKind.Complexity,
57
+ limit,
58
+ got: result
59
+ } });
60
+ throw new Error("Unknown complexity error kind");
83
61
  }
84
62
 
85
- // lib/field-settings.ts
86
- import {
87
- getArgumentValues
88
- } from "graphql";
63
+ //#endregion
64
+ //#region lib/field-settings.ts
89
65
  function getFieldComplexitySettings(ctx, info, type, field, selection, fieldName, fieldSettingsMap) {
90
- const args = getArgumentValues(field, selection, info.variableValues);
91
- const customComplexity = fieldSettingsMap[type.name]?.[fieldName];
92
- if (customComplexity) {
93
- return customComplexity({ args, ctx });
94
- }
95
- const wildCardComplexity = fieldSettingsMap[type.name]?.["*"];
96
- if (wildCardComplexity) {
97
- return wildCardComplexity({ args, ctx });
98
- }
66
+ const args = getArgumentValues(field, selection, info.variableValues);
67
+ const customComplexity = fieldSettingsMap.get(type.name)?.get(fieldName);
68
+ if (customComplexity) return customComplexity({
69
+ args,
70
+ ctx
71
+ });
72
+ const wildCardComplexity = fieldSettingsMap.get(type.name)?.get("*");
73
+ if (wildCardComplexity) return wildCardComplexity({
74
+ args,
75
+ ctx
76
+ });
99
77
  }
100
78
  function registerFieldSettingsSetter(type, field, fn, map) {
101
- map[type] ??= {};
102
- map[type][field] = fn;
79
+ if (!map.has(type)) map.set(type, /* @__PURE__ */ new Map());
80
+ map.get(type)?.set(field, fn);
103
81
  }
104
82
 
105
- // lib/complexity-calculator.ts
83
+ //#endregion
84
+ //#region lib/complexity-calculator.ts
85
+ /**
86
+ * Originally based on plugin-complexity of Pothos
87
+ * Source: https://github.com/hayes/pothos/blob/main/packages/plugin-complexity/src/calculate-complexity.ts
88
+ * Copyright (c) 2021 Michael Hayes
89
+ * Adapted by Baeta developers
90
+ */
106
91
  function calculateComplexity(ctx, info, fieldSettingsMap, defaults) {
107
- const operationName = capitalize(info.operation.operation);
108
- const operationType = info.schema.getType(operationName);
109
- if (!operationType || !isOutputType(operationType)) {
110
- throw new ComplexityError(`Unsupported operation ${operationName}`);
111
- }
112
- return complexityFromSelectionSet(
113
- ctx,
114
- info,
115
- operationType,
116
- info.operation.selectionSet,
117
- fieldSettingsMap,
118
- defaults
119
- );
92
+ const operationName = capitalize(info.operation.operation);
93
+ const operationType = info.schema.getType(operationName);
94
+ if (!operationType || !isOutputType(operationType)) throw new ComplexityError(`Unsupported operation ${operationName}`);
95
+ return complexityFromSelectionSet(ctx, info, operationType, info.operation.selectionSet, fieldSettingsMap, defaults);
120
96
  }
121
97
  function complexityFromSelectionSet(ctx, info, type, selectionSet, fieldSettingsMap, defaults) {
122
- const result = {
123
- depth: 0,
124
- breadth: 0,
125
- complexity: 0
126
- };
127
- for (const selection of selectionSet.selections) {
128
- const selectionResult = complexityFromSelection(
129
- ctx,
130
- info,
131
- type,
132
- selection,
133
- fieldSettingsMap,
134
- defaults
135
- );
136
- result.complexity += selectionResult.complexity;
137
- result.breadth += selectionResult.breadth;
138
- result.depth = Math.max(result.depth, selectionResult.depth);
139
- }
140
- return result;
98
+ const result = {
99
+ depth: 0,
100
+ breadth: 0,
101
+ complexity: 0
102
+ };
103
+ for (const selection of selectionSet.selections) {
104
+ const selectionResult = complexityFromSelection(ctx, info, type, selection, fieldSettingsMap, defaults);
105
+ result.complexity += selectionResult.complexity;
106
+ result.breadth += selectionResult.breadth;
107
+ result.depth = Math.max(result.depth, selectionResult.depth);
108
+ }
109
+ return result;
141
110
  }
142
111
  function complexityFromSelection(ctx, info, type, selection, fieldSettingsMap, defaults) {
143
- if (selection.kind === Kind.FIELD) {
144
- return complexityFromField(ctx, info, type, selection, fieldSettingsMap, defaults);
145
- }
146
- if (selection.kind === Kind.FRAGMENT_SPREAD) {
147
- const fragment = info.fragments[selection.name.value];
148
- if (!fragment) {
149
- throw new ComplexityError(`Fragment ${selection.name.value} not found`);
150
- }
151
- return complexityFromFragment(ctx, info, type, fragment, fieldSettingsMap, defaults);
152
- }
153
- return complexityFromFragment(ctx, info, type, selection, fieldSettingsMap, defaults);
112
+ if (selection.kind === Kind.FIELD) return complexityFromField(ctx, info, type, selection, fieldSettingsMap, defaults);
113
+ if (selection.kind === Kind.FRAGMENT_SPREAD) {
114
+ const fragment = info.fragments[selection.name.value];
115
+ if (!fragment) throw new ComplexityError(`Fragment ${selection.name.value} not found`);
116
+ return complexityFromFragment(ctx, info, type, fragment, fieldSettingsMap, defaults);
117
+ }
118
+ return complexityFromFragment(ctx, info, type, selection, fieldSettingsMap, defaults);
154
119
  }
155
120
  function complexityFromFragment(ctx, info, type, fragment, fieldSettingsMap, defaults) {
156
- const fragmentType = fragment.typeCondition ? info.schema.getType(fragment.typeCondition.name.value) : type;
157
- if (!isOutputType(fragmentType)) {
158
- throw new ComplexityError(`Unsupported fragment type ${fragmentType}`);
159
- }
160
- if (!fragmentType) {
161
- throw new ComplexityError(`Fragment type ${fragmentType} not found`);
162
- }
163
- return complexityFromSelectionSet(
164
- ctx,
165
- info,
166
- fragmentType,
167
- fragment.selectionSet,
168
- fieldSettingsMap,
169
- defaults
170
- );
121
+ const fragmentType = fragment.typeCondition ? info.schema.getType(fragment.typeCondition.name.value) : type;
122
+ if (!isOutputType(fragmentType)) throw new ComplexityError(`Unsupported fragment type ${fragmentType}`);
123
+ if (!fragmentType) throw new ComplexityError(`Fragment type ${fragmentType} not found`);
124
+ return complexityFromSelectionSet(ctx, info, fragmentType, fragment.selectionSet, fieldSettingsMap, defaults);
171
125
  }
172
126
  function complexityFromField(ctx, info, type, selection, fieldSettingsMap, defaults) {
173
- const fieldName = selection.name.value;
174
- const field = isObjectType(type) || isInterfaceType(type) ? type.getFields()[fieldName] : void 0;
175
- if (!field && !fieldName.startsWith("__")) {
176
- throw new ComplexityError(`Field ${fieldName} not found on type ${type.name}`);
177
- }
178
- if (!field) {
179
- return {
180
- depth: 1,
181
- breadth: 1,
182
- complexity: 1
183
- };
184
- }
185
- const fieldComplexitySettings = getFieldComplexitySettings(
186
- ctx,
187
- info,
188
- type,
189
- field,
190
- selection,
191
- fieldName,
192
- fieldSettingsMap
193
- );
194
- if (fieldComplexitySettings === false) {
195
- return {
196
- depth: 0,
197
- breadth: 0,
198
- complexity: 0
199
- };
200
- }
201
- let depth = 1;
202
- let breadth = 1;
203
- let complexity = 0;
204
- const listMultiplier = fieldComplexitySettings?.multiplier ?? defaults.multiplier;
205
- const multiplier = field && isListOrNullableList(field.type) ? listMultiplier : 1;
206
- complexity += (fieldComplexitySettings?.complexity ?? defaults.complexity) * multiplier;
207
- if (!field || !selection.selectionSet) {
208
- return {
209
- depth,
210
- breadth,
211
- complexity
212
- };
213
- }
214
- const subSelection = complexityFromSelectionSet(
215
- ctx,
216
- info,
217
- getNamedType(field.type),
218
- selection.selectionSet,
219
- fieldSettingsMap,
220
- defaults
221
- );
222
- depth += subSelection.depth;
223
- breadth += subSelection.breadth;
224
- complexity += subSelection.complexity * Math.max(multiplier, 1);
225
- return {
226
- depth,
227
- breadth,
228
- complexity
229
- };
127
+ const fieldName = selection.name.value;
128
+ const field = isObjectType(type) || isInterfaceType(type) ? type.getFields()[fieldName] : void 0;
129
+ if (!field && !fieldName.startsWith("__")) throw new ComplexityError(`Field ${fieldName} not found on type ${type.name}`);
130
+ if (!field) return {
131
+ depth: 1,
132
+ breadth: 1,
133
+ complexity: 1
134
+ };
135
+ const fieldComplexitySettings = getFieldComplexitySettings(ctx, info, type, field, selection, fieldName, fieldSettingsMap);
136
+ if (fieldComplexitySettings === false) return {
137
+ depth: 0,
138
+ breadth: 0,
139
+ complexity: 0
140
+ };
141
+ let depth = 1;
142
+ let breadth = 1;
143
+ let complexity = 0;
144
+ const listMultiplier = fieldComplexitySettings?.multiplier ?? defaults.multiplier;
145
+ const multiplier = field && isListOrNullableList(field.type) ? listMultiplier : 1;
146
+ complexity += (fieldComplexitySettings?.complexity ?? defaults.complexity) * multiplier;
147
+ if (!field || !selection.selectionSet) return {
148
+ depth,
149
+ breadth,
150
+ complexity
151
+ };
152
+ const subSelection = complexityFromSelectionSet(ctx, info, getNamedType(field.type), selection.selectionSet, fieldSettingsMap, defaults);
153
+ depth += subSelection.depth;
154
+ breadth += subSelection.breadth;
155
+ complexity += subSelection.complexity * Math.max(multiplier, 1);
156
+ return {
157
+ depth,
158
+ breadth,
159
+ complexity
160
+ };
230
161
  }
231
162
 
232
- // lib/complexity-options.ts
233
- var defaultLimits = {
234
- depth: 10,
235
- breadth: 50,
236
- complexity: 1e3
163
+ //#endregion
164
+ //#region lib/complexity-options.ts
165
+ const defaultLimits = {
166
+ depth: 10,
167
+ breadth: 50,
168
+ complexity: 1e3
237
169
  };
238
170
  function normalizeOptions(options) {
239
- return {
240
- limit: options.limit ?? defaultLimits,
241
- defaultComplexity: options.defaultComplexity ?? 1,
242
- defaultListMultiplier: options.defaultListMultiplier ?? 10,
243
- complexityError: options.complexityError ?? getDefaultComplexityError
244
- };
171
+ return {
172
+ limit: options.limit ?? defaultLimits,
173
+ defaultComplexity: options.defaultComplexity ?? 1,
174
+ defaultListMultiplier: options.defaultListMultiplier ?? 10,
175
+ complexityError: options.complexityError ?? getDefaultComplexityError
176
+ };
245
177
  }
246
178
 
247
- // lib/store.ts
248
- import { createContextStore } from "@baeta/core";
249
- var complexityStoreKey = Symbol("complexity-extension");
250
- var [getComplexityStore, setComplexityStoreLoader] = createContextStore(complexityStoreKey);
179
+ //#endregion
180
+ //#region lib/store.ts
181
+ const complexityStoreKey = Symbol("complexity-extension");
182
+ const [getComplexityStore, setComplexityStoreLoader] = createContextStore(complexityStoreKey);
251
183
 
252
- // lib/store-loader.ts
253
- function loadComplexityStore(ctx, getLimits, defaultLimits2) {
254
- setComplexityStoreLoader(ctx, async () => {
255
- const limits = typeof getLimits === "function" ? await getLimits(ctx) : getLimits;
256
- let cache;
257
- const cacheComplexity = (fn) => {
258
- if (cache) {
259
- return cache;
260
- }
261
- cache = fn();
262
- return cache;
263
- };
264
- return {
265
- limits: {
266
- depth: limits?.depth ?? defaultLimits2.depth,
267
- breadth: limits?.breadth ?? defaultLimits2.breadth,
268
- complexity: limits?.complexity ?? defaultLimits2.complexity
269
- },
270
- cacheComplexity
271
- };
272
- });
184
+ //#endregion
185
+ //#region lib/store-loader.ts
186
+ function loadComplexityStore(ctx, getLimits, defaultLimits$1) {
187
+ setComplexityStoreLoader(ctx, async () => {
188
+ const limits = typeof getLimits === "function" ? await getLimits(ctx) : getLimits;
189
+ let cache;
190
+ const cacheComplexity = (fn) => {
191
+ if (cache) return cache;
192
+ cache = fn();
193
+ return cache;
194
+ };
195
+ return {
196
+ limits: {
197
+ depth: limits?.depth ?? defaultLimits$1.depth,
198
+ breadth: limits?.breadth ?? defaultLimits$1.breadth,
199
+ complexity: limits?.complexity ?? defaultLimits$1.complexity
200
+ },
201
+ cacheComplexity
202
+ };
203
+ });
273
204
  }
274
205
 
275
- // lib/complexity-middleware.ts
206
+ //#endregion
207
+ //#region lib/complexity-middleware.ts
276
208
  function createComplexityMiddleware(options, fieldSettingsMap) {
277
- return async (next, params) => {
278
- loadComplexityStore(params.ctx, options.limit, defaultLimits);
279
- const store = await getComplexityStore(params.ctx);
280
- const limits = store.limits;
281
- const results = store.cacheComplexity(() => {
282
- return calculateComplexity(params.ctx, params.info, fieldSettingsMap, {
283
- complexity: options.defaultComplexity,
284
- multiplier: options.defaultListMultiplier
285
- });
286
- });
287
- if (results.complexity > limits.complexity) {
288
- throw options.complexityError(
289
- ComplexityErrorKind.Complexity,
290
- limits.complexity,
291
- results.complexity
292
- );
293
- }
294
- if (results.depth > limits.depth) {
295
- throw options.complexityError(ComplexityErrorKind.Depth, limits.depth, results.depth);
296
- }
297
- if (results.breadth > limits.breadth) {
298
- throw options.complexityError(ComplexityErrorKind.Breadth, limits.breadth, results.breadth);
299
- }
300
- return next();
301
- };
209
+ return async (next, params) => {
210
+ loadComplexityStore(params.ctx, options.limit, defaultLimits);
211
+ const store = await getComplexityStore(params.ctx);
212
+ const limits = store.limits;
213
+ const results = store.cacheComplexity(() => {
214
+ return calculateComplexity(params.ctx, params.info, fieldSettingsMap, {
215
+ complexity: options.defaultComplexity,
216
+ multiplier: options.defaultListMultiplier
217
+ });
218
+ });
219
+ if (results.complexity > limits.complexity) throw options.complexityError(ComplexityErrorKind.Complexity, limits.complexity, results.complexity);
220
+ if (results.depth > limits.depth) throw options.complexityError(ComplexityErrorKind.Depth, limits.depth, results.depth);
221
+ if (results.breadth > limits.breadth) throw options.complexityError(ComplexityErrorKind.Breadth, limits.breadth, results.breadth);
222
+ return next();
223
+ };
302
224
  }
303
225
 
304
- // lib/complexity-extension.ts
226
+ //#endregion
227
+ //#region lib/complexity-extension.ts
305
228
  var ComplexityExtension = class extends Extension {
306
- stateKey = Symbol("complexity-settings");
307
- options;
308
- constructor(options = {}) {
309
- super();
310
- this.options = normalizeOptions(options);
311
- }
312
- getTypeExtensions = (builder) => {
313
- return {
314
- $complexity: (fn) => {
315
- const editable = builder.edit();
316
- this.setState(editable, {
317
- fieldSettings: fn
318
- });
319
- return editable.commitToMethods();
320
- }
321
- };
322
- };
323
- getFieldExtensions = (builder) => {
324
- return {
325
- $complexity: (fn) => {
326
- const editable = builder.edit();
327
- this.setState(editable, {
328
- fieldSettings: fn
329
- });
330
- return editable.commitToMethods();
331
- }
332
- };
333
- };
334
- getSubscriptionExtensions = (builder) => {
335
- return {
336
- $complexity: (fn) => {
337
- const editable = builder.edit();
338
- this.setState(editable, {
339
- fieldSettings: fn
340
- });
341
- return editable.commitToMethods();
342
- }
343
- };
344
- };
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(
365
- this.options,
366
- fieldSettingsMap
367
- );
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);
375
- }
376
- }
377
- }
378
- }
229
+ stateKey = Symbol("complexity-settings");
230
+ options;
231
+ constructor(options = {}) {
232
+ super();
233
+ this.options = normalizeOptions(options);
234
+ }
235
+ getTypeExtensions = (builder) => {
236
+ return { $complexity: (fn) => {
237
+ const editable = builder.edit();
238
+ this.setState(editable, { fieldSettings: fn });
239
+ return editable.commitToMethods();
240
+ } };
241
+ };
242
+ getFieldExtensions = (builder) => {
243
+ return { $complexity: (fn) => {
244
+ const editable = builder.edit();
245
+ this.setState(editable, { fieldSettings: fn });
246
+ return editable.commitToMethods();
247
+ } };
248
+ };
249
+ getSubscriptionExtensions = (builder) => {
250
+ return { $complexity: (fn) => {
251
+ const editable = builder.edit();
252
+ this.setState(editable, { fieldSettings: fn });
253
+ return editable.commitToMethods();
254
+ } };
255
+ };
256
+ mutate(compilers) {
257
+ const fieldSettingsMap = /* @__PURE__ */ new Map();
258
+ for (const typeCompiler of this.iterateTypes(compilers)) {
259
+ const typeState = this.getState(typeCompiler);
260
+ if (typeState) registerFieldSettingsSetter(typeCompiler.type, "*", typeState.fieldSettings, fieldSettingsMap);
261
+ for (const fieldCompiler of typeCompiler.fields) {
262
+ const fieldState = this.getState(fieldCompiler);
263
+ if (!fieldState) continue;
264
+ registerFieldSettingsSetter(typeCompiler.type, fieldCompiler.field, fieldState.fieldSettings, fieldSettingsMap);
265
+ }
266
+ }
267
+ const middleware = createComplexityMiddleware(this.options, fieldSettingsMap);
268
+ for (const typeCompiler of this.iterateTypes(compilers)) {
269
+ if (![
270
+ "Query",
271
+ "Mutation",
272
+ "Subscription"
273
+ ].includes(typeCompiler.type)) continue;
274
+ for (const fieldCompiler of typeCompiler.fields) fieldCompiler.addInitialMiddleware(middleware);
275
+ }
276
+ }
277
+ *iterateTypes(compilers) {
278
+ for (const compiler of compilers) for (const typeCompiler of compiler.types) yield typeCompiler;
279
+ }
379
280
  };
380
281
 
381
- // index.ts
282
+ //#endregion
283
+ //#region index.ts
284
+ /**
285
+ * Creates a complexity analysis extension for GraphQL queries.
286
+ *
287
+ * @param options - Configuration options for complexity analysis
288
+ * @returns Extension factory function
289
+ *
290
+ * @example
291
+ * ```typescript
292
+ * const complexity = complexityExtension<Context>({
293
+ * defaultComplexity: 1,
294
+ * defaultListMultiplier: 10,
295
+ * limit: {
296
+ * depth: 5,
297
+ * breadth: 10,
298
+ * complexity: 100
299
+ * }
300
+ * });
301
+ * ```
302
+ */
382
303
  function complexityExtension(options) {
383
- return new ComplexityExtension(options);
304
+ return new ComplexityExtension(options);
384
305
  }
385
- export {
386
- ComplexityError,
387
- ComplexityErrorCode,
388
- ComplexityErrorKind,
389
- complexityExtension
390
- };
306
+
307
+ //#endregion
308
+ export { ComplexityError, ComplexityErrorCode, ComplexityErrorKind, complexityExtension };
391
309
  //# sourceMappingURL=index.js.map
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 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"]}
1
+ {"version":3,"file":"index.js","names":["cache: Required<ComplexityLimit> | undefined","defaultLimits","fieldSettingsMap: FieldSettingsMap"],"sources":["../utils/graphlq.ts","../utils/string.ts","../lib/complexity-errors.ts","../lib/field-settings.ts","../lib/complexity-calculator.ts","../lib/complexity-options.ts","../lib/store.ts","../lib/store-loader.ts","../lib/complexity-middleware.ts","../lib/complexity-extension.ts","../index.ts"],"sourcesContent":["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 = Map<string, Map<string, GetFieldSettings<unknown, unknown>>>;\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.get(type.name)?.get(fieldName);\n\n\tif (customComplexity) {\n\t\treturn customComplexity({ args, ctx });\n\t}\n\n\tconst wildCardComplexity = fieldSettingsMap.get(type.name)?.get('*');\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\tif (!map.has(type)) {\n\t\tmap.set(type, new Map());\n\t}\n\tmap.get(type)?.set(field, fn as GetFieldSettings<unknown, unknown>);\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 { 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 {\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 = new Map();\n\n\t\tfor (const typeCompiler of this.iterateTypes(compilers)) {\n\t\t\tconst typeState = this.getState(typeCompiler);\n\n\t\t\tif (typeState) {\n\t\t\t\tregisterFieldSettingsSetter(\n\t\t\t\t\ttypeCompiler.type,\n\t\t\t\t\t'*',\n\t\t\t\t\ttypeState.fieldSettings,\n\t\t\t\t\tfieldSettingsMap,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tfor (const fieldCompiler of typeCompiler.fields) {\n\t\t\t\tconst fieldState = this.getState(fieldCompiler);\n\t\t\t\tif (!fieldState) continue;\n\n\t\t\t\tregisterFieldSettingsSetter(\n\t\t\t\t\ttypeCompiler.type,\n\t\t\t\t\tfieldCompiler.field,\n\t\t\t\t\tfieldState.fieldSettings,\n\t\t\t\t\tfieldSettingsMap,\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 typeCompiler of this.iterateTypes(compilers)) {\n\t\t\tif (!['Query', 'Mutation', 'Subscription'].includes(typeCompiler.type)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const fieldCompiler of typeCompiler.fields) {\n\t\t\t\tfieldCompiler.addInitialMiddleware(middleware);\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected *iterateTypes(compilers: ModuleCompiler[]) {\n\t\tfor (const compiler of compilers) {\n\t\t\tfor (const typeCompiler of compiler.types) {\n\t\t\t\tyield typeCompiler;\n\t\t\t}\n\t\t}\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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baeta/extension-complexity",
3
- "version": "2.0.0-next.1",
3
+ "version": "2.0.0-next.7",
4
4
  "keywords": [
5
5
  "baeta",
6
6
  "graphql",
@@ -37,22 +37,28 @@
37
37
  "package.json"
38
38
  ],
39
39
  "scripts": {
40
- "build": "tsup",
41
- "prepack": "prep",
42
- "postpack": "prep --clean",
43
- "test": "ava",
40
+ "build": "builder build",
41
+ "prepack": "builder prepare",
42
+ "postpack": "builder prepare --clean",
43
+ "test": "builder test",
44
+ "test:circular": "builder test-circular",
44
45
  "types": "tsc --noEmit"
45
46
  },
47
+ "ava": {
48
+ "extensions": {
49
+ "ts": "module"
50
+ }
51
+ },
46
52
  "devDependencies": {
47
53
  "@baeta/builder": "^0.0.0",
48
- "@baeta/core": "^2.0.0-next.1",
54
+ "@baeta/core": "^2.0.0-next.7",
49
55
  "@baeta/testing": "^0.0.0",
50
56
  "@baeta/tsconfig": "^0.0.0",
51
- "graphql": "^16.11.0",
57
+ "graphql": "^16.12.0",
52
58
  "typescript": "^5.9.3"
53
59
  },
54
60
  "peerDependencies": {
55
- "@baeta/core": "^2.0.0-next.1",
61
+ "@baeta/core": "^2.0.0-next.7",
56
62
  "graphql": "^16.6.0"
57
63
  },
58
64
  "engines": {
@@ -67,15 +73,6 @@
67
73
  }
68
74
  }
69
75
  },
70
- "ava": {
71
- "extensions": {
72
- "ts": "module"
73
- },
74
- "nodeArguments": [
75
- "--no-warnings",
76
- "--experimental-transform-types"
77
- ]
78
- },
79
76
  "typedocOptions": {
80
77
  "entryPoints": [
81
78
  "./index.ts"