graphql-shield-node23 7.6.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/cjs/constructors.js +134 -0
  3. package/dist/cjs/generator.js +205 -0
  4. package/dist/cjs/index.js +15 -0
  5. package/dist/cjs/package.json +1 -0
  6. package/dist/cjs/rules.js +402 -0
  7. package/dist/cjs/shield.js +52 -0
  8. package/dist/cjs/types.js +2 -0
  9. package/dist/cjs/utils.js +97 -0
  10. package/dist/cjs/validation.js +84 -0
  11. package/dist/esm/constructors.js +124 -0
  12. package/dist/esm/generator.js +201 -0
  13. package/dist/esm/index.js +2 -0
  14. package/dist/esm/rules.js +366 -0
  15. package/dist/esm/shield.js +45 -0
  16. package/dist/esm/types.js +1 -0
  17. package/dist/esm/utils.js +88 -0
  18. package/dist/esm/validation.js +79 -0
  19. package/dist/package.json +47 -0
  20. package/dist/typings/constructors.d.cts +91 -0
  21. package/dist/typings/constructors.d.ts +91 -0
  22. package/dist/typings/generator.d.cts +11 -0
  23. package/dist/typings/generator.d.ts +11 -0
  24. package/dist/typings/index.d.cts +3 -0
  25. package/dist/typings/index.d.ts +3 -0
  26. package/dist/typings/rules.d.cts +159 -0
  27. package/dist/typings/rules.d.ts +159 -0
  28. package/dist/typings/shield.d.cts +11 -0
  29. package/dist/typings/shield.d.ts +11 -0
  30. package/dist/typings/types.d.cts +64 -0
  31. package/dist/typings/types.d.ts +64 -0
  32. package/dist/typings/utils.d.cts +52 -0
  33. package/dist/typings/utils.d.ts +52 -0
  34. package/dist/typings/validation.d.cts +19 -0
  35. package/dist/typings/validation.d.ts +19 -0
  36. package/package.json +67 -0
  37. package/src/constructors.ts +157 -0
  38. package/src/generator.ts +294 -0
  39. package/src/index.ts +13 -0
  40. package/src/rules.ts +521 -0
  41. package/src/shield.ts +53 -0
  42. package/src/types.ts +94 -0
  43. package/src/utils.ts +101 -0
  44. package/src/validation.ts +90 -0
  45. package/tests/__snapshots__/input.test.ts.snap +7 -0
  46. package/tests/cache.test.ts +545 -0
  47. package/tests/constructors.test.ts +136 -0
  48. package/tests/fallback.test.ts +618 -0
  49. package/tests/fragments.test.ts +113 -0
  50. package/tests/generator.test.ts +356 -0
  51. package/tests/input.test.ts +63 -0
  52. package/tests/integration.test.ts +65 -0
  53. package/tests/logic.test.ts +530 -0
  54. package/tests/utils.test.ts +55 -0
  55. package/tests/validation.test.ts +139 -0
  56. package/tsconfig.json +10 -0
@@ -0,0 +1,294 @@
1
+ import {
2
+ IMiddleware,
3
+ IMiddlewareFunction,
4
+ IMiddlewareGeneratorConstructor,
5
+ } from 'graphql-middleware'
6
+ import {
7
+ GraphQLSchema,
8
+ GraphQLObjectType,
9
+ isObjectType,
10
+ isIntrospectionType,
11
+ GraphQLResolveInfo,
12
+ } from 'graphql'
13
+ import {
14
+ IRules,
15
+ IOptions,
16
+ ShieldRule,
17
+ IRuleFieldMap,
18
+ IShieldContext,
19
+ } from './types.js'
20
+ import {
21
+ isRuleFunction,
22
+ isRuleFieldMap,
23
+ isRule,
24
+ isLogicRule,
25
+ withDefault,
26
+ } from './utils.js'
27
+ import { ValidationError } from './validation.js'
28
+ import { IMiddlewareWithOptions } from 'graphql-middleware/dist/types'
29
+
30
+ /**
31
+ *
32
+ * @param options
33
+ *
34
+ * Generates a middleware function from a given rule and
35
+ * initializes the cache object in context.
36
+ *
37
+ */
38
+ function generateFieldMiddlewareFromRule(
39
+ rule: ShieldRule,
40
+ options: IOptions,
41
+ ): IMiddlewareFunction<object, object, IShieldContext> {
42
+ async function middleware(
43
+ resolve: (
44
+ parent: object,
45
+ args: object,
46
+ ctx: IShieldContext,
47
+ info: GraphQLResolveInfo,
48
+ ) => Promise<any>,
49
+ parent: { [key: string]: any },
50
+ args: { [key: string]: any },
51
+ ctx: IShieldContext,
52
+ info: GraphQLResolveInfo,
53
+ ) {
54
+ // Cache
55
+ if (!ctx) {
56
+ ctx = {} as IShieldContext
57
+ }
58
+
59
+ if (!ctx._shield) {
60
+ ctx._shield = {
61
+ cache: {},
62
+ }
63
+ }
64
+
65
+ // Execution
66
+ try {
67
+ const res = await rule.resolve(parent, args, ctx, info, options)
68
+
69
+ if (res === true) {
70
+ return await resolve(parent, args, ctx, info)
71
+ } else if (res === false) {
72
+ if (typeof options.fallbackError === 'function') {
73
+ return await options.fallbackError(null, parent, args, ctx, info)
74
+ }
75
+ return options.fallbackError
76
+ } else {
77
+ return res
78
+ }
79
+ } catch (err) {
80
+ if (options.debug) {
81
+ throw err
82
+ } else if (options.allowExternalErrors) {
83
+ return err
84
+ } else {
85
+ if (typeof options.fallbackError === 'function') {
86
+ return await options.fallbackError(err, parent, args, ctx, info)
87
+ }
88
+ return options.fallbackError
89
+ }
90
+ }
91
+ }
92
+
93
+ if (isRule(rule) && rule.extractFragment()) {
94
+ return {
95
+ fragment: rule.extractFragment(),
96
+ resolve: middleware,
97
+ } as IMiddlewareWithOptions<object, object, IShieldContext>
98
+ }
99
+
100
+ if (isLogicRule(rule)) {
101
+ return {
102
+ fragments: rule.extractFragments(),
103
+ resolve: middleware,
104
+ } as IMiddlewareWithOptions<object, object, IShieldContext>
105
+ }
106
+
107
+ return middleware as IMiddlewareFunction<object, object, IShieldContext>
108
+ }
109
+
110
+ /**
111
+ *
112
+ * @param type
113
+ * @param rules
114
+ * @param options
115
+ *
116
+ * Generates middleware from rule for a particular type.
117
+ *
118
+ */
119
+ function applyRuleToType(
120
+ type: GraphQLObjectType,
121
+ rules: ShieldRule | IRuleFieldMap,
122
+ options: IOptions,
123
+ ): IMiddleware {
124
+ if (isRuleFunction(rules)) {
125
+ /* Apply defined rule function to every field */
126
+ const fieldMap = type.getFields()
127
+
128
+ const middleware = Object.keys(fieldMap).reduce((middleware, field) => {
129
+ return {
130
+ ...middleware,
131
+ [field]: generateFieldMiddlewareFromRule(rules, options),
132
+ }
133
+ }, {})
134
+
135
+ return middleware
136
+ } else if (isRuleFieldMap(rules)) {
137
+ /* Apply rules assigned to each field to each field */
138
+ const fieldMap = type.getFields()
139
+
140
+ /* Extract default type wildcard if any and remove it for validation */
141
+ const defaultTypeRule = rules['*']
142
+ const {'*': _, ...rulesWithoutWildcard} = rules;
143
+ /* Validation */
144
+
145
+ const fieldErrors = Object.keys(rulesWithoutWildcard)
146
+ .filter((type) => !Object.prototype.hasOwnProperty.call(fieldMap, type))
147
+ .map((field) => `${type.name}.${field}`)
148
+ .join(', ')
149
+
150
+ if (fieldErrors.length > 0) {
151
+ throw new ValidationError(
152
+ `It seems like you have applied rules to ${fieldErrors} fields but Shield cannot find them in your schema.`,
153
+ )
154
+ }
155
+
156
+ /* Generation */
157
+
158
+ const middleware = Object.keys(fieldMap).reduce(
159
+ (middleware, field) => ({
160
+ ...middleware,
161
+ [field]: generateFieldMiddlewareFromRule(
162
+ withDefault(defaultTypeRule || options.fallbackRule)(rules[field]),
163
+ options,
164
+ ),
165
+ }),
166
+ {},
167
+ )
168
+
169
+ return middleware
170
+ } else {
171
+ /* Apply fallbackRule to type with no defined rule */
172
+ const fieldMap = type.getFields()
173
+
174
+ const middleware = Object.keys(fieldMap).reduce(
175
+ (middleware, field) => ({
176
+ ...middleware,
177
+ [field]: generateFieldMiddlewareFromRule(options.fallbackRule, options),
178
+ }),
179
+ {},
180
+ )
181
+
182
+ return middleware
183
+ }
184
+ }
185
+
186
+ /**
187
+ *
188
+ * @param schema
189
+ * @param rule
190
+ * @param options
191
+ *
192
+ * Applies the same rule over entire schema.
193
+ *
194
+ */
195
+ function applyRuleToSchema(
196
+ schema: GraphQLSchema,
197
+ rule: ShieldRule,
198
+ options: IOptions,
199
+ ): IMiddleware {
200
+ const typeMap = schema.getTypeMap()
201
+
202
+ const middleware = Object.keys(typeMap)
203
+ .filter((type) => !isIntrospectionType(typeMap[type]))
204
+ .reduce((middleware, typeName) => {
205
+ const type = typeMap[typeName]
206
+
207
+ if (isObjectType(type)) {
208
+ return {
209
+ ...middleware,
210
+ [typeName]: applyRuleToType(type, rule, options),
211
+ }
212
+ } else {
213
+ return middleware
214
+ }
215
+ }, {})
216
+
217
+ return middleware
218
+ }
219
+
220
+ /**
221
+ *
222
+ * @param rules
223
+ * @param wrapper
224
+ *
225
+ * Converts rule tree to middleware.
226
+ *
227
+ */
228
+ function generateMiddlewareFromSchemaAndRuleTree(
229
+ schema: GraphQLSchema,
230
+ rules: IRules,
231
+ options: IOptions,
232
+ ): IMiddleware {
233
+ if (isRuleFunction(rules)) {
234
+ /* Applies rule to entire schema. */
235
+ return applyRuleToSchema(schema, rules, options)
236
+ } else {
237
+ /**
238
+ * Checks type map and field map and applies rules
239
+ * to particular fields.
240
+ */
241
+ const typeMap = schema.getTypeMap()
242
+
243
+ /* Validation */
244
+
245
+ const typeErrors = Object.keys(rules)
246
+ .filter((type) => !Object.prototype.hasOwnProperty.call(typeMap, type))
247
+ .join(', ')
248
+
249
+ if (typeErrors.length > 0) {
250
+ throw new ValidationError(
251
+ `It seems like you have applied rules to ${typeErrors} types but Shield cannot find them in your schema.`,
252
+ )
253
+ }
254
+
255
+ // Generation
256
+
257
+ const middleware = Object.keys(typeMap)
258
+ .filter((type) => !isIntrospectionType(typeMap[type]))
259
+ .reduce<IMiddleware>((middleware, typeName) => {
260
+ const type = typeMap[typeName]
261
+
262
+ if (isObjectType(type)) {
263
+ return {
264
+ ...middleware,
265
+ [typeName]: applyRuleToType(type, rules[typeName], options),
266
+ }
267
+ } else {
268
+ return middleware
269
+ }
270
+ }, {})
271
+
272
+ return middleware
273
+ }
274
+ }
275
+
276
+ /**
277
+ *
278
+ * @param ruleTree
279
+ * @param options
280
+ *
281
+ * Generates middleware from given rules.
282
+ *
283
+ */
284
+ export function generateMiddlewareGeneratorFromRuleTree<
285
+ TSource = any,
286
+ TContext = any,
287
+ TArgs = any
288
+ >(
289
+ ruleTree: IRules,
290
+ options: IOptions,
291
+ ): IMiddlewareGeneratorConstructor<TSource, TContext, TArgs> {
292
+ return (schema: GraphQLSchema) =>
293
+ generateMiddlewareFromSchemaAndRuleTree(schema, ruleTree, options)
294
+ }
package/src/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ export { IRules, IRule } from './types.js'
2
+ export { shield } from './shield.js'
3
+ export {
4
+ rule,
5
+ inputRule,
6
+ allow,
7
+ deny,
8
+ and,
9
+ chain,
10
+ race,
11
+ or,
12
+ not,
13
+ } from './constructors.js'