UNPKG

verdict-rules

Version:

A small, zero-dependency, async-native rule-evaluation engine. Compose conditions into one explainable pass/fail verdict, with sequential evaluation and real short-circuiting as a guarantee.

78 lines (77 loc) • 2.68 kB
import type { RuleResult } from "./result.js"; /** * The contract every rule satisfies. * * A plain `interface` — structural typing: any object of the right shape * is a `Rule`. No `implements` clause, no base class, no registration. * * `Rule<TContext>` is generic over the context it reads from, with no * default type parameter. Dict-context is `Rule<Context>`, written out * every time. * * ```ts * const overEighteen: Rule<Context> = { * name: "over_18", * async evaluate(ctx) { * return { ruleName: "over_18", passed: (ctx.age as number) >= 18 }; * }, * }; * ``` */ export interface Rule<TContext> { /** * Unique identifier for this rule, used for engine lookups and to attribute * a result back to its source. */ readonly name: string; /** Optional group label. Rules sharing one can be run together. */ readonly group?: string | undefined; /** Evaluate this rule against `context`. */ evaluate(context: TContext): Promise<RuleResult>; } /** Signature of the predicate {@link FunctionRule} wraps. */ export type RulePredicate<TContext> = (context: TContext) => Promise<RuleResult>; /** * Wraps a plain async predicate as a {@link Rule}. * * `TContext` is inferred from the wrapped predicate's own parameter type. */ export declare class FunctionRule<TContext> implements Rule<TContext> { #private; readonly name: string; readonly group: string | undefined; constructor(name: string, predicate: RulePredicate<TContext>, group?: string); /** Runs the wrapped predicate and returns whatever it returns, unchanged. */ evaluate(context: TContext): Promise<RuleResult>; } /** * Composite that passes only if every sub-rule passes. * * Short-circuits on the first failing sub-rule. * * An empty list passes vacuously. * * Every sub-rule must share the exact same `TContext`. */ export declare class AndRule<TContext> implements Rule<TContext> { #private; readonly name: string; readonly group: string | undefined; constructor(name: string, rules: readonly Rule<TContext>[], group?: string); evaluate(context: TContext): Promise<RuleResult>; } /** * Composite that passes as soon as any sub-rule passes. * * Short-circuits on the first passing sub-rule. * * An empty list fails vacuously. The same same-`TContext` requirement * across sub-rules applies here too. */ export declare class OrRule<TContext> implements Rule<TContext> { #private; readonly name: string; readonly group: string | undefined; constructor(name: string, rules: readonly Rule<TContext>[], group?: string); evaluate(context: TContext): Promise<RuleResult>; }