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.
- package/CHANGELOG.md +31 -0
- package/dist/cjs/constructors.js +134 -0
- package/dist/cjs/generator.js +205 -0
- package/dist/cjs/index.js +15 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/rules.js +402 -0
- package/dist/cjs/shield.js +52 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/utils.js +97 -0
- package/dist/cjs/validation.js +84 -0
- package/dist/esm/constructors.js +124 -0
- package/dist/esm/generator.js +201 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/rules.js +366 -0
- package/dist/esm/shield.js +45 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/utils.js +88 -0
- package/dist/esm/validation.js +79 -0
- package/dist/package.json +47 -0
- package/dist/typings/constructors.d.cts +91 -0
- package/dist/typings/constructors.d.ts +91 -0
- package/dist/typings/generator.d.cts +11 -0
- package/dist/typings/generator.d.ts +11 -0
- package/dist/typings/index.d.cts +3 -0
- package/dist/typings/index.d.ts +3 -0
- package/dist/typings/rules.d.cts +159 -0
- package/dist/typings/rules.d.ts +159 -0
- package/dist/typings/shield.d.cts +11 -0
- package/dist/typings/shield.d.ts +11 -0
- package/dist/typings/types.d.cts +64 -0
- package/dist/typings/types.d.ts +64 -0
- package/dist/typings/utils.d.cts +52 -0
- package/dist/typings/utils.d.ts +52 -0
- package/dist/typings/validation.d.cts +19 -0
- package/dist/typings/validation.d.ts +19 -0
- package/package.json +67 -0
- package/src/constructors.ts +157 -0
- package/src/generator.ts +294 -0
- package/src/index.ts +13 -0
- package/src/rules.ts +521 -0
- package/src/shield.ts +53 -0
- package/src/types.ts +94 -0
- package/src/utils.ts +101 -0
- package/src/validation.ts +90 -0
- package/tests/__snapshots__/input.test.ts.snap +7 -0
- package/tests/cache.test.ts +545 -0
- package/tests/constructors.test.ts +136 -0
- package/tests/fallback.test.ts +618 -0
- package/tests/fragments.test.ts +113 -0
- package/tests/generator.test.ts +356 -0
- package/tests/input.test.ts +63 -0
- package/tests/integration.test.ts +65 -0
- package/tests/logic.test.ts +530 -0
- package/tests/utils.test.ts +55 -0
- package/tests/validation.test.ts +139 -0
- package/tsconfig.json +10 -0
package/src/utils.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { ShieldRule, ILogicRule, IRuleFieldMap, IRule } from './types.js'
|
|
2
|
+
import { Rule, LogicRule } from './rules.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param x
|
|
7
|
+
*
|
|
8
|
+
* Makes sure that a certain field is a rule.
|
|
9
|
+
*
|
|
10
|
+
*/
|
|
11
|
+
export function isRule(x: any): x is IRule {
|
|
12
|
+
return (
|
|
13
|
+
x instanceof Rule || (x && x.constructor && x.constructor.name === 'Rule')
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @param x
|
|
20
|
+
*
|
|
21
|
+
* Makes sure that a certain field is a logic rule.
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
export function isLogicRule(x: any): x is ILogicRule {
|
|
25
|
+
return (
|
|
26
|
+
x instanceof LogicRule ||
|
|
27
|
+
(x &&
|
|
28
|
+
x.constructor &&
|
|
29
|
+
(x.constructor.name === 'RuleOr' ||
|
|
30
|
+
x.constructor.name === 'RuleAnd' ||
|
|
31
|
+
x.constructor.name === 'RuleChain' ||
|
|
32
|
+
x.constructor.name === 'RuleRace' ||
|
|
33
|
+
x.constructor.name === 'RuleNot' ||
|
|
34
|
+
x.constructor.name === 'RuleTrue' ||
|
|
35
|
+
x.constructor.name === 'RuleFalse'))
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @param x
|
|
42
|
+
*
|
|
43
|
+
* Makes sure that a certain field is a rule or a logic rule.
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
46
|
+
export function isRuleFunction(x: any): x is ShieldRule {
|
|
47
|
+
return isRule(x) || isLogicRule(x)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
*
|
|
52
|
+
* @param x
|
|
53
|
+
*
|
|
54
|
+
* Determines whether a certain field is rule field map or not.
|
|
55
|
+
*
|
|
56
|
+
*/
|
|
57
|
+
export function isRuleFieldMap(x: any): x is IRuleFieldMap {
|
|
58
|
+
return (
|
|
59
|
+
typeof x === 'object' &&
|
|
60
|
+
Object.values(x).every((rule) => isRuleFunction(rule))
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
*
|
|
66
|
+
* @param obj
|
|
67
|
+
* @param func
|
|
68
|
+
*
|
|
69
|
+
* Flattens object of particular type by checking if the leaf
|
|
70
|
+
* evaluates to true from particular function.
|
|
71
|
+
*
|
|
72
|
+
*/
|
|
73
|
+
export function flattenObjectOf<T>(
|
|
74
|
+
obj: { [key: string]: any },
|
|
75
|
+
f: (x: any) => boolean,
|
|
76
|
+
): T[] {
|
|
77
|
+
const values = Object.keys(obj).reduce<T[]>((acc, key) => {
|
|
78
|
+
const val = obj[key]
|
|
79
|
+
if (f(val)) {
|
|
80
|
+
return [...acc, val]
|
|
81
|
+
} else if (typeof val === 'object' && !f(val)) {
|
|
82
|
+
return [...acc, ...flattenObjectOf(val, f)]
|
|
83
|
+
} else {
|
|
84
|
+
return acc
|
|
85
|
+
}
|
|
86
|
+
}, [])
|
|
87
|
+
return values
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
*
|
|
92
|
+
* Returns fallback is provided value is undefined
|
|
93
|
+
*
|
|
94
|
+
* @param fallback
|
|
95
|
+
*/
|
|
96
|
+
export function withDefault<T>(fallback: T): (value: T | undefined) => T {
|
|
97
|
+
return (value) => {
|
|
98
|
+
if (value === undefined) return fallback
|
|
99
|
+
return value
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { IRules, ShieldRule, ILogicRule, IRule } from './types.js'
|
|
2
|
+
import { isRuleFunction, flattenObjectOf, isLogicRule } from './utils.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @param ruleTree
|
|
7
|
+
*
|
|
8
|
+
* Validates the rule tree declaration by checking references of rule
|
|
9
|
+
* functions. We deem rule tree valid if no two rules with the same name point
|
|
10
|
+
* to different rules.
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
13
|
+
export function validateRuleTree(
|
|
14
|
+
ruleTree: IRules,
|
|
15
|
+
): { status: 'ok' } | { status: 'err'; message: string } {
|
|
16
|
+
const rules = extractRules(ruleTree)
|
|
17
|
+
|
|
18
|
+
const valid = rules.reduce<{ map: Map<string, IRule>; duplicates: string[] }>(
|
|
19
|
+
({ map, duplicates }, rule) => {
|
|
20
|
+
if (!map.has(rule.name)) {
|
|
21
|
+
return { map: map.set(rule.name, rule), duplicates }
|
|
22
|
+
} else if (
|
|
23
|
+
!map.get(rule.name)!.equals(rule) &&
|
|
24
|
+
!duplicates.includes(rule.name)
|
|
25
|
+
) {
|
|
26
|
+
return {
|
|
27
|
+
map: map.set(rule.name, rule),
|
|
28
|
+
duplicates: [...duplicates, rule.name],
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
return { map, duplicates }
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{ map: new Map<string, IRule>(), duplicates: [] },
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if (valid.duplicates.length === 0) {
|
|
38
|
+
return { status: 'ok' }
|
|
39
|
+
} else {
|
|
40
|
+
const duplicates = valid.duplicates.join(', ')
|
|
41
|
+
return {
|
|
42
|
+
status: 'err',
|
|
43
|
+
message: `There seem to be multiple definitions of these rules: ${duplicates}`,
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Helper functions */
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @param ruleTree
|
|
51
|
+
*
|
|
52
|
+
* Extracts rules from rule tree.
|
|
53
|
+
*
|
|
54
|
+
*/
|
|
55
|
+
function extractRules(ruleTree: IRules): IRule[] {
|
|
56
|
+
const resolvers = flattenObjectOf<ShieldRule>(ruleTree, isRuleFunction)
|
|
57
|
+
|
|
58
|
+
const rules = resolvers.reduce<IRule[]>((rules, rule) => {
|
|
59
|
+
if (isLogicRule(rule)) {
|
|
60
|
+
return [...rules, ...extractLogicRules(rule)]
|
|
61
|
+
} else {
|
|
62
|
+
return [...rules, rule]
|
|
63
|
+
}
|
|
64
|
+
}, [])
|
|
65
|
+
|
|
66
|
+
return rules
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
*
|
|
71
|
+
* Recursively extracts Rules from LogicRule
|
|
72
|
+
*
|
|
73
|
+
* @param rule
|
|
74
|
+
*/
|
|
75
|
+
function extractLogicRules(rule: ILogicRule): IRule[] {
|
|
76
|
+
return rule.getRules().reduce<IRule[]>((acc, shieldRule) => {
|
|
77
|
+
if (isLogicRule(shieldRule)) {
|
|
78
|
+
return [...acc, ...extractLogicRules(shieldRule)]
|
|
79
|
+
} else {
|
|
80
|
+
return [...acc, shieldRule]
|
|
81
|
+
}
|
|
82
|
+
}, [])
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export class ValidationError extends Error {
|
|
87
|
+
constructor(message: string) {
|
|
88
|
+
super(message)
|
|
89
|
+
}
|
|
90
|
+
}
|