@baeta/extension-complexity 0.0.3 → 0.0.5

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,24 @@
1
1
  # @baeta/extension-complexity
2
2
 
3
+ ## 0.0.5
4
+
5
+ ### Patch Changes
6
+
7
+ - [#189](https://github.com/andreisergiu98/baeta/pull/189) [`d500378`](https://github.com/andreisergiu98/baeta/commit/d500378198e0a9c48298c4242913bca8ad348228) Thanks [@andreisergiu98](https://github.com/andreisergiu98)! - add jsdocs
8
+
9
+ - Updated dependencies [[`d500378`](https://github.com/andreisergiu98/baeta/commit/d500378198e0a9c48298c4242913bca8ad348228), [`1334c2a`](https://github.com/andreisergiu98/baeta/commit/1334c2a866676c88f0f3d380b22133d81c4e98bc)]:
10
+ - @baeta/core@1.0.8
11
+
12
+ ## 0.0.4
13
+
14
+ ### Patch Changes
15
+
16
+ - [`b59db50`](https://github.com/andreisergiu98/baeta/commit/b59db501a83275ab2d964933080e688a3a5d8820) Thanks [@andreisergiu98](https://github.com/andreisergiu98)! - add readme
17
+
18
+ - Updated dependencies [[`b59db50`](https://github.com/andreisergiu98/baeta/commit/b59db501a83275ab2d964933080e688a3a5d8820)]:
19
+ - @baeta/core@0.1.5
20
+ - @baeta/errors@0.1.4
21
+
3
22
  ## 0.0.3
4
23
 
5
24
  ### Patch Changes
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Pampu Andrei
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,139 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/andreisergiu98/baeta/refs/heads/main/website/static/img/logo-baeta.svg" alt="Baeta Logo" width="150"/>
3
+ </p>
4
+
5
+ <div align="center">
6
+ <h1>Baeta</h1>
7
+ <a href="https://www.npmjs.com/package/@baeta/cli"><img src="https://img.shields.io/npm/v/@baeta/cli.svg?style=flat" /></a>
8
+ <a href="https://github.com/andreisergiu98/baeta/actions/workflows/testing.yml"><img src="https://img.shields.io/github/actions/workflow/status/andreisergiu98/baeta/testing.yml" /></a>
9
+ <a href="https://github.com/andreisergiu98/baeta/pulls"><img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" /></a>
10
+ <a href="https://github.com/andreisergiu98/baeta/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" /></a>
11
+ <br />
12
+ <br />
13
+ <a href="https://baeta.io/docs/getting-started/installation">Getting Started</a>
14
+ <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
15
+ <a href="https://www.baeta.io/">Website</a>
16
+ <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
17
+ <a href="https://baeta.io/docs/intro">Docs</a>
18
+ <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
19
+ <a href="https://github.com/andreisergiu98/baeta/tree/main/examples">Examples</a>
20
+ <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
21
+ <a href="https://discord.gg/BHFXHvyj">Discord</a>
22
+ <br />
23
+ <hr />
24
+ </div>
25
+
26
+ # What is Baeta?
27
+
28
+ Building GraphQL APIs shouldn't be complicated. **Baeta** is a modern, modular, open-source GraphQL framework designed with flexibility in mind. It follows a granular approach where you only add what you need, helping developers focus on what matters most - creating powerful, scalable APIs without the boilerplate.
29
+
30
+ ### Key Features
31
+
32
+ - **Modular Architecture**: Organize your API into manageable modules
33
+ - **Schema-First Development**: Define your API contract upfront
34
+ - **Type Safety**: Automatic code generation for type-safe development
35
+ - **Middleware & Directives**: Easy integration of custom behaviors
36
+ - **High Performance**: Built for scalability and efficiency
37
+
38
+ #### And optional extensions and plugins
39
+
40
+ - **@baeta/extension-auth**: Add powerful scope-based authorization
41
+ - **@baeta/extension-cache**: Implement automatic caching with simple update patterns
42
+ - ... and more!
43
+
44
+ ## Why use Baeta?
45
+
46
+ Baeta makes it easy to build better GraphQL APIs while staying flexible. Here's how:
47
+
48
+ **Granular and Progressive:** Start small and add features as you need them. Whether you're building a simple API or a complex system, Baeta scales with your needs.
49
+
50
+ **Modular architecture:** Baeta's modular design allows you to organize your GraphQL API into smaller, more manageable modules that can be added or removed as needed. This makes it easier to maintain and scale your API over time.
51
+
52
+ **Schema-first approach:** With Baeta, you define your schema first, and then logic and resolvers. This approach ensures a consistent and well-defined API for your clients and reduces boilerplate code.
53
+
54
+ ## How it Works
55
+
56
+ #### 1. Define your schema
57
+
58
+ ```graphql
59
+ type User {
60
+ id: ID!
61
+ name: String!
62
+ email: String!
63
+ age: Int
64
+ }
65
+
66
+ input UserWhereUnique {
67
+ id: ID
68
+ email: String
69
+ }
70
+
71
+ type Query {
72
+ user(where: UserWhereUnique!): User!
73
+ users: [User!]!
74
+ }
75
+ ```
76
+
77
+ #### 2. Implement your resolvers
78
+
79
+ ```typescript
80
+ import { getUserModule } from "./typedef";
81
+
82
+ const { Query } = getUserModule();
83
+
84
+ Query.user(({ args }) => {
85
+ return dataSource.user.find(args.where);
86
+ });
87
+
88
+ Query.users(() => {
89
+ return dataSource.user.findMany();
90
+ });
91
+ ```
92
+
93
+ #### 3. Add authorization
94
+
95
+ ```typescript
96
+ const { Query, Mutation } = getUserModule();
97
+
98
+ Query.users.$auth({
99
+ $or: {
100
+ isPublic: true,
101
+ isLoggedIn: true,
102
+ },
103
+ });
104
+ ```
105
+
106
+ #### 4. Add caching
107
+
108
+ ```typescript
109
+ import { getUserModule } from "./typedef";
110
+
111
+ const { User, Query } = getUserModule();
112
+
113
+ export const userCache = User.$createCache();
114
+
115
+ Query.user.$useCache(userCache);
116
+ Query.users.$useCache(userCache);
117
+ ```
118
+
119
+ ## Compatibility
120
+
121
+ Baeta is compatible with all GraphQL servers, which makes it easy to integrate with your existing stack. It works seamlessly with popular GraphQL server libraries such as **Graphql Yoga** and **Apollo Server**, as well as other popular tools like **Prisma**, **Drizzle** and **Kysely**.
122
+
123
+ Baeta's development tools are built for Node.js, but the runtime code is environment-agnostic. This means your Baeta applications can run anywhere JavaScript runs, including:
124
+
125
+ - Deno
126
+ - Cloudflare Workers
127
+ - AWS Lambda
128
+ - Vercel Edge Functions
129
+ - Bun
130
+ - Node.js
131
+ - Any other JavaScript runtime
132
+
133
+ ## Credits
134
+
135
+ Baeta was inspired by several amazing projects and people in the GraphQL ecosystem. Check out our [Credits page](https://baeta.io/docs/credits) to learn more about the individuals and projects that influenced Baeta's development.
136
+
137
+ ## License
138
+
139
+ Baeta is licensed under the [MIT License](./LICENSE).
package/dist/index.d.ts CHANGED
@@ -1,62 +1,171 @@
1
- import { Extension, ModuleBuilder, NativeMiddleware, ResolverMapper } from '@baeta/core/sdk';
2
- import { GraphQLError } from 'graphql';
1
+ import { Extension } from '@baeta/core/sdk';
2
+ import { GraphQLError, GraphQLErrorOptions } from 'graphql';
3
3
 
4
+ /**
5
+ * Configuration for field complexity calculation.
6
+ */
4
7
  type FieldSettings = {
5
8
  complexity?: number;
6
9
  multiplier?: number;
7
10
  };
11
+ /**
12
+ * Arguments passed to field settings functions.
13
+ */
8
14
  type GetFieldSettingsArgs<Context, Args> = {
15
+ /** Arguments passed to the GraphQL field */
9
16
  args: Args;
17
+ /** Request context */
10
18
  ctx: Context;
11
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
+ */
12
27
  type GetFieldSettings<Context, Args> = (params: GetFieldSettingsArgs<Context, Args>) => FieldSettings | false;
13
28
 
14
29
  declare global {
15
30
  export namespace BaetaExtensions {
16
31
  interface ResolverExtensions<Result, Root, Context, Args> {
32
+ /**
33
+ * Configures complexity calculation for a type field.
34
+ *
35
+ * @param fn - Function to determine complexity settings
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * Query.users.$complexity(({ args }) => ({
40
+ * complexity: 1,
41
+ * multiplier: args.limit || 10
42
+ * }));
43
+ *
44
+ * // Disable complexity calculation
45
+ * Query.simple.$complexity(() => false);
46
+ * ```
47
+ */
17
48
  $complexity: (fn: GetFieldSettings<Context, Args>) => void;
18
49
  }
19
50
  interface TypeExtensions<Root, Context> {
51
+ /**
52
+ * Configures complexity calculation for all fields of a type.
53
+ *
54
+ * @param fn - Function to determine complexity settings
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * User.$complexity(() => ({
59
+ * complexity: 2, // Higher base complexity for all User fields
60
+ * multiplier: 5
61
+ * }));
62
+ * ```
63
+ */
20
64
  $complexity: (fn: GetFieldSettings<Context, unknown>) => void;
21
65
  }
22
66
  interface SubscriptionExtensions<Root, Context, Args> {
67
+ /**
68
+ * Configures complexity calculation for subscription fields.
69
+ *
70
+ * @param fn - Function to determine complexity settings
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * Subscription.userUpdates.$complexity(({ args }) => ({
75
+ * complexity: 5,
76
+ * multiplier: args.batchSize || 1
77
+ * }));
78
+ * ```
79
+ */
23
80
  $complexity: (fn: GetFieldSettings<Context, Args>) => void;
24
81
  }
25
82
  }
26
83
  }
27
84
 
85
+ /** Complexity error code */
86
+ declare const ComplexityErrorCode = "COMPLEXITY_ERROR";
87
+ /**
88
+ * Thrown when a query exceeds the complexity limits.
89
+ */
90
+ declare class ComplexityError extends GraphQLError {
91
+ constructor(message?: string, options?: GraphQLErrorOptions);
92
+ }
93
+ /**
94
+ * Types of complexity validation errors that can occur during query analysis.
95
+ */
28
96
  declare enum ComplexityErrorKind {
97
+ /** Query exceeds maximum allowed depth */
29
98
  Depth = "DepthExceeded",
99
+ /** Query exceeds maximum allowed breadth (fields per level) */
30
100
  Breadth = "BreadthExceeded",
101
+ /** Query exceeds total complexity score limit */
31
102
  Complexity = "ComplexityExceeded"
32
103
  }
104
+ /**
105
+ * Function type for creating custom complexity error messages.
106
+ *
107
+ * @param kind - The type of complexity limit that was exceeded
108
+ * @param limits - The maximum allowed value
109
+ * @param results - The actual value that exceeded the limit
110
+ * @returns A GraphQL error with a custom message
111
+ */
33
112
  type GetComplexityError = (kind: ComplexityErrorKind, limits: number, results: number) => GraphQLError;
34
113
 
114
+ /**
115
+ * Configuration for query complexity limits.
116
+ */
35
117
  interface ComplexityLimit {
118
+ /** Maximum allowed query depth */
36
119
  depth?: number;
120
+ /** Maximum allowed fields per level */
37
121
  breadth?: number;
122
+ /** Maximum allowed total complexity score */
38
123
  complexity?: number;
39
124
  }
125
+ /**
126
+ * Function to determine complexity limits, can be static or context-based.
127
+ */
40
128
  type GetComplexityLimit<Context> = ComplexityLimit | ((ctx: Context) => ComplexityLimit | Promise<ComplexityLimit>);
41
129
 
130
+ /**
131
+ * Configuration options for the complexity extension.
132
+ */
42
133
  interface ComplexityExtensionOptions<Context> {
134
+ /** Static limits or function to determine limits based on context */
43
135
  limit?: GetComplexityLimit<Context>;
136
+ /**
137
+ * Base complexity score for fields
138
+ * @defaultValue 1
139
+ */
44
140
  defaultComplexity?: number;
141
+ /**
142
+ * Multiplier applied to list fields
143
+ * @defaultValue 10
144
+ */
45
145
  defaultListMultiplier?: number;
146
+ /** Custom error message generator */
46
147
  complexityError?: GetComplexityError;
47
148
  }
48
149
 
49
- declare class ComplexityExtension<Ctx> extends Extension {
50
- private readonly options;
51
- constructor(options?: ComplexityExtensionOptions<Ctx>);
52
- private fieldSettingsMap;
53
- getTypeExtensions: <Root, Context>(_module: ModuleBuilder, type: string) => BaetaExtensions.TypeExtensions<Root, Context>;
54
- getResolverExtensions: <Result, Root, Context, Args>(_module: ModuleBuilder, type: string, field: string) => BaetaExtensions.ResolverExtensions<Result, Root, Context, Args>;
55
- getSubscriptionExtensions: <Root, Context, Args>(_module: ModuleBuilder, field: string) => BaetaExtensions.SubscriptionExtensions<Root, Context, Args>;
56
- createComplexityMiddleware<Result, Root, Context, Args>(): NativeMiddleware<Result, Root, Context, Args>;
57
- build: (_module: ModuleBuilder, mapper: ResolverMapper) => void;
58
- }
59
-
60
- declare function complexityExtension<Ctx>(options?: ComplexityExtensionOptions<Ctx>): () => ComplexityExtension<Ctx>;
150
+ /**
151
+ * Creates a complexity analysis extension for GraphQL queries.
152
+ *
153
+ * @param options - Configuration options for complexity analysis
154
+ * @returns Extension factory function
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * const complexity = complexityExtension<Context>({
159
+ * defaultComplexity: 1,
160
+ * defaultListMultiplier: 10,
161
+ * limit: {
162
+ * depth: 5,
163
+ * breadth: 10,
164
+ * complexity: 100
165
+ * }
166
+ * });
167
+ * ```
168
+ */
169
+ declare function complexityExtension<Ctx>(options?: ComplexityExtensionOptions<Ctx>): () => Extension;
61
170
 
62
- export { ComplexityErrorKind, type ComplexityExtensionOptions, type ComplexityLimit, type GetComplexityError, type GetComplexityLimit, complexityExtension };
171
+ export { ComplexityError, ComplexityErrorCode, ComplexityErrorKind, type ComplexityExtensionOptions, type ComplexityLimit, type FieldSettings, type GetComplexityError, type GetComplexityLimit, type GetFieldSettings, type GetFieldSettingsArgs, complexityExtension };
package/dist/index.js CHANGED
@@ -4,7 +4,6 @@ import {
4
4
  } from "@baeta/core/sdk";
5
5
 
6
6
  // lib/complexity-calculator.ts
7
- import { ValidationError } from "@baeta/errors";
8
7
  import {
9
8
  Kind,
10
9
  getNamedType,
@@ -30,6 +29,57 @@ function capitalize(str) {
30
29
  return str.charAt(0).toUpperCase() + str.slice(1);
31
30
  }
32
31
 
32
+ // lib/complexity-errors.ts
33
+ import { GraphQLError } from "graphql";
34
+ var ComplexityErrorCode = "COMPLEXITY_ERROR";
35
+ 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
+ }
45
+ };
46
+ var ComplexityErrorKind = /* @__PURE__ */ ((ComplexityErrorKind2) => {
47
+ ComplexityErrorKind2["Depth"] = "DepthExceeded";
48
+ ComplexityErrorKind2["Breadth"] = "BreadthExceeded";
49
+ ComplexityErrorKind2["Complexity"] = "ComplexityExceeded";
50
+ return ComplexityErrorKind2;
51
+ })(ComplexityErrorKind || {});
52
+ function getDefaultComplexityError(kind, limit, result) {
53
+ if (kind === "DepthExceeded" /* Depth */) {
54
+ return new ComplexityError(`Depth limit of ${limit} exceeded, got: ${result}`, {
55
+ extensions: {
56
+ kind: "DepthExceeded" /* Depth */,
57
+ limit,
58
+ got: result
59
+ }
60
+ });
61
+ }
62
+ if (kind === "BreadthExceeded" /* Breadth */) {
63
+ return new ComplexityError(`Breadth limit of ${limit} exceeded, got: ${result}`, {
64
+ extensions: {
65
+ kind: "BreadthExceeded" /* Breadth */,
66
+ limit,
67
+ got: result
68
+ }
69
+ });
70
+ }
71
+ if (kind === "ComplexityExceeded" /* Complexity */) {
72
+ return new ComplexityError(`Complexity limit of ${limit} exceeded, got: ${result}`, {
73
+ extensions: {
74
+ kind: "ComplexityExceeded" /* Complexity */,
75
+ limit,
76
+ got: result
77
+ }
78
+ });
79
+ }
80
+ throw new Error("Unknown complexity error kind");
81
+ }
82
+
33
83
  // lib/field-settings.ts
34
84
  import {
35
85
  getArgumentValues
@@ -55,7 +105,7 @@ function calculateComplexity(ctx, info, fieldSettingsMap, defaults) {
55
105
  const operationName = capitalize(info.operation.operation);
56
106
  const operationType = info.schema.getType(operationName);
57
107
  if (!operationType || !isOutputType(operationType)) {
58
- throw new ValidationError(`Unsupported operation ${operationName}`);
108
+ throw new ComplexityError(`Unsupported operation ${operationName}`);
59
109
  }
60
110
  return complexityFromSelectionSet(
61
111
  ctx,
@@ -94,7 +144,7 @@ function complexityFromSelection(ctx, info, type, selection, fieldSettingsMap, d
94
144
  if (selection.kind === Kind.FRAGMENT_SPREAD) {
95
145
  const fragment = info.fragments[selection.name.value];
96
146
  if (!fragment) {
97
- throw new ValidationError(`Fragment ${selection.name.value} not found`);
147
+ throw new ComplexityError(`Fragment ${selection.name.value} not found`);
98
148
  }
99
149
  return complexityFromFragment(ctx, info, type, fragment, fieldSettingsMap, defaults);
100
150
  }
@@ -103,10 +153,10 @@ function complexityFromSelection(ctx, info, type, selection, fieldSettingsMap, d
103
153
  function complexityFromFragment(ctx, info, type, fragment, fieldSettingsMap, defaults) {
104
154
  const fragmentType = fragment.typeCondition ? info.schema.getType(fragment.typeCondition.name.value) : type;
105
155
  if (!isOutputType(fragmentType)) {
106
- throw new ValidationError(`Unsupported fragment type ${fragmentType}`);
156
+ throw new ComplexityError(`Unsupported fragment type ${fragmentType}`);
107
157
  }
108
158
  if (!fragmentType) {
109
- throw new ValidationError(`Fragment type ${fragmentType} not found`);
159
+ throw new ComplexityError(`Fragment type ${fragmentType} not found`);
110
160
  }
111
161
  return complexityFromSelectionSet(
112
162
  ctx,
@@ -121,7 +171,7 @@ function complexityFromField(ctx, info, type, selection, fieldSettingsMap, defau
121
171
  const fieldName = selection.name.value;
122
172
  const field = isObjectType(type) || isInterfaceType(type) ? type.getFields()[fieldName] : void 0;
123
173
  if (!field && !fieldName.startsWith("__")) {
124
- throw new ValidationError(`Field ${fieldName} not found on type ${type.name}`);
174
+ throw new ComplexityError(`Field ${fieldName} not found on type ${type.name}`);
125
175
  }
126
176
  if (!field) {
127
177
  return {
@@ -177,27 +227,6 @@ function complexityFromField(ctx, info, type, selection, fieldSettingsMap, defau
177
227
  };
178
228
  }
179
229
 
180
- // lib/complexity-errors.ts
181
- import { ValidationError as ValidationError2 } from "@baeta/errors";
182
- var ComplexityErrorKind = /* @__PURE__ */ ((ComplexityErrorKind2) => {
183
- ComplexityErrorKind2["Depth"] = "DepthExceeded";
184
- ComplexityErrorKind2["Breadth"] = "BreadthExceeded";
185
- ComplexityErrorKind2["Complexity"] = "ComplexityExceeded";
186
- return ComplexityErrorKind2;
187
- })(ComplexityErrorKind || {});
188
- function getDefaultComplexityError(kind, limit, result) {
189
- if (kind === "DepthExceeded" /* Depth */) {
190
- return new ValidationError2(`Depth limit of ${limit} exceeded, got: ${result}`);
191
- }
192
- if (kind === "BreadthExceeded" /* Breadth */) {
193
- return new ValidationError2(`Breadth limit of ${limit} exceeded, got: ${result}`);
194
- }
195
- if (kind === "ComplexityExceeded" /* Complexity */) {
196
- return new ValidationError2(`Complexity limit of ${limit} exceeded, got: ${result}`);
197
- }
198
- throw new Error("Unknown complexity error kind");
199
- }
200
-
201
230
  // lib/complexity-options.ts
202
231
  var defaultLimits = {
203
232
  depth: 10,
@@ -324,6 +353,8 @@ function complexityExtension(options) {
324
353
  return () => new ComplexityExtension(options);
325
354
  }
326
355
  export {
356
+ ComplexityError,
357
+ ComplexityErrorCode,
327
358
  ComplexityErrorKind,
328
359
  complexityExtension
329
360
  };
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/field-settings.ts","../lib/complexity-errors.ts","../lib/complexity-options.ts","../lib/store.ts","../lib/store-loader.ts","../index.ts"],"sourcesContent":["import {\n\tExtension,\n\ttype ModuleBuilder,\n\ttype NativeMiddleware,\n\ttype ResolverMapper,\n} from '@baeta/core/sdk';\nimport { calculateComplexity } from './complexity-calculator.ts';\nimport { ComplexityErrorKind } from './complexity-errors.ts';\nimport {\n\ttype ComplexityExtensionOptions,\n\tdefaultLimits,\n\tnormalizeOptions,\n} from './complexity-options.ts';\nimport { type FieldSettingsMap, registerFieldSettingsSetter } from './field-settings.ts';\nimport { loadComplexityStore } from './store-loader.ts';\nimport { getComplexityStore } from './store.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 (next) => async (root, args, ctx, info) => {\n\t\t\tloadComplexityStore(ctx as unknown as Ctx, this.options.limit, defaultLimits);\n\n\t\t\tconst store = await getComplexityStore(ctx);\n\n\t\t\tconst limits = store.limits;\n\n\t\t\tconst results = store.cacheComplexity(() => {\n\t\t\t\treturn calculateComplexity(ctx as unknown as Ctx, info, this.fieldSettingsMap, {\n\t\t\t\t\tcomplexity: this.options.defaultComplexity,\n\t\t\t\t\tmultiplier: this.options.defaultListMultiplier,\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tif (results.depth > limits.depth) {\n\t\t\t\tthrow this.options.complexityError(ComplexityErrorKind.Depth, limits.depth, results.depth);\n\t\t\t}\n\n\t\t\tif (results.breadth > limits.breadth) {\n\t\t\t\tthrow this.options.complexityError(\n\t\t\t\t\tComplexityErrorKind.Breadth,\n\t\t\t\t\tlimits.breadth,\n\t\t\t\t\tresults.breadth,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (results.complexity > limits.complexity) {\n\t\t\t\tthrow this.options.complexityError(\n\t\t\t\t\tComplexityErrorKind.Complexity,\n\t\t\t\t\tlimits.complexity,\n\t\t\t\t\tresults.complexity,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn next(root, args, ctx, info);\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","import { ValidationError } from '@baeta/errors';\nimport {\n\ttype FieldNode,\n\ttype FragmentDefinitionNode,\n\ttype GraphQLNamedType,\n\ttype GraphQLResolveInfo,\n\ttype InlineFragmentNode,\n\tKind,\n\ttype SelectionNode,\n\ttype SelectionSetNode,\n\tgetNamedType,\n\tisInterfaceType,\n\tisObjectType,\n\tisOutputType,\n} from 'graphql';\nimport { isListOrNullableList } from '../utils/graphlq.ts';\nimport { capitalize } from '../utils/string.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 ValidationError(`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 ValidationError(`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 ValidationError(`Unsupported fragment type ${fragmentType}`);\n\t}\n\n\tif (!fragmentType) {\n\t\tthrow new ValidationError(`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 ValidationError(`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 {\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\nexport type FieldSettings = {\n\tcomplexity?: number;\n\tmultiplier?: number;\n};\n\nexport type GetFieldSettingsArgs<Context, Args> = {\n\targs: Args;\n\tctx: Context;\n};\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 { ValidationError } from '@baeta/errors';\nimport type { GraphQLError } from 'graphql';\n\nexport enum ComplexityErrorKind {\n\tDepth = 'DepthExceeded',\n\tBreadth = 'BreadthExceeded',\n\tComplexity = 'ComplexityExceeded',\n}\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 ValidationError(`Depth limit of ${limit} exceeded, got: ${result}`);\n\t}\n\n\tif (kind === ComplexityErrorKind.Breadth) {\n\t\treturn new ValidationError(`Breadth limit of ${limit} exceeded, got: ${result}`);\n\t}\n\n\tif (kind === ComplexityErrorKind.Complexity) {\n\t\treturn new ValidationError(`Complexity limit of ${limit} exceeded, got: ${result}`);\n\t}\n\n\tthrow new Error('Unknown complexity error kind');\n}\n","import { type GetComplexityError, getDefaultComplexityError } from './complexity-errors.ts';\nimport type { GetComplexityLimit } from './complexity-limits.ts';\n\nexport interface ComplexityExtensionOptions<Context> {\n\tlimit?: GetComplexityLimit<Context>;\n\tdefaultComplexity?: number;\n\tdefaultListMultiplier?: number;\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 = 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 './lib/global-types.ts';\n\nimport { ComplexityExtension } from './lib/complexity-extension.ts';\nimport type { ComplexityExtensionOptions } from './lib/complexity-options.ts';\n\nexport { ComplexityErrorKind, type GetComplexityError } from './lib/complexity-errors.ts';\nexport type { ComplexityLimit, GetComplexityLimit } from './lib/complexity-limits.ts';\nexport type { ComplexityExtensionOptions } from './lib/complexity-options.ts';\n\nexport function complexityExtension<Ctx>(options?: ComplexityExtensionOptions<Ctx>) {\n\treturn () => new ComplexityExtension(options);\n}\n"],"mappings":"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","names":["ValidationError","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","../index.ts"],"sourcesContent":["import {\n\tExtension,\n\ttype ModuleBuilder,\n\ttype NativeMiddleware,\n\ttype ResolverMapper,\n} from '@baeta/core/sdk';\nimport { calculateComplexity } from './complexity-calculator.ts';\nimport { ComplexityErrorKind } from './complexity-errors.ts';\nimport {\n\ttype ComplexityExtensionOptions,\n\tdefaultLimits,\n\tnormalizeOptions,\n} from './complexity-options.ts';\nimport { type FieldSettingsMap, registerFieldSettingsSetter } from './field-settings.ts';\nimport { loadComplexityStore } from './store-loader.ts';\nimport { getComplexityStore } from './store.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 (next) => async (root, args, ctx, info) => {\n\t\t\tloadComplexityStore(ctx as unknown as Ctx, this.options.limit, defaultLimits);\n\n\t\t\tconst store = await getComplexityStore(ctx);\n\n\t\t\tconst limits = store.limits;\n\n\t\t\tconst results = store.cacheComplexity(() => {\n\t\t\t\treturn calculateComplexity(ctx as unknown as Ctx, info, this.fieldSettingsMap, {\n\t\t\t\t\tcomplexity: this.options.defaultComplexity,\n\t\t\t\t\tmultiplier: this.options.defaultListMultiplier,\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tif (results.depth > limits.depth) {\n\t\t\t\tthrow this.options.complexityError(ComplexityErrorKind.Depth, limits.depth, results.depth);\n\t\t\t}\n\n\t\t\tif (results.breadth > limits.breadth) {\n\t\t\t\tthrow this.options.complexityError(\n\t\t\t\t\tComplexityErrorKind.Breadth,\n\t\t\t\t\tlimits.breadth,\n\t\t\t\t\tresults.breadth,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (results.complexity > limits.complexity) {\n\t\t\t\tthrow this.options.complexityError(\n\t\t\t\t\tComplexityErrorKind.Complexity,\n\t\t\t\t\tlimits.complexity,\n\t\t\t\t\tresults.complexity,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn next(root, args, ctx, info);\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\ttype InlineFragmentNode,\n\tKind,\n\ttype SelectionNode,\n\ttype SelectionSetNode,\n\tgetNamedType,\n\tisInterfaceType,\n\tisObjectType,\n\tisOutputType,\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 = 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 './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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baeta/extension-complexity",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "keywords": [
5
5
  "baeta",
6
6
  "graphql",
@@ -44,13 +44,13 @@
44
44
  },
45
45
  "devDependencies": {
46
46
  "@baeta/builder": "^0.0.0",
47
- "@baeta/core": "^0.1.4",
47
+ "@baeta/core": "^1.0.8",
48
48
  "@baeta/tsconfig": "^0.0.0",
49
49
  "graphql": "^16.9.0",
50
50
  "typescript": "^5.7.2"
51
51
  },
52
52
  "peerDependencies": {
53
- "@baeta/core": "^0.1.4",
53
+ "@baeta/core": "^1.0.8",
54
54
  "graphql": "^16.6.0"
55
55
  },
56
56
  "engines": {
@@ -74,14 +74,17 @@
74
74
  "--experimental-transform-types"
75
75
  ]
76
76
  },
77
- "dependencies": {
78
- "@baeta/errors": "^0.1.3"
79
- },
80
77
  "typedocOptions": {
81
78
  "entryPoints": [
82
79
  "./index.ts"
83
80
  ],
84
81
  "readme": "none",
85
- "tsconfig": "./tsconfig.json"
82
+ "tsconfig": "./tsconfig.json",
83
+ "sort": [
84
+ "kind",
85
+ "instance-first",
86
+ "required-first",
87
+ "alphabetical-ignoring-documents"
88
+ ]
86
89
  }
87
90
  }