graphql-query-depth-limit-esm 0.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +369 -348
- package/dist/index.cjs +557 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +273 -0
- package/dist/index.d.ts +269 -7
- package/dist/index.js +536 -9
- package/dist/index.js.map +1 -0
- package/package.json +74 -65
- package/dist/depthLimit.d.ts +0 -41
- package/dist/depthLimit.d.ts.map +0 -1
- package/dist/depthLimit.js +0 -273
- package/dist/index.d.ts.map +0 -1
- package/dist/types.d.ts +0 -25
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -1
package/package.json
CHANGED
|
@@ -1,67 +1,76 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
2
|
+
"name": "graphql-query-depth-limit-esm",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "GraphQL query depth limiting validation rule with directive support, ignore rules, and fragment cycle detection",
|
|
5
|
+
"author": "Lafitte Mehdy",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.cjs",
|
|
16
|
+
"module": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"LICENSE",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=20.0.0"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"depth-limit",
|
|
28
|
+
"dos-protection",
|
|
29
|
+
"esm",
|
|
30
|
+
"graphql",
|
|
31
|
+
"security",
|
|
32
|
+
"validation"
|
|
33
|
+
],
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/lafittemehdy/graphql-query-depth-limit-esm.git"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/lafittemehdy/graphql-query-depth-limit-esm/issues"
|
|
40
|
+
},
|
|
41
|
+
"homepage": "https://github.com/lafittemehdy/graphql-query-depth-limit-esm#readme",
|
|
42
|
+
"sideEffects": false,
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public",
|
|
45
|
+
"provenance": true
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"graphql": "^16.0.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@apollo/server": "^5.4.0",
|
|
52
|
+
"@biomejs/biome": "^2.4.0",
|
|
53
|
+
"@types/node": "^25.2.3",
|
|
54
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
55
|
+
"@vitest/ui": "^4.0.18",
|
|
56
|
+
"graphql": "^16.12.0",
|
|
57
|
+
"graphql-yoga": "^5.18.0",
|
|
58
|
+
"tsup": "^8.5.1",
|
|
59
|
+
"tsx": "^4.21.0",
|
|
60
|
+
"typescript": "^5.9.3",
|
|
61
|
+
"vitest": "^4.0.18"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsup",
|
|
65
|
+
"dev": "tsc --watch",
|
|
66
|
+
"example:apollo": "tsx examples/servers/apollo-server.ts",
|
|
67
|
+
"example:yoga": "tsx examples/servers/yoga-server.ts",
|
|
68
|
+
"lint": "biome check && tsc --noEmit",
|
|
69
|
+
"lint:fix": "biome check --write && tsc --noEmit",
|
|
70
|
+
"prepublishOnly": "pnpm run lint && pnpm run build && pnpm test",
|
|
71
|
+
"test": "vitest run",
|
|
72
|
+
"test:coverage": "vitest run --coverage",
|
|
73
|
+
"test:ui": "vitest --ui",
|
|
74
|
+
"test:watch": "vitest"
|
|
75
|
+
}
|
|
67
76
|
}
|
package/dist/depthLimit.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { type ValidationContext } from "graphql";
|
|
2
|
-
import type { DepthCallback, DepthLimitOptions } from "./types.js";
|
|
3
|
-
/**
|
|
4
|
-
* Creates a GraphQL validation rule that limits query depth.
|
|
5
|
-
*
|
|
6
|
-
* This helps prevent DoS attacks and resource exhaustion from excessively deep queries.
|
|
7
|
-
* The depth limit can be configured globally and optionally overridden per-field using
|
|
8
|
-
* the @depth directive.
|
|
9
|
-
*
|
|
10
|
-
* Security considerations:
|
|
11
|
-
* - This validator correctly handles fragments used at different depths
|
|
12
|
-
* - Circular fragment references are detected and handled per-path
|
|
13
|
-
* - Introspection fields (__typename, __schema, etc.) are automatically ignored
|
|
14
|
-
*
|
|
15
|
-
* Limitations:
|
|
16
|
-
* - Variables in @depth directives are not supported (falls back to global limit)
|
|
17
|
-
* - Field names are case-sensitive by default (use caseInsensitiveIgnore option if needed)
|
|
18
|
-
*
|
|
19
|
-
* @param maxDepth - Maximum allowed depth for queries
|
|
20
|
-
* @param options - Optional configuration (ignore rules, directive support, case sensitivity)
|
|
21
|
-
* @param callback - Optional callback invoked with depth information for all operations
|
|
22
|
-
* @returns A GraphQL validation rule function
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* ```typescript
|
|
26
|
-
* import { depthLimit } from 'graphql-query-depth-limit-esm';
|
|
27
|
-
* import { validate } from 'graphql';
|
|
28
|
-
*
|
|
29
|
-
* const validationRules = [
|
|
30
|
-
* depthLimit(5, {
|
|
31
|
-
* ignore: ['friends', /.*Connection$/],
|
|
32
|
-
* useDirective: true,
|
|
33
|
-
* caseInsensitiveIgnore: false
|
|
34
|
-
* })
|
|
35
|
-
* ];
|
|
36
|
-
*
|
|
37
|
-
* const errors = validate(schema, query, validationRules);
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export declare function depthLimit(maxDepth: number, options?: DepthLimitOptions, callback?: DepthCallback): (context: ValidationContext) => {};
|
|
41
|
-
//# sourceMappingURL=depthLimit.d.ts.map
|
package/dist/depthLimit.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"depthLimit.d.ts","sourceRoot":"","sources":["../src/depthLimit.ts"],"names":[],"mappings":"AAAA,OAAO,EAgBL,KAAK,iBAAiB,EACvB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAc,MAAM,YAAY,CAAC;AA8S/E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,EAC3B,QAAQ,CAAC,EAAE,aAAa,IAEiB,SAAS,iBAAiB,QAwDpE"}
|
package/dist/depthLimit.js
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
import { GraphQLError, getNamedType, isCompositeType, Kind, } from "graphql";
|
|
2
|
-
/**
|
|
3
|
-
* Determines whether a field should be ignored in depth calculation.
|
|
4
|
-
*
|
|
5
|
-
* @param fieldName - The name of the field to check
|
|
6
|
-
* @param ignore - Array of ignore rules (strings, RegExp, or functions)
|
|
7
|
-
* @param caseInsensitive - Whether to perform case-insensitive matching for string rules
|
|
8
|
-
* @returns True if the field should be ignored, false otherwise
|
|
9
|
-
*/
|
|
10
|
-
function shouldIgnoreField(fieldName, ignore, caseInsensitive = false) {
|
|
11
|
-
// Always ignore introspection fields
|
|
12
|
-
if (fieldName.startsWith("__")) {
|
|
13
|
-
return true;
|
|
14
|
-
}
|
|
15
|
-
if (!ignore || ignore.length === 0) {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
for (const rule of ignore) {
|
|
19
|
-
if (typeof rule === "string") {
|
|
20
|
-
const matches = caseInsensitive
|
|
21
|
-
? rule.toLowerCase() === fieldName.toLowerCase()
|
|
22
|
-
: rule === fieldName;
|
|
23
|
-
if (matches) {
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
else if (rule instanceof RegExp) {
|
|
28
|
-
if (rule.test(fieldName)) {
|
|
29
|
-
return true;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
else if (typeof rule === "function") {
|
|
33
|
-
if (rule(fieldName)) {
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Extracts the depth limit from a @depth directive on a field definition.
|
|
42
|
-
*
|
|
43
|
-
* Note: This function only supports integer literals in the directive.
|
|
44
|
-
* Variables (e.g., @depth(max: $var)) are not supported because variable
|
|
45
|
-
* values are not available during the validation phase. Directives with
|
|
46
|
-
* variables will be ignored and fall back to the global depth limit.
|
|
47
|
-
*
|
|
48
|
-
* @param field - The GraphQL field definition to check
|
|
49
|
-
* @returns The max depth from the directive, or undefined if not found/invalid
|
|
50
|
-
*/
|
|
51
|
-
function getDepthFromDirective(field) {
|
|
52
|
-
if (!field?.astNode?.directives) {
|
|
53
|
-
return undefined;
|
|
54
|
-
}
|
|
55
|
-
const depthDirective = field.astNode.directives.find((d) => d.name.value === "depth");
|
|
56
|
-
if (!depthDirective?.arguments) {
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
const maxArg = depthDirective.arguments.find((arg) => arg.name.value === "max");
|
|
60
|
-
if (maxArg?.value.kind === "IntValue") {
|
|
61
|
-
const directiveDepth = Number.parseInt(maxArg.value.value, 10);
|
|
62
|
-
if (Number.isFinite(directiveDepth) && directiveDepth >= 0) {
|
|
63
|
-
return directiveDepth;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Extracts all fragment definitions from a GraphQL document.
|
|
70
|
-
*
|
|
71
|
-
* @param definitions - Array of definition nodes from the GraphQL document
|
|
72
|
-
* @returns Map of fragment names to their definitions
|
|
73
|
-
*/
|
|
74
|
-
function getFragments(definitions) {
|
|
75
|
-
const fragments = new Map();
|
|
76
|
-
for (const definition of definitions) {
|
|
77
|
-
if (definition.kind === Kind.FRAGMENT_DEFINITION) {
|
|
78
|
-
fragments.set(definition.name.value, definition);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return fragments;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Extracts all operation definitions from a GraphQL document.
|
|
85
|
-
*
|
|
86
|
-
* @param definitions - Array of definition nodes from the GraphQL document
|
|
87
|
-
* @returns Array of operation definitions (queries, mutations, subscriptions)
|
|
88
|
-
*/
|
|
89
|
-
function getOperations(definitions) {
|
|
90
|
-
return definitions.filter((def) => def.kind === Kind.OPERATION_DEFINITION);
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Recursively calculates the depth of a GraphQL query node.
|
|
94
|
-
*
|
|
95
|
-
* This function handles fragment spreads correctly by creating an independent copy
|
|
96
|
-
* of the visited fragments set for each fragment path. This ensures:
|
|
97
|
-
* 1. Fragments used at different depths are calculated correctly
|
|
98
|
-
* 2. Circular fragment references are detected per-path, not globally
|
|
99
|
-
* 3. The same fragment can be used multiple times without miscalculation
|
|
100
|
-
*
|
|
101
|
-
* @param node - The AST node to calculate depth for
|
|
102
|
-
* @param fragments - Map of all fragment definitions in the document
|
|
103
|
-
* @param schema - GraphQL schema for type resolution
|
|
104
|
-
* @param maxDepth - Maximum allowed depth for this node
|
|
105
|
-
* @param context - Context object containing current depth, parent type, and visited fragments
|
|
106
|
-
* @param options - Options object containing configuration flags and ignore rules
|
|
107
|
-
* @returns Object containing final depth and any violation found
|
|
108
|
-
*/
|
|
109
|
-
function calculateDepth(node, fragments, schema, maxDepth, context, options) {
|
|
110
|
-
const { currentDepth, parentType, visitedFragments } = context;
|
|
111
|
-
const { useDirective, caseInsensitiveIgnore, ignore } = options;
|
|
112
|
-
if (currentDepth > maxDepth) {
|
|
113
|
-
return {
|
|
114
|
-
depth: currentDepth,
|
|
115
|
-
violation: { depth: currentDepth, maxDepth },
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
if (!node.selectionSet) {
|
|
119
|
-
return { depth: currentDepth, violation: null };
|
|
120
|
-
}
|
|
121
|
-
let maxChildDepth = currentDepth;
|
|
122
|
-
let violation = null;
|
|
123
|
-
for (const selection of node.selectionSet.selections) {
|
|
124
|
-
if (selection.kind === Kind.FIELD) {
|
|
125
|
-
const fieldNode = selection;
|
|
126
|
-
const fieldName = fieldNode.name.value;
|
|
127
|
-
if (shouldIgnoreField(fieldName, ignore, caseInsensitiveIgnore)) {
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
if (fieldNode.selectionSet) {
|
|
131
|
-
// Check for field-specific depth limit from @depth directive
|
|
132
|
-
let fieldMaxDepth = maxDepth;
|
|
133
|
-
let fieldType;
|
|
134
|
-
if (schema && parentType) {
|
|
135
|
-
const namedType = getNamedType(parentType);
|
|
136
|
-
if (isCompositeType(namedType) && "getFields" in namedType) {
|
|
137
|
-
const fieldDef = namedType.getFields()[fieldName];
|
|
138
|
-
if (fieldDef) {
|
|
139
|
-
fieldType = fieldDef.type;
|
|
140
|
-
if (useDirective) {
|
|
141
|
-
const directiveDepth = getDepthFromDirective(fieldDef);
|
|
142
|
-
if (directiveDepth !== undefined) {
|
|
143
|
-
fieldMaxDepth = directiveDepth;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const result = calculateDepth(fieldNode, fragments, schema, fieldMaxDepth, {
|
|
150
|
-
currentDepth: currentDepth + 1,
|
|
151
|
-
parentType: fieldType,
|
|
152
|
-
visitedFragments,
|
|
153
|
-
}, options);
|
|
154
|
-
if (result.violation && !violation) {
|
|
155
|
-
violation = result.violation;
|
|
156
|
-
}
|
|
157
|
-
maxChildDepth = Math.max(maxChildDepth, result.depth);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
else if (selection.kind === Kind.FRAGMENT_SPREAD) {
|
|
161
|
-
const spreadNode = selection;
|
|
162
|
-
const fragmentName = spreadNode.name.value;
|
|
163
|
-
// Create a copy of visitedFragments for this path to correctly handle
|
|
164
|
-
// fragments used at different depths. This prevents the bug where a fragment
|
|
165
|
-
// used multiple times would only be calculated based on first occurrence.
|
|
166
|
-
const fragmentVisited = new Set(visitedFragments);
|
|
167
|
-
if (fragmentVisited.has(fragmentName)) {
|
|
168
|
-
// Fragment cycle detected - skip to prevent infinite recursion
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
const fragment = fragments.get(fragmentName);
|
|
172
|
-
if (fragment) {
|
|
173
|
-
fragmentVisited.add(fragmentName);
|
|
174
|
-
const result = calculateDepth(fragment, fragments, schema, maxDepth, {
|
|
175
|
-
currentDepth,
|
|
176
|
-
parentType,
|
|
177
|
-
visitedFragments: fragmentVisited,
|
|
178
|
-
}, options);
|
|
179
|
-
if (result.violation && !violation) {
|
|
180
|
-
violation = result.violation;
|
|
181
|
-
}
|
|
182
|
-
maxChildDepth = Math.max(maxChildDepth, result.depth);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
else if (selection.kind === Kind.INLINE_FRAGMENT) {
|
|
186
|
-
const inlineFragment = selection;
|
|
187
|
-
// Inline fragments inherit the visitedFragments set since they don't have names
|
|
188
|
-
// and cannot create cycles by themselves
|
|
189
|
-
const result = calculateDepth(inlineFragment, fragments, schema, maxDepth, context, options);
|
|
190
|
-
if (result.violation && !violation) {
|
|
191
|
-
violation = result.violation;
|
|
192
|
-
}
|
|
193
|
-
maxChildDepth = Math.max(maxChildDepth, result.depth);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return { depth: maxChildDepth, violation };
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Creates a GraphQL validation rule that limits query depth.
|
|
200
|
-
*
|
|
201
|
-
* This helps prevent DoS attacks and resource exhaustion from excessively deep queries.
|
|
202
|
-
* The depth limit can be configured globally and optionally overridden per-field using
|
|
203
|
-
* the @depth directive.
|
|
204
|
-
*
|
|
205
|
-
* Security considerations:
|
|
206
|
-
* - This validator correctly handles fragments used at different depths
|
|
207
|
-
* - Circular fragment references are detected and handled per-path
|
|
208
|
-
* - Introspection fields (__typename, __schema, etc.) are automatically ignored
|
|
209
|
-
*
|
|
210
|
-
* Limitations:
|
|
211
|
-
* - Variables in @depth directives are not supported (falls back to global limit)
|
|
212
|
-
* - Field names are case-sensitive by default (use caseInsensitiveIgnore option if needed)
|
|
213
|
-
*
|
|
214
|
-
* @param maxDepth - Maximum allowed depth for queries
|
|
215
|
-
* @param options - Optional configuration (ignore rules, directive support, case sensitivity)
|
|
216
|
-
* @param callback - Optional callback invoked with depth information for all operations
|
|
217
|
-
* @returns A GraphQL validation rule function
|
|
218
|
-
*
|
|
219
|
-
* @example
|
|
220
|
-
* ```typescript
|
|
221
|
-
* import { depthLimit } from 'graphql-query-depth-limit-esm';
|
|
222
|
-
* import { validate } from 'graphql';
|
|
223
|
-
*
|
|
224
|
-
* const validationRules = [
|
|
225
|
-
* depthLimit(5, {
|
|
226
|
-
* ignore: ['friends', /.*Connection$/],
|
|
227
|
-
* useDirective: true,
|
|
228
|
-
* caseInsensitiveIgnore: false
|
|
229
|
-
* })
|
|
230
|
-
* ];
|
|
231
|
-
*
|
|
232
|
-
* const errors = validate(schema, query, validationRules);
|
|
233
|
-
* ```
|
|
234
|
-
*/
|
|
235
|
-
export function depthLimit(maxDepth, options, callback) {
|
|
236
|
-
return function depthLimitValidationRule(context) {
|
|
237
|
-
const document = context.getDocument();
|
|
238
|
-
const fragments = getFragments(document.definitions);
|
|
239
|
-
const operations = getOperations(document.definitions);
|
|
240
|
-
const depths = {};
|
|
241
|
-
const schema = context.getSchema();
|
|
242
|
-
const rootTypeMap = {
|
|
243
|
-
mutation: schema.getMutationType() ?? undefined,
|
|
244
|
-
query: schema.getQueryType() ?? undefined,
|
|
245
|
-
subscription: schema.getSubscriptionType() ?? undefined,
|
|
246
|
-
};
|
|
247
|
-
for (const operation of operations) {
|
|
248
|
-
const operationName = operation.name?.value || "anonymous";
|
|
249
|
-
const visitedFragments = new Set();
|
|
250
|
-
const rootType = rootTypeMap[operation.operation];
|
|
251
|
-
const result = calculateDepth(operation, fragments, schema, maxDepth, {
|
|
252
|
-
currentDepth: 0,
|
|
253
|
-
parentType: rootType,
|
|
254
|
-
visitedFragments,
|
|
255
|
-
}, {
|
|
256
|
-
caseInsensitiveIgnore: options?.caseInsensitiveIgnore ?? false,
|
|
257
|
-
ignore: options?.ignore,
|
|
258
|
-
useDirective: options?.useDirective ?? false,
|
|
259
|
-
});
|
|
260
|
-
depths[operationName] = result.depth;
|
|
261
|
-
// Report error if depth limit was exceeded (either field-specific or global)
|
|
262
|
-
if (result.violation) {
|
|
263
|
-
context.reportError(new GraphQLError(`'${operationName}' has depth ${result.violation.depth} which exceeds maximum operation depth of ${result.violation.maxDepth}`, {
|
|
264
|
-
nodes: [operation],
|
|
265
|
-
}));
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
if (callback) {
|
|
269
|
-
callback(depths);
|
|
270
|
-
}
|
|
271
|
-
return {};
|
|
272
|
-
};
|
|
273
|
-
}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,GACX,MAAM,YAAY,CAAC"}
|
package/dist/types.d.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { ValidationRule } from "graphql";
|
|
2
|
-
export type IgnoreRule = string | RegExp | ((fieldName: string) => boolean);
|
|
3
|
-
export interface DepthLimitOptions {
|
|
4
|
-
/**
|
|
5
|
-
* Whether to perform case-insensitive matching for string-based ignore rules
|
|
6
|
-
* When true, "user" will match "User", "USER", etc.
|
|
7
|
-
* Note: GraphQL field names are case-sensitive by specification
|
|
8
|
-
* @default false
|
|
9
|
-
*/
|
|
10
|
-
caseInsensitiveIgnore?: boolean;
|
|
11
|
-
/**
|
|
12
|
-
* Fields to exclude from depth calculation
|
|
13
|
-
* Can be strings (exact match), RegExp patterns, or custom functions
|
|
14
|
-
*/
|
|
15
|
-
ignore?: IgnoreRule[];
|
|
16
|
-
/**
|
|
17
|
-
* Whether to read depth limits from @depth directive on fields
|
|
18
|
-
* When enabled, field-specific depth limits override the global maxDepth
|
|
19
|
-
* @default false
|
|
20
|
-
*/
|
|
21
|
-
useDirective?: boolean;
|
|
22
|
-
}
|
|
23
|
-
export type DepthCallback = (depths: Record<string, number>) => void;
|
|
24
|
-
export type DepthLimitFunction = (maxDepth: number, options?: DepthLimitOptions, callback?: DepthCallback) => ValidationRule;
|
|
25
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;AAE5E,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;OAGG;IACH,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;IAEtB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;AAErE,MAAM,MAAM,kBAAkB,GAAG,CAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,iBAAiB,EAC3B,QAAQ,CAAC,EAAE,aAAa,KACrB,cAAc,CAAC"}
|
package/dist/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|