trpc-shield
Version:
tRPC permissions as another layer of abstraction!
93 lines (86 loc) • 2.27 kB
text/typescript
import { LogicRule, Rule } from './rules';
import { ILogicRule, IRule, IRuleFieldMap, ShieldRule } from './types';
/**
*
* @param x
*
* Makes sure that a certain field is a rule.
*
*/
export function isRule<TContext extends Record<string, any>>(x: any): x is IRule<TContext> {
return x instanceof Rule || (x?.constructor && x.constructor.name === 'Rule');
}
/**
*
* @param x
*
* Makes sure that a certain field is a logic rule.
*
*/
export function isLogicRule<TContext extends Record<string, any>>(x: any): x is ILogicRule<TContext> {
return (
x instanceof LogicRule ||
(x?.constructor &&
(x.constructor.name === 'RuleOr' ||
x.constructor.name === 'RuleAnd' ||
x.constructor.name === 'RuleChain' ||
x.constructor.name === 'RuleRace' ||
x.constructor.name === 'RuleNot' ||
x.constructor.name === 'RuleTrue' ||
x.constructor.name === 'RuleFalse'))
);
}
/**
*
* @param x
*
* Makes sure that a certain field is a rule or a logic rule.
*
*/
export function isRuleFunction<TContext extends Record<string, any>>(x: any): x is ShieldRule<TContext> {
return isRule(x) || isLogicRule(x);
}
/**
*
* @param x
*
* Determines whether a certain field is rule field map or not.
*
*/
export function isRuleFieldMap<TContext extends Record<string, any>>(x: any): x is IRuleFieldMap<TContext> {
return typeof x === 'object' && Object.values(x).every((rule) => isRuleFunction(rule));
}
/**
*
* @param obj
* @param func
*
* Flattens object of particular type by checking if the leaf
* evaluates to true from particular function.
*
*/
export function flattenObjectOf<T>(obj: { [key: string]: any }, f: (x: any) => boolean): T[] {
const values = Object.keys(obj).reduce<T[]>((acc, key) => {
const val = obj[key];
if (f(val)) {
return [...acc, val];
} else if (typeof val === 'object' && !f(val)) {
return [...acc, ...flattenObjectOf(val, f)];
} else {
return acc;
}
}, []);
return values;
}
/**
*
* Returns fallback is provided value is undefined
*
* @param fallback
*/
export function withDefault<T>(fallback: T): (value: T | undefined) => T {
return (value) => {
if (value === undefined) return fallback;
return value;
};
}