import type { Constraint, ConstraintContext, ConstraintResult, StateView } from './types.js'; export const evaluateConstraints = ( constraints: Constraint[], ctx: ConstraintContext, view: StateView ): ConstraintResult => { for (const constraint of constraints) { const missing = constraint.requires(ctx).filter((req) => !view.has(req)); if (missing.length > 0 && ctx.mode === 'precheck') { return { kind: 'unknown', missing }; } const result = constraint.test(ctx, view); if (result.kind === 'deny') { return { ...result, constraintName: result.constraintName ?? constraint.name, }; } if (result.kind !== 'allow') { return result; } } return { kind: 'allow' }; }; export interface ActionWithConstraints { buildConstraints(ctx: ConstraintContext, args: unknown): Constraint[]; } export const evaluateActionConstraints = ( action: ActionWithConstraints, ctx: ConstraintContext, view: StateView, args: Args ): ConstraintResult => { const constraints = action.buildConstraints(ctx, args); return evaluateConstraints(constraints, ctx, view); };