/** * Breadcrumb trail — ring buffer for timeline navigation * * @module breadcrumbs */ import type { Breadcrumb } from './types.js'; export interface BreadcrumbTrailOptions { /** Maximum number of breadcrumbs to keep (default: 100) */ maxSize?: number; } /** * Ring buffer for breadcrumbs with fixed max size */ export class BreadcrumbTrail { private breadcrumbs: Breadcrumb[] = []; private maxSize: number; constructor(options: BreadcrumbTrailOptions = {}) { this.maxSize = options.maxSize ?? 100; } /** * Add a breadcrumb to the trail */ add(category: string, message: string, data?: Record): void { const breadcrumb: Breadcrumb = { timestamp: new Date().toISOString(), category, message, data, }; this.breadcrumbs.push(breadcrumb); // Evict oldest if over limit if (this.breadcrumbs.length > this.maxSize) { this.breadcrumbs.shift(); } } /** * Get all breadcrumbs (oldest first) */ getAll(): Breadcrumb[] { return [...this.breadcrumbs]; } /** * Get last N breadcrumbs */ getLast(n: number): Breadcrumb[] { return this.breadcrumbs.slice(-n); } /** * Get most recent breadcrumb */ getMostRecent(): Breadcrumb | null { return this.breadcrumbs[this.breadcrumbs.length - 1] ?? null; } /** * Clear all breadcrumbs */ clear(): void { this.breadcrumbs = []; } /** * Get current size */ size(): number { return this.breadcrumbs.length; } }