@envelop/resource-limitations 3.0.0-alpha-36a1267.0 → 3.0.0-alpha-5b6bfa8.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ## `@envelop/resource-limitations`
2
2
 
3
- This plugins uses `extended-valiations` concept ([details here](https://github.com/dotansimha/envelop/tree/main/packages/plugins/extended-validation#envelopextended-validation)) for implemeting a resource-limitations rate-limit similar to GitHub GraphQL API (see https://docs.github.com/en/graphql/overview/resource-limitations for more details)
3
+ This plugins uses `extended-valiations` concept ([details here](https://github.com/n1ru4l/envelop/tree/main/packages/plugins/extended-validation#envelopextended-validation)) for implemeting a resource-limitations rate-limit similar to GitHub GraphQL API (see https://docs.github.com/en/graphql/overview/resource-limitations for more details)
4
4
 
5
5
  ## Getting Started
6
6
 
@@ -11,8 +11,8 @@ yarn add @envelop/resource-limitations
11
11
  ## Usage Example
12
12
 
13
13
  ```ts
14
- import { envelop } from '@envelop/core';
15
- import { useResourceLimitations } from '@envelop/resource-limitations';
14
+ import { envelop } from '@envelop/core'
15
+ import { useResourceLimitations } from '@envelop/resource-limitations'
16
16
 
17
17
  const getEnveloped = envelop({
18
18
  plugins: [
@@ -22,8 +22,8 @@ const getEnveloped = envelop({
22
22
  paginationArgumentMaximum: 100, // optional, default to 100
23
23
  paginationArgumentMinimum: 1, // optional, default to 1
24
24
  paginationArgumentScalars: ['ConnectionInt'], // optional, use if connections use a different scalar type as the argument instead of `Int`
25
- extensions: false, // set this to `true` in order to add the calculated const to the response of queries
26
- }),
27
- ],
28
- });
25
+ extensions: false // set this to `true` in order to add the calculated const to the response of queries
26
+ })
27
+ ]
28
+ })
29
29
  ```
@@ -1,19 +1,18 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- const core = require('@envelop/core');
6
- const extendedValidation = require('@envelop/extended-validation');
7
- const graphql = require('graphql');
8
- const utils = require('@graphql-tools/utils');
9
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useResourceLimitations = exports.ResourceLimitationValidationRule = exports.defaultPaginationArgumentMinimum = exports.defaultPaginationArgumentMaximum = exports.defaultNodeCostLimit = void 0;
4
+ const core_1 = require("@envelop/core");
5
+ const extended_validation_1 = require("@envelop/extended-validation");
6
+ const graphql_1 = require("@graphql-tools/graphql");
7
+ const utils_1 = require("@graphql-tools/utils");
10
8
  const getWrappedType = (graphqlType) => {
11
- if (graphqlType instanceof graphql.GraphQLList || graphqlType instanceof graphql.GraphQLNonNull) {
9
+ if (graphqlType instanceof graphql_1.GraphQLList || graphqlType instanceof graphql_1.GraphQLNonNull) {
12
10
  return getWrappedType(graphqlType.ofType);
13
11
  }
14
12
  return graphqlType;
15
13
  };
16
- const isValidArgType = (type, paginationArgumentTypes) => type === graphql.GraphQLInt || (graphql.isScalarType(type) && !!paginationArgumentTypes && paginationArgumentTypes.includes(type.name));
14
+ const isValidArgType = (type, paginationArgumentTypes) => type === graphql_1.GraphQLInt ||
15
+ ((0, graphql_1.isScalarType)(type) && !!paginationArgumentTypes && paginationArgumentTypes.includes(type.name));
17
16
  const hasFieldDefConnectionArgs = (field, argumentTypes) => {
18
17
  let hasFirst = false;
19
18
  let hasLast = false;
@@ -32,13 +31,17 @@ const hasFieldDefConnectionArgs = (field, argumentTypes) => {
32
31
  };
33
32
  const buildMissingPaginationFieldErrorMessage = (params) => `Missing pagination argument for field '${params.fieldName}'. ` +
34
33
  `Please provide ` +
35
- (params.hasFirst && params.hasLast ? "either the 'first' or 'last'" : params.hasFirst ? "the 'first'" : "the 'last'") +
34
+ (params.hasFirst && params.hasLast
35
+ ? "either the 'first' or 'last'"
36
+ : params.hasFirst
37
+ ? "the 'first'"
38
+ : "the 'last'") +
36
39
  ' field argument.';
37
40
  const buildInvalidPaginationRangeErrorMessage = (params) => `Invalid pagination argument for field ${params.fieldName}. ` +
38
41
  `The value for the '${params.argumentName}' argument must be an integer within ${params.paginationArgumentMinimum}-${params.paginationArgumentMaximum}.`;
39
- const defaultNodeCostLimit = 500000;
40
- const defaultPaginationArgumentMaximum = 100;
41
- const defaultPaginationArgumentMinimum = 1;
42
+ exports.defaultNodeCostLimit = 500000;
43
+ exports.defaultPaginationArgumentMaximum = 100;
44
+ exports.defaultPaginationArgumentMinimum = 1;
42
45
  /**
43
46
  * Validate whether a user is allowed to execute a certain GraphQL operation.
44
47
  */
@@ -53,9 +56,9 @@ const ResourceLimitationValidationRule = (params) => (context, executionArgs) =>
53
56
  const fieldDef = context.getFieldDef();
54
57
  // if it is not found the query is invalid and graphql validation will complain
55
58
  if (fieldDef != null) {
56
- const argumentValues = utils.getArgumentValues(fieldDef, fieldNode, executionArgs.variableValues || undefined);
59
+ const argumentValues = (0, utils_1.getArgumentValues)(fieldDef, fieldNode, executionArgs.variableValues || undefined);
57
60
  const type = getWrappedType(fieldDef.type);
58
- if (type instanceof graphql.GraphQLObjectType && type.name.endsWith('Connection')) {
61
+ if (type instanceof graphql_1.GraphQLObjectType && type.name.endsWith('Connection')) {
59
62
  let nodeCost = 1;
60
63
  connectionFieldMap.add(fieldNode);
61
64
  const { hasFirst, hasLast } = hasFieldDefConnectionArgs(fieldDef, params.paginationArgumentTypes);
@@ -65,15 +68,16 @@ const ResourceLimitationValidationRule = (params) => (context, executionArgs) =>
65
68
  }
66
69
  else if (hasFirst === true || hasLast === true) {
67
70
  if ('first' in argumentValues === false && 'last' in argumentValues === false) {
68
- context.reportError(new graphql.GraphQLError(buildMissingPaginationFieldErrorMessage({
71
+ context.reportError(new graphql_1.GraphQLError(buildMissingPaginationFieldErrorMessage({
69
72
  fieldName: fieldDef.name,
70
73
  hasFirst,
71
74
  hasLast,
72
75
  }), fieldNode));
73
76
  }
74
77
  else if ('first' in argumentValues === true && 'last' in argumentValues === false) {
75
- if (argumentValues.first < paginationArgumentMinimum || argumentValues.first > paginationArgumentMaximum) {
76
- context.reportError(new graphql.GraphQLError(buildInvalidPaginationRangeErrorMessage({
78
+ if (argumentValues.first < paginationArgumentMinimum ||
79
+ argumentValues.first > paginationArgumentMaximum) {
80
+ context.reportError(new graphql_1.GraphQLError(buildInvalidPaginationRangeErrorMessage({
77
81
  paginationArgumentMaximum,
78
82
  paginationArgumentMinimum,
79
83
  argumentName: 'first',
@@ -86,8 +90,9 @@ const ResourceLimitationValidationRule = (params) => (context, executionArgs) =>
86
90
  }
87
91
  }
88
92
  else if ('last' in argumentValues === true && 'false' in argumentValues === false) {
89
- if (argumentValues.last < paginationArgumentMinimum || argumentValues.last > paginationArgumentMaximum) {
90
- context.reportError(new graphql.GraphQLError(buildInvalidPaginationRangeErrorMessage({
93
+ if (argumentValues.last < paginationArgumentMinimum ||
94
+ argumentValues.last > paginationArgumentMaximum) {
95
+ context.reportError(new graphql_1.GraphQLError(buildInvalidPaginationRangeErrorMessage({
91
96
  paginationArgumentMaximum,
92
97
  paginationArgumentMinimum,
93
98
  argumentName: 'last',
@@ -100,7 +105,7 @@ const ResourceLimitationValidationRule = (params) => (context, executionArgs) =>
100
105
  }
101
106
  }
102
107
  else {
103
- context.reportError(new graphql.GraphQLError(buildMissingPaginationFieldErrorMessage({
108
+ context.reportError(new graphql_1.GraphQLError(buildMissingPaginationFieldErrorMessage({
104
109
  fieldName: fieldDef.name,
105
110
  hasFirst,
106
111
  hasLast,
@@ -125,18 +130,19 @@ const ResourceLimitationValidationRule = (params) => (context, executionArgs) =>
125
130
  totalNodeCost = 1;
126
131
  }
127
132
  if (totalNodeCost > params.nodeCostLimit) {
128
- context.reportError(new graphql.GraphQLError(`Cannot request more than ${params.nodeCostLimit} nodes in a single document. Please split your operation into multiple sub operations or reduce the amount of requested nodes.`, documentNode));
133
+ context.reportError(new graphql_1.GraphQLError(`Cannot request more than ${params.nodeCostLimit} nodes in a single document. Please split your operation into multiple sub operations or reduce the amount of requested nodes.`, documentNode));
129
134
  }
130
135
  (_a = params.reportNodeCost) === null || _a === void 0 ? void 0 : _a.call(params, totalNodeCost, executionArgs);
131
136
  },
132
137
  },
133
138
  };
134
139
  };
140
+ exports.ResourceLimitationValidationRule = ResourceLimitationValidationRule;
135
141
  const useResourceLimitations = (params) => {
136
142
  var _a, _b, _c, _d;
137
- const paginationArgumentMaximum = (_a = params === null || params === void 0 ? void 0 : params.paginationArgumentMaximum) !== null && _a !== void 0 ? _a : defaultPaginationArgumentMaximum;
138
- const paginationArgumentMinimum = (_b = params === null || params === void 0 ? void 0 : params.paginationArgumentMinimum) !== null && _b !== void 0 ? _b : defaultPaginationArgumentMinimum;
139
- const nodeCostLimit = (_c = params === null || params === void 0 ? void 0 : params.nodeCostLimit) !== null && _c !== void 0 ? _c : defaultNodeCostLimit;
143
+ const paginationArgumentMaximum = (_a = params === null || params === void 0 ? void 0 : params.paginationArgumentMaximum) !== null && _a !== void 0 ? _a : exports.defaultPaginationArgumentMaximum;
144
+ const paginationArgumentMinimum = (_b = params === null || params === void 0 ? void 0 : params.paginationArgumentMinimum) !== null && _b !== void 0 ? _b : exports.defaultPaginationArgumentMinimum;
145
+ const nodeCostLimit = (_c = params === null || params === void 0 ? void 0 : params.nodeCostLimit) !== null && _c !== void 0 ? _c : exports.defaultNodeCostLimit;
140
146
  const extensions = (_d = params === null || params === void 0 ? void 0 : params.extensions) !== null && _d !== void 0 ? _d : false;
141
147
  const nodeCostMap = new WeakMap();
142
148
  const handleResult = ({ result, args }) => {
@@ -152,9 +158,9 @@ const useResourceLimitations = (params) => {
152
158
  };
153
159
  return {
154
160
  onPluginInit({ addPlugin }) {
155
- addPlugin(extendedValidation.useExtendedValidation({
161
+ addPlugin((0, extended_validation_1.useExtendedValidation)({
156
162
  rules: [
157
- ResourceLimitationValidationRule({
163
+ (0, exports.ResourceLimitationValidationRule)({
158
164
  nodeCostLimit,
159
165
  paginationArgumentMaximum,
160
166
  paginationArgumentMinimum,
@@ -172,15 +178,10 @@ const useResourceLimitations = (params) => {
172
178
  onExecute({ args }) {
173
179
  return {
174
180
  onExecuteDone(payload) {
175
- return core.handleStreamOrSingleExecutionResult(payload, ({ result }) => handleResult({ result, args }));
181
+ return (0, core_1.handleStreamOrSingleExecutionResult)(payload, ({ result }) => handleResult({ result, args }));
176
182
  },
177
183
  };
178
184
  },
179
185
  };
180
186
  };
181
-
182
- exports.ResourceLimitationValidationRule = ResourceLimitationValidationRule;
183
- exports.defaultNodeCostLimit = defaultNodeCostLimit;
184
- exports.defaultPaginationArgumentMaximum = defaultPaginationArgumentMaximum;
185
- exports.defaultPaginationArgumentMinimum = defaultPaginationArgumentMinimum;
186
187
  exports.useResourceLimitations = useResourceLimitations;
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -1,15 +1,15 @@
1
1
  import { handleStreamOrSingleExecutionResult } from '@envelop/core';
2
2
  import { useExtendedValidation } from '@envelop/extended-validation';
3
- import { GraphQLObjectType, GraphQLError, GraphQLList, GraphQLNonNull, GraphQLInt, isScalarType } from 'graphql';
3
+ import { GraphQLError, GraphQLInt, GraphQLList, GraphQLNonNull, GraphQLObjectType, isScalarType, } from '@graphql-tools/graphql';
4
4
  import { getArgumentValues } from '@graphql-tools/utils';
5
-
6
5
  const getWrappedType = (graphqlType) => {
7
6
  if (graphqlType instanceof GraphQLList || graphqlType instanceof GraphQLNonNull) {
8
7
  return getWrappedType(graphqlType.ofType);
9
8
  }
10
9
  return graphqlType;
11
10
  };
12
- const isValidArgType = (type, paginationArgumentTypes) => type === GraphQLInt || (isScalarType(type) && !!paginationArgumentTypes && paginationArgumentTypes.includes(type.name));
11
+ const isValidArgType = (type, paginationArgumentTypes) => type === GraphQLInt ||
12
+ (isScalarType(type) && !!paginationArgumentTypes && paginationArgumentTypes.includes(type.name));
13
13
  const hasFieldDefConnectionArgs = (field, argumentTypes) => {
14
14
  let hasFirst = false;
15
15
  let hasLast = false;
@@ -28,17 +28,21 @@ const hasFieldDefConnectionArgs = (field, argumentTypes) => {
28
28
  };
29
29
  const buildMissingPaginationFieldErrorMessage = (params) => `Missing pagination argument for field '${params.fieldName}'. ` +
30
30
  `Please provide ` +
31
- (params.hasFirst && params.hasLast ? "either the 'first' or 'last'" : params.hasFirst ? "the 'first'" : "the 'last'") +
31
+ (params.hasFirst && params.hasLast
32
+ ? "either the 'first' or 'last'"
33
+ : params.hasFirst
34
+ ? "the 'first'"
35
+ : "the 'last'") +
32
36
  ' field argument.';
33
37
  const buildInvalidPaginationRangeErrorMessage = (params) => `Invalid pagination argument for field ${params.fieldName}. ` +
34
38
  `The value for the '${params.argumentName}' argument must be an integer within ${params.paginationArgumentMinimum}-${params.paginationArgumentMaximum}.`;
35
- const defaultNodeCostLimit = 500000;
36
- const defaultPaginationArgumentMaximum = 100;
37
- const defaultPaginationArgumentMinimum = 1;
39
+ export const defaultNodeCostLimit = 500000;
40
+ export const defaultPaginationArgumentMaximum = 100;
41
+ export const defaultPaginationArgumentMinimum = 1;
38
42
  /**
39
43
  * Validate whether a user is allowed to execute a certain GraphQL operation.
40
44
  */
41
- const ResourceLimitationValidationRule = (params) => (context, executionArgs) => {
45
+ export const ResourceLimitationValidationRule = (params) => (context, executionArgs) => {
42
46
  const { paginationArgumentMaximum, paginationArgumentMinimum } = params;
43
47
  const nodeCostStack = [];
44
48
  let totalNodeCost = 0;
@@ -68,7 +72,8 @@ const ResourceLimitationValidationRule = (params) => (context, executionArgs) =>
68
72
  }), fieldNode));
69
73
  }
70
74
  else if ('first' in argumentValues === true && 'last' in argumentValues === false) {
71
- if (argumentValues.first < paginationArgumentMinimum || argumentValues.first > paginationArgumentMaximum) {
75
+ if (argumentValues.first < paginationArgumentMinimum ||
76
+ argumentValues.first > paginationArgumentMaximum) {
72
77
  context.reportError(new GraphQLError(buildInvalidPaginationRangeErrorMessage({
73
78
  paginationArgumentMaximum,
74
79
  paginationArgumentMinimum,
@@ -82,7 +87,8 @@ const ResourceLimitationValidationRule = (params) => (context, executionArgs) =>
82
87
  }
83
88
  }
84
89
  else if ('last' in argumentValues === true && 'false' in argumentValues === false) {
85
- if (argumentValues.last < paginationArgumentMinimum || argumentValues.last > paginationArgumentMaximum) {
90
+ if (argumentValues.last < paginationArgumentMinimum ||
91
+ argumentValues.last > paginationArgumentMaximum) {
86
92
  context.reportError(new GraphQLError(buildInvalidPaginationRangeErrorMessage({
87
93
  paginationArgumentMaximum,
88
94
  paginationArgumentMinimum,
@@ -128,7 +134,7 @@ const ResourceLimitationValidationRule = (params) => (context, executionArgs) =>
128
134
  },
129
135
  };
130
136
  };
131
- const useResourceLimitations = (params) => {
137
+ export const useResourceLimitations = (params) => {
132
138
  var _a, _b, _c, _d;
133
139
  const paginationArgumentMaximum = (_a = params === null || params === void 0 ? void 0 : params.paginationArgumentMaximum) !== null && _a !== void 0 ? _a : defaultPaginationArgumentMaximum;
134
140
  const paginationArgumentMinimum = (_b = params === null || params === void 0 ? void 0 : params.paginationArgumentMinimum) !== null && _b !== void 0 ? _b : defaultPaginationArgumentMinimum;
@@ -174,5 +180,3 @@ const useResourceLimitations = (params) => {
174
180
  },
175
181
  };
176
182
  };
177
-
178
- export { ResourceLimitationValidationRule, defaultNodeCostLimit, defaultPaginationArgumentMaximum, defaultPaginationArgumentMinimum, useResourceLimitations };
package/package.json CHANGED
@@ -1,38 +1,59 @@
1
1
  {
2
2
  "name": "@envelop/resource-limitations",
3
- "version": "3.0.0-alpha-36a1267.0",
3
+ "version": "3.0.0-alpha-5b6bfa8.0",
4
4
  "description": "A rate-limit implementation based on resource limitations and static calculation of the score (similar to GitHub GraphQL API)",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@envelop/core": "2.1.0-alpha-36a1267.0",
8
- "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
7
+ "@envelop/core": "3.0.0-alpha-5b6bfa8.0",
8
+ "@graphql-tools/graphql": "0.1.0-alpha-33fb2950.0"
9
9
  },
10
10
  "dependencies": {
11
- "@envelop/extended-validation": "2.0.0-alpha-36a1267.0",
12
- "@graphql-tools/utils": "^8.6.1"
11
+ "@envelop/extended-validation": "2.0.0-alpha-5b6bfa8.0",
12
+ "@graphql-tools/utils": "8.9.1-alpha-33fb2950.0"
13
13
  },
14
14
  "repository": {
15
15
  "type": "git",
16
- "url": "https://github.com/dotansimha/envelop.git",
16
+ "url": "https://github.com/n1ru4l/envelop.git",
17
17
  "directory": "packages/plugins/resource-limitations"
18
18
  },
19
19
  "author": "Laurin Quast <laurinquast@googlemail.com>",
20
20
  "license": "MIT",
21
- "main": "index.js",
22
- "module": "index.mjs",
23
- "typings": "index.d.ts",
21
+ "main": "cjs/index.js",
22
+ "module": "esm/index.js",
23
+ "typings": "typings/index.d.ts",
24
24
  "typescript": {
25
- "definition": "index.d.ts"
25
+ "definition": "typings/index.d.ts"
26
26
  },
27
+ "type": "module",
27
28
  "exports": {
28
29
  ".": {
29
- "require": "./index.js",
30
- "import": "./index.mjs"
30
+ "require": {
31
+ "types": "./typings/index.d.ts",
32
+ "default": "./cjs/index.js"
33
+ },
34
+ "import": {
35
+ "types": "./typings/index.d.ts",
36
+ "default": "./esm/index.js"
37
+ },
38
+ "default": {
39
+ "types": "./typings/index.d.ts",
40
+ "default": "./esm/index.js"
41
+ }
31
42
  },
32
43
  "./*": {
33
- "require": "./*.js",
34
- "import": "./*.mjs"
44
+ "require": {
45
+ "types": "./typings/*.d.ts",
46
+ "default": "./cjs/*.js"
47
+ },
48
+ "import": {
49
+ "types": "./typings/*.d.ts",
50
+ "default": "./esm/*.js"
51
+ },
52
+ "default": {
53
+ "types": "./typings/*.d.ts",
54
+ "default": "./esm/*.js"
55
+ }
35
56
  },
36
57
  "./package.json": "./package.json"
37
58
  }
38
- }
59
+ }
@@ -1,6 +1,6 @@
1
1
  import { Plugin } from '@envelop/core';
2
2
  import { ExtendedValidationRule } from '@envelop/extended-validation';
3
- import { ExecutionArgs } from 'graphql';
3
+ import { ExecutionArgs } from '@graphql-tools/graphql';
4
4
  export declare const defaultNodeCostLimit = 500000;
5
5
  export declare const defaultPaginationArgumentMaximum = 100;
6
6
  export declare const defaultPaginationArgumentMinimum = 1;
@@ -41,5 +41,5 @@ declare type UseResourceLimitationsParams = {
41
41
  */
42
42
  extensions?: boolean;
43
43
  };
44
- export declare const useResourceLimitations: (params?: UseResourceLimitationsParams | undefined) => Plugin;
44
+ export declare const useResourceLimitations: (params?: UseResourceLimitationsParams) => Plugin;
45
45
  export {};