/** * @file Base Route Guard Interface and Types * @description Defines the core route guard interface and types for implementing * navigation guards. Inspired by Angular route guards with React adaptations. * * @module @/lib/routing/guards/route-guard * * This module provides: * - Base guard interface definition * - Guard result types * - Guard context structure * - Guard execution utilities * - Type-safe guard creation * * @example * ```typescript * import { RouteGuard, createGuard, GuardResult } from '@/lib/routing/guards/route-guard'; * * const myGuard = createGuard({ * name: 'myGuard', * canActivate: async (context) => { * if (someCondition) { * return GuardResult.allow(); * } * return GuardResult.redirect('/login'); * }, * }); * ``` */ /** * Guard execution timing */ export type GuardTiming = 'canActivate' | 'canDeactivate' | 'canMatch' | 'canLoad'; /** * Guard result type */ export type GuardResultType = 'allow' | 'deny' | 'redirect' | 'pending'; /** * Guard result object */ export interface GuardResultObject { /** Result type */ readonly type: GuardResultType; /** Redirect path (if type is 'redirect') */ readonly redirectTo?: string; /** Redirect options */ readonly redirectOptions?: RedirectOptions; /** Denial reason (if type is 'deny') */ readonly reason?: string; /** Additional data */ readonly data?: Record; } /** * Redirect options */ export interface RedirectOptions { /** Replace current history entry */ readonly replace?: boolean; /** State to pass to redirect target */ readonly state?: unknown; /** Query parameters */ readonly query?: Record; /** Preserve current query parameters */ readonly preserveQuery?: boolean; } /** * Guard context passed to guard functions */ export interface GuardContext { /** Target route path */ readonly path: string; /** Route parameters */ readonly params: Record; /** Query parameters */ readonly query: Record; /** Current route (for canDeactivate) */ readonly currentRoute?: string; /** Next route (for canDeactivate) */ readonly nextRoute?: string; /** User context */ readonly user?: GuardUser; /** Feature flags */ readonly features?: Record; /** Custom data from route or parent guards */ readonly data: Record; /** Navigation state */ readonly state?: unknown; /** Whether this is initial load */ readonly isInitialLoad: boolean; /** Parent route context (for nested routes) */ readonly parent?: GuardContext; } /** * User context for guards */ export interface GuardUser { /** User ID */ readonly id: string; /** Whether user is authenticated */ readonly isAuthenticated: boolean; /** User roles */ readonly roles: readonly string[]; /** User permissions */ readonly permissions: readonly string[]; /** User metadata */ readonly metadata?: Record; } /** * Guard function signature */ export type GuardFunction = (context: GuardContext) => GuardResultObject | Promise; /** * Guard configuration */ export interface GuardConfig { /** Unique guard name */ readonly name: string; /** Guard description */ readonly description?: string; /** Guard timing */ readonly timing?: GuardTiming; /** Guard priority (lower = runs first) */ readonly priority?: number; /** Whether guard is async */ readonly async?: boolean; /** Timeout in milliseconds */ readonly timeout?: number; /** Routes this guard applies to (glob patterns) */ readonly routes?: readonly string[]; /** Routes to exclude (glob patterns) */ readonly exclude?: readonly string[]; /** Whether guard is enabled */ readonly enabled?: boolean; /** Feature flag for this guard */ readonly featureFlag?: string; /** canActivate implementation */ readonly canActivate?: GuardFunction; /** canDeactivate implementation */ readonly canDeactivate?: GuardFunction; /** canMatch implementation */ readonly canMatch?: GuardFunction; /** canLoad implementation */ readonly canLoad?: GuardFunction; } /** * Route guard interface */ export interface RouteGuard extends GuardConfig { /** Execute the guard */ execute: (timing: GuardTiming, context: GuardContext) => Promise; /** Check if guard applies to a route */ appliesTo: (path: string) => boolean; } /** * Guard execution result */ export interface GuardExecutionResult { /** Guard name */ readonly guardName: string; /** Result from guard */ readonly result: GuardResultObject; /** Execution duration (ms) */ readonly durationMs: number; /** Whether guard timed out */ readonly timedOut: boolean; /** Error if guard threw */ readonly error?: Error; } /** * Helper class for creating guard results * * @example * ```typescript * // Allow navigation * return GuardResult.allow(); * * // Deny with reason * return GuardResult.deny('Insufficient permissions'); * * // Redirect * return GuardResult.redirect('/login', { replace: true }); * ``` */ export declare class GuardResult { /** * Allow navigation * * @param data - Optional data to pass along * @returns Allow result */ static allow(data?: Record): GuardResultObject; /** * Deny navigation * * @param reason - Reason for denial * @param data - Optional data * @returns Deny result */ static deny(reason?: string, data?: Record): GuardResultObject; /** * Redirect to another route * * @param path - Path to redirect to * @param options - Redirect options * @returns Redirect result */ static redirect(path: string, options?: RedirectOptions): GuardResultObject; /** * Pending result (guard is still processing) * * @returns Pending result */ static pending(): GuardResultObject; /** * Create result from boolean * * @param allowed - Whether navigation is allowed * @param denyReason - Reason if denied * @returns Result based on boolean */ static fromBoolean(allowed: boolean, denyReason?: string): GuardResultObject; /** * Check if result allows navigation * * @param result - Result to check * @returns True if result allows navigation */ static isAllowed(result: GuardResultObject): boolean; /** * Check if result denies navigation * * @param result - Result to check * @returns True if result denies navigation */ static isDenied(result: GuardResultObject): boolean; /** * Check if result is a redirect * * @param result - Result to check * @returns True if result is a redirect */ static isRedirect(result: GuardResultObject): boolean; } /** * Base class for route guards * * @example * ```typescript * class MyGuard extends BaseRouteGuard { * constructor() { * super({ * name: 'myGuard', * canActivate: async (ctx) => { * return GuardResult.allow(); * }, * }); * } * } * ``` */ export declare class BaseRouteGuard implements RouteGuard { readonly name: string; readonly description?: string; readonly timing?: GuardTiming; readonly priority: number; readonly async: boolean; readonly timeout: number; readonly routes?: readonly string[]; readonly exclude?: readonly string[]; readonly enabled: boolean; readonly featureFlag?: string; readonly canActivate?: GuardFunction; readonly canDeactivate?: GuardFunction; readonly canMatch?: GuardFunction; readonly canLoad?: GuardFunction; constructor(config: GuardConfig); /** * Execute the guard for a specific timing */ execute(timing: GuardTiming, context: GuardContext): Promise; /** * Check if guard applies to a route */ appliesTo(path: string): boolean; /** * Get the handler for a timing */ private getHandler; /** * Execute handler with timeout */ private executeWithTimeout; /** * Match a glob pattern against a path */ private matchPattern; } /** * Create a route guard * * @param config - Guard configuration * @returns Route guard instance */ export declare function createGuard(config: GuardConfig): RouteGuard; /** * Create a guard context * * @param options - Context options * @returns Guard context */ export declare function createGuardContext(options: Partial & { path: string; }): GuardContext; /** * Merge guard results (returns first non-allow result) * * @param results - Array of guard results * @returns Merged result */ export declare function mergeGuardResults(results: readonly GuardResultObject[]): GuardResultObject; /** * Check if all results allow navigation * * @param results - Array of guard results * @returns True if all allow */ export declare function allResultsAllow(results: readonly GuardResultObject[]): boolean; /** * Get the first redirect result * * @param results - Array of guard results * @returns First redirect result or undefined */ export declare function getFirstRedirect(results: readonly GuardResultObject[]): GuardResultObject | undefined; /** * Get all denial reasons * * @param results - Array of guard results * @returns Array of denial reasons */ export declare function getDenialReasons(results: readonly GuardResultObject[]): string[]; /** * Type guard for GuardResultObject */ export declare function isGuardResult(value: unknown): value is GuardResultObject; /** * Type guard for RouteGuard */ export declare function isRouteGuard(value: unknown): value is RouteGuard; /** * Type guard for GuardContext */ export declare function isGuardContext(value: unknown): value is GuardContext;