{"version":3,"sources":["../src/version.ts","../src/types/error.ts","../src/config/defaults.ts","../src/config/manager.ts","../src/types/utils.ts","../src/utils/logger.ts","../src/client/cache.ts","../src/client/rate-limiter.ts","../src/client/client.ts","../src/types/constants.ts","../src/utils/datetime.ts","../src/utils/parse.ts","../src/utils/seasons.ts","../src/utils/url.ts","../src/data/depth-charts.ts","../src/utils/validation.ts","../src/data/participation.ts","../src/data/pbp.ts","../src/data/player-stats.ts","../src/data/players.ts","../src/data/rosters.ts"],"names":["DEFAULT_CONFIG","ky","Papa","parquetReadObjects","logger","aggregated"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Package version\n * This should be kept in sync with package.json\n */\nexport const version = '0.3.0';\n","/**\n * Error types and result patterns\n * @module types/error\n */\n\n/**\n * Error codes for nflreadts errors\n */\nexport enum ErrorCode {\n  // Network errors\n  NETWORK_ERROR = 'NETWORK_ERROR',\n  TIMEOUT = 'TIMEOUT',\n  RATE_LIMIT = 'RATE_LIMIT',\n  REQUEST_ABORTED = 'REQUEST_ABORTED',\n\n  // Data errors\n  DATA_NOT_FOUND = 'DATA_NOT_FOUND',\n  INVALID_DATA = 'INVALID_DATA',\n  PARSE_ERROR = 'PARSE_ERROR',\n\n  // Validation errors\n  INVALID_SEASON = 'INVALID_SEASON',\n  INVALID_WEEK = 'INVALID_WEEK',\n  INVALID_TEAM = 'INVALID_TEAM',\n  INVALID_PLAYER = 'INVALID_PLAYER',\n  INVALID_PARAMETER = 'INVALID_PARAMETER',\n\n  // Configuration errors\n  CONFIG_ERROR = 'CONFIG_ERROR',\n\n  // Cache errors\n  CACHE_ERROR = 'CACHE_ERROR',\n\n  // Unknown\n  UNKNOWN_ERROR = 'UNKNOWN_ERROR',\n}\n\n/**\n * Base error class for nflreadts\n */\nexport class NflReadError extends Error {\n  /**\n   * Error code\n   */\n  public readonly code: ErrorCode;\n\n  /**\n   * Additional context about the error\n   */\n  public readonly context?: Record<string, unknown>;\n\n  constructor(\n    message: string,\n    code: ErrorCode = ErrorCode.UNKNOWN_ERROR,\n    context?: Record<string, unknown>,\n    cause?: Error\n  ) {\n    super(message, { cause });\n    this.name = 'NflReadError';\n    this.code = code;\n    this.context = context ?? {};\n\n    // Maintains proper stack trace for where error was thrown (V8 only)\n    if (Error.captureStackTrace) {\n      Error.captureStackTrace(this, NflReadError);\n    }\n  }\n\n  /**\n   * Create a JSON representation of the error\n   */\n  toJSON(): Record<string, unknown> {\n    return {\n      name: this.name,\n      message: this.message,\n      code: this.code,\n      context: this.context,\n      stack: this.stack,\n    };\n  }\n}\n\n/**\n * Network-related errors\n */\nexport class NetworkError extends NflReadError {\n  constructor(message: string, context?: Record<string, unknown>, cause?: Error) {\n    super(message, ErrorCode.NETWORK_ERROR, context, cause);\n    this.name = 'NetworkError';\n  }\n}\n\n/**\n * Timeout errors\n */\nexport class TimeoutError extends NflReadError {\n  constructor(message: string, context?: Record<string, unknown>) {\n    super(message, ErrorCode.TIMEOUT, context);\n    this.name = 'TimeoutError';\n  }\n}\n\n/**\n * Request aborted errors\n */\nexport class RequestAbortedError extends NflReadError {\n  constructor(message: string, context?: Record<string, unknown>) {\n    super(message, ErrorCode.REQUEST_ABORTED, context);\n    this.name = 'RequestAbortedError';\n  }\n}\n\n/**\n * Rate limit errors\n */\nexport class RateLimitError extends NflReadError {\n  /**\n   * When the rate limit resets (timestamp)\n   */\n  public readonly resetAt?: number;\n\n  constructor(message: string, resetAt?: number, context?: Record<string, unknown>) {\n    super(message, ErrorCode.RATE_LIMIT, context);\n    this.name = 'RateLimitError';\n    this.resetAt = resetAt ?? 0;\n  }\n}\n\n/**\n * Data not found errors\n */\nexport class DataNotFoundError extends NflReadError {\n  constructor(message: string, context?: Record<string, unknown>) {\n    super(message, ErrorCode.DATA_NOT_FOUND, context);\n    this.name = 'DataNotFoundError';\n  }\n}\n\n/**\n * Invalid data errors\n */\nexport class InvalidDataError extends NflReadError {\n  constructor(message: string, context?: Record<string, unknown>, cause?: Error) {\n    super(message, ErrorCode.INVALID_DATA, context, cause);\n    this.name = 'InvalidDataError';\n  }\n}\n\n/**\n * Validation errors\n */\nexport class ValidationError extends NflReadError {\n  constructor(message: string, code: ErrorCode, context?: Record<string, unknown>) {\n    super(message, code, context);\n    this.name = 'ValidationError';\n  }\n}\n\n/**\n * Result type for operations that can fail\n * Using discriminated union pattern for type safety\n */\nexport type Result<T, E = NflReadError> = { ok: true; value: T } | { ok: false; error: E };\n\n/**\n * Create a successful result\n */\nexport function Ok<T>(value: T): Result<T, never> {\n  return { ok: true, value };\n}\n\n/**\n * Create an error result\n */\nexport function Err<E>(error: E): Result<never, E> {\n  return { ok: false, error };\n}\n\n/**\n * Type guard for successful results\n */\nexport function isOk<T, E>(result: Result<T, E>): result is { ok: true; value: T } {\n  return result.ok === true;\n}\n\n/**\n * Type guard for error results\n */\nexport function isErr<T, E>(result: Result<T, E>): result is { ok: false; error: E } {\n  return result.ok === false;\n}\n\n/**\n * Unwrap a result, throwing if it's an error\n */\nexport function unwrap<T, E extends Error>(result: Result<T, E>): T {\n  if (isErr(result)) {\n    throw result.error;\n  }\n  return result.value;\n}\n\n/**\n * Unwrap a result with a default value\n */\nexport function unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T {\n  return isOk(result) ? result.value : defaultValue;\n}\n\n/**\n * Map a result's value\n */\nexport function mapResult<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> {\n  return isOk(result) ? Ok(fn(result.value)) : result;\n}\n\n/**\n * Map a result's error\n */\nexport function mapError<T, E, F>(result: Result<T, E>, fn: (error: E) => F): Result<T, F> {\n  return isErr(result) ? Err(fn(result.error)) : result;\n}\n","/**\n * Default configuration values\n * @module config/defaults\n */\n\nimport { version } from '../version.js';\n\nimport type { Environment, NflReadConfig } from './types.js';\n\n/**\n * Detect the current runtime environment\n */\nexport function detectEnvironment(): Environment {\n  // Check for Node.js\n  if (typeof process !== 'undefined' && process.versions?.node) {\n    return 'node';\n  }\n\n  // Check for browser\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n  const hasWindow = typeof (globalThis as any).window !== 'undefined';\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access\n  const hasDocument = typeof (globalThis as any).document !== 'undefined';\n\n  if (hasWindow && hasDocument) {\n    return 'browser';\n  }\n\n  return 'unknown';\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: NflReadConfig = {\n  http: {\n    timeout: 30000, // 30 seconds\n    retries: 3,\n    retryDelay: 1000, // 1 second\n    userAgent: `nflreadts/${version}`,\n    headers: {},\n  },\n  cache: {\n    enabled: true,\n    ttl: 3600000, // 1 hour\n    maxSize: 100,\n    storage: 'memory',\n  },\n  dataSources: {\n    baseUrl: 'https://github.com/nflverse/nflverse-data/releases/download',\n    mirrors: [],\n  },\n  logging: {\n    debug: false,\n    level: 'warn',\n  },\n};\n\n/**\n * Get environment-specific default overrides\n */\nexport function getEnvironmentDefaults(env: Environment): Partial<NflReadConfig> {\n  switch (env) {\n    case 'node':\n      return {\n        // Could enable persistent cache in Node.js\n        // No overrides needed for now\n      };\n    case 'browser':\n      return {\n        cache: {\n          // Browser has memory constraints\n          maxSize: 50,\n          enabled: true,\n          ttl: 1800000, // 30 minutes\n          storage: 'memory',\n        },\n      };\n    default:\n      return {};\n  }\n}\n","/**\n * Configuration manager for nflreadts\n * @module config/manager\n */\n\nimport { DEFAULT_CONFIG, detectEnvironment, getEnvironmentDefaults } from './defaults.js';\n\nimport type { NflReadConfig, PartialNflReadConfig } from './types.js';\n\n/**\n * Deep merge two objects\n * Later object properties override earlier ones\n */\nfunction deepMerge(target: NflReadConfig, source: PartialNflReadConfig): NflReadConfig {\n  const result: NflReadConfig = { ...target };\n\n  // Merge http config\n  if (source.http) {\n    result.http = { ...target.http, ...source.http };\n  }\n\n  // Merge cache config\n  if (source.cache) {\n    result.cache = { ...target.cache, ...source.cache };\n  }\n\n  // Merge dataSources config\n  if (source.dataSources) {\n    result.dataSources = { ...target.dataSources, ...source.dataSources };\n  }\n\n  // Merge logging config\n  if (source.logging) {\n    result.logging = { ...target.logging, ...source.logging };\n  }\n\n  return result;\n}\n\n/**\n * Configuration manager class\n * Follows the Singleton pattern to ensure consistent config across the application\n */\nexport class ConfigManager {\n  private static instance: ConfigManager | null = null;\n  private config: NflReadConfig;\n\n  /**\n   * Private constructor to enforce singleton pattern\n   */\n  private constructor(userConfig?: PartialNflReadConfig) {\n    const env = detectEnvironment();\n    const envDefaults = getEnvironmentDefaults(env);\n\n    // Merge: defaults -> environment defaults -> user config\n    let config = { ...DEFAULT_CONFIG };\n    config = deepMerge(config, envDefaults);\n    if (userConfig) {\n      config = deepMerge(config, userConfig);\n    }\n\n    this.config = config;\n  }\n\n  /**\n   * Get the singleton instance\n   */\n  public static getInstance(userConfig?: PartialNflReadConfig): ConfigManager {\n    if (!ConfigManager.instance) {\n      ConfigManager.instance = new ConfigManager(userConfig);\n    } else if (userConfig) {\n      // If instance exists and new config provided, merge it in\n      ConfigManager.instance.update(userConfig);\n    }\n    return ConfigManager.instance;\n  }\n\n  /**\n   * Reset the singleton instance (useful for testing)\n   */\n  public static reset(): void {\n    ConfigManager.instance = null;\n  }\n\n  /**\n   * Get the current configuration\n   */\n  public getConfig(): Readonly<NflReadConfig> {\n    return this.config;\n  }\n\n  /**\n   * Get a specific configuration value by path\n   */\n  public get<K extends keyof NflReadConfig>(section: K): Readonly<NflReadConfig[K]>;\n  public get<K extends keyof NflReadConfig, S extends keyof NflReadConfig[K]>(\n    section: K,\n    key: S\n  ): Readonly<NflReadConfig[K][S]>;\n  public get<K extends keyof NflReadConfig, S extends keyof NflReadConfig[K]>(\n    section: K,\n    key?: S\n  ): Readonly<NflReadConfig[K]> | Readonly<NflReadConfig[K][S]> {\n    if (key === undefined) {\n      return this.config[section];\n    }\n    return this.config[section][key];\n  }\n\n  /**\n   * Update configuration with new values\n   */\n  public update(userConfig: PartialNflReadConfig): void {\n    this.config = deepMerge(this.config, userConfig);\n  }\n\n  /**\n   * Reset configuration to defaults (with environment-specific overrides)\n   */\n  public resetToDefaults(): void {\n    const env = detectEnvironment();\n    const envDefaults = getEnvironmentDefaults(env);\n    this.config = deepMerge({ ...DEFAULT_CONFIG }, envDefaults);\n  }\n}\n\n/**\n * Convenience function to get the current configuration\n */\nexport function getConfig(): Readonly<NflReadConfig> {\n  return ConfigManager.getInstance().getConfig();\n}\n\n/**\n * Convenience function to configure nflreadts\n */\nexport function configure(userConfig: PartialNflReadConfig): void {\n  ConfigManager.getInstance(userConfig);\n}\n","import { LogLevel } from './enums';\n\n/**\n * Utility types and patterns\n * @module types/utils\n */\n\n/**\n * Make specific properties required\n */\nexport type RequireFields<T, K extends keyof T> = T & Required<Pick<T, K>>;\n\n/**\n * Make specific properties optional\n */\nexport type OptionalFields<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;\n\n/**\n * Make all properties nullable\n */\nexport type Nullable<T> = {\n  [K in keyof T]: T[K] | null;\n};\n\n/**\n * Make specific properties nullable\n */\nexport type NullableFields<T, K extends keyof T> = Omit<T, K> & {\n  [P in K]: T[P] | null;\n};\n\n/**\n * Awaited type for promises (built-in from TS 4.5+, but defining for completeness)\n */\nexport type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;\n\n/**\n * Extract array element type\n */\nexport type ArrayElement<T> = T extends readonly (infer U)[] ? U : never;\n\n/**\n * Make all nested properties readonly\n */\nexport type DeepReadonly<T> = {\n  readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];\n};\n\n/**\n * Filter options for data loading\n */\nexport interface FilterOptions {\n  /**\n   * Limit number of results\n   */\n  limit?: number;\n\n  /**\n   * Offset for pagination\n   */\n  offset?: number;\n\n  /**\n   * Sort field\n   */\n  sortBy?: string;\n\n  /**\n   * Sort direction\n   */\n  sortOrder?: 'asc' | 'desc';\n}\n\n/**\n * Data loading options (common across all load functions)\n */\nexport interface LoadOptions extends FilterOptions {\n  /**\n   * Force refresh (bypass cache)\n   */\n  forceRefresh?: boolean;\n\n  /**\n   * Abort signal for cancellation\n   */\n  signal?: AbortSignal;\n}\n\n/**\n * Paginated response wrapper\n */\nexport interface PaginatedResponse<T> {\n  /**\n   * Array of data items\n   */\n  data: T[];\n\n  /**\n   * Total number of items available\n   */\n  total: number;\n\n  /**\n   * Current page offset\n   */\n  offset: number;\n\n  /**\n   * Number of items in current page\n   */\n  limit: number;\n\n  /**\n   * Whether there are more items\n   */\n  hasMore: boolean;\n}\n\n/**\n * Data state discriminated union for loading states\n */\nexport type DataState<T> =\n  | { status: 'idle' }\n  | { status: 'loading' }\n  | { status: 'success'; data: T }\n  | { status: 'error'; error: Error };\n\n/**\n * Type guard for success state\n */\nexport function isSuccess<T>(state: DataState<T>): state is { status: 'success'; data: T } {\n  return state.status === 'success';\n}\n\n/**\n * Type guard for error state\n */\nexport function isError<T>(state: DataState<T>): state is { status: 'error'; error: Error } {\n  return state.status === 'error';\n}\n\n/**\n * Type guard for loading state\n */\nexport function isLoading<T>(state: DataState<T>): state is { status: 'loading' } {\n  return state.status === 'loading';\n}\n\n/**\n * Range type for filtering\n */\nexport interface Range<T> {\n  min?: T;\n  max?: T;\n}\n\n/**\n * Type for season range\n */\nexport type SeasonRange = Range<number>;\n\n/**\n * Type for week range\n */\nexport type WeekRange = Range<number>;\n\n/**\n * Configuration options for season normalization\n */\nexport interface NormalizeSeasonsOptions {\n  /**\n   * Minimum valid season\n   * @default 1999\n   */\n  minSeason?: number;\n\n  /**\n   * Maximum valid season\n   * @default current season\n   */\n  maxSeason?: number;\n\n  /**\n   * Default season when input is undefined\n   * @default current season\n   */\n  defaultSeason?: number;\n}\n\n/**\n * Map log level string to number\n */\nexport const LogLevelMap: Record<string, LogLevel> = {\n  error: LogLevel.ERROR,\n  warn: LogLevel.WARN,\n  info: LogLevel.INFO,\n  debug: LogLevel.DEBUG,\n};\n","/**\n * Logging utilities\n * @module utils/logger\n */\n\nimport { getConfig } from '../config/manager.js';\n\nimport type { LogConfig } from '../config/types.js';\nimport { LogLevel } from '../types/enums.js';\nimport { LogLevelMap } from '../types/utils.js';\n\n/**\n * Logger class\n */\nexport class Logger {\n  private config: LogConfig;\n\n  constructor(config?: LogConfig) {\n    this.config = config ?? getConfig().logging;\n  }\n\n  /**\n   * Get the current log level as a number\n   */\n  private getLogLevel(): LogLevel {\n    return LogLevelMap[this.config.level] ?? LogLevel.WARN;\n  }\n\n  /**\n   * Check if a log level should be logged\n   */\n  private shouldLog(level: LogLevel): boolean {\n    return level <= this.getLogLevel();\n  }\n\n  /**\n   * Log a message\n   */\n  private log(level: LogLevel, levelName: string, message: string, ...args: unknown[]): void {\n    if (!this.shouldLog(level)) {\n      return;\n    }\n\n    // Use custom logger if provided\n    if (this.config.logger) {\n      this.config.logger(levelName, message, ...args);\n      return;\n    }\n  }\n\n  /**\n   * Log an error message\n   */\n  error(message: string, ...args: unknown[]): void {\n    this.log(LogLevel.ERROR, 'error', message, ...args);\n  }\n\n  /**\n   * Log a warning message\n   */\n  warn(message: string, ...args: unknown[]): void {\n    this.log(LogLevel.WARN, 'warn', message, ...args);\n  }\n\n  /**\n   * Log an info message\n   */\n  info(message: string, ...args: unknown[]): void {\n    this.log(LogLevel.INFO, 'info', message, ...args);\n  }\n\n  /**\n   * Log a debug message\n   */\n  debug(message: string, ...args: unknown[]): void {\n    if (this.config.debug) {\n      this.log(LogLevel.DEBUG, 'debug', message, ...args);\n    }\n  }\n\n  /**\n   * Log an error object\n   */\n  logError(error: Error, context?: Record<string, unknown>): void {\n    this.error('Error occurred:', {\n      name: error.name,\n      message: error.message,\n      stack: error.stack,\n      ...context,\n    });\n  }\n\n  /**\n   * Create a child logger with additional context\n   */\n  child(context: Record<string, unknown>): Logger {\n    const originalLogger = this.config.logger;\n\n    const childLogger: LogConfig['logger'] = (level, message, ...args) => {\n      const contextStr = Object.entries(context)\n        .map(([key, value]) => `${key}=${String(value)}`)\n        .join(' ');\n\n      if (originalLogger) {\n        originalLogger(level, `[${contextStr}] ${message}`, ...args);\n      } else {\n        // Will be handled by default console logging in log()\n        this.log(LogLevelMap[level] ?? LogLevel.INFO, level, `[${contextStr}] ${message}`, ...args);\n      }\n    };\n\n    return new Logger({\n      ...this.config,\n      logger: childLogger,\n    });\n  }\n\n  /**\n   * Update logger configuration\n   */\n  updateConfig(config: Partial<LogConfig>): void {\n    this.config = { ...this.config, ...config };\n  }\n}\n\n/**\n * Default logger instance\n */\nlet defaultLogger: Logger | null = null;\n\n/**\n * Get the default logger instance\n */\nexport function getLogger(): Logger {\n  if (!defaultLogger) {\n    defaultLogger = new Logger();\n  }\n  return defaultLogger;\n}\n\n/**\n * Reset the default logger (useful for testing)\n */\nexport function resetLogger(): void {\n  defaultLogger = null;\n}\n\n/**\n * Create a named logger with context\n */\nexport function createLogger(name: string): Logger {\n  return getLogger().child({ component: name });\n}\n","/**\n * Response caching implementation\n * @module client/cache\n */\n\nimport type { CacheEntry } from './types.js';\n\n/**\n * In-memory cache for HTTP responses\n * Uses LRU-style eviction when max size is reached\n */\nexport class ResponseCache {\n  private cache = new Map<string, CacheEntry>();\n  private accessOrder = new Map<string, number>();\n  private accessCounter = 0;\n\n  /**\n   * Maximum number of entries to store\n   */\n  private readonly maxSize: number;\n\n  /**\n   * Default TTL in milliseconds\n   */\n  private readonly defaultTtl: number;\n\n  constructor(maxSize = 1000, defaultTtl = 3600000) {\n    this.maxSize = maxSize;\n    this.defaultTtl = defaultTtl;\n  }\n\n  /**\n   * Get an item from cache if it exists and hasn't expired\n   */\n  get<T>(key: string): T | undefined {\n    const entry = this.cache.get(key);\n\n    if (!entry) {\n      return undefined;\n    }\n\n    // Check if expired\n    const now = Date.now();\n    if (now - entry.cachedAt > entry.ttl) {\n      this.cache.delete(key);\n      this.accessOrder.delete(key);\n      return undefined;\n    }\n\n    // Update access order for LRU\n    this.accessOrder.set(key, ++this.accessCounter);\n\n    return entry.data as T;\n  }\n\n  /**\n   * Store an item in cache\n   */\n  set<T>(key: string, data: T, ttl?: number, etag?: string, lastModified?: string): void {\n    // Evict oldest entry if at capacity\n    if (this.cache.size >= this.maxSize && !this.cache.has(key)) {\n      this.evictOldest();\n    }\n\n    const entry: CacheEntry<T> = {\n      data,\n      cachedAt: Date.now(),\n      ttl: ttl ?? this.defaultTtl,\n      etag: etag ?? '',\n      lastModified: lastModified ?? '',\n    };\n\n    this.cache.set(key, entry);\n    this.accessOrder.set(key, ++this.accessCounter);\n  }\n\n  /**\n   * Check if a key exists and hasn't expired\n   */\n  has(key: string): boolean {\n    return this.get(key) !== undefined;\n  }\n\n  /**\n   * Delete an entry from cache\n   */\n  delete(key: string): boolean {\n    this.accessOrder.delete(key);\n    return this.cache.delete(key);\n  }\n\n  /**\n   * Clear all entries from cache\n   */\n  clear(): void {\n    this.cache.clear();\n    this.accessOrder.clear();\n    this.accessCounter = 0;\n  }\n\n  /**\n   * Get number of entries in cache\n   */\n  get size(): number {\n    return this.cache.size;\n  }\n\n  /**\n   * Get cache statistics\n   */\n  stats(): { size: number; maxSize: number; entries: string[] } {\n    return {\n      size: this.cache.size,\n      maxSize: this.maxSize,\n      entries: Array.from(this.cache.keys()),\n    };\n  }\n\n  /**\n   * Evict expired entries\n   */\n  evictExpired(): number {\n    const now = Date.now();\n    let evicted = 0;\n\n    for (const [key, entry] of this.cache.entries()) {\n      if (now - entry.cachedAt > entry.ttl) {\n        this.cache.delete(key);\n        this.accessOrder.delete(key);\n        evicted++;\n      }\n    }\n\n    return evicted;\n  }\n\n  /**\n   * Evict the oldest (least recently used) entry\n   */\n  private evictOldest(): void {\n    if (this.cache.size === 0) return;\n\n    // Find key with lowest access counter\n    let oldestKey: string | undefined;\n    let oldestAccess = Infinity;\n\n    for (const [key, access] of this.accessOrder.entries()) {\n      if (access < oldestAccess) {\n        oldestAccess = access;\n        oldestKey = key;\n      }\n    }\n\n    if (oldestKey) {\n      this.cache.delete(oldestKey);\n      this.accessOrder.delete(oldestKey);\n    }\n  }\n\n  /**\n   * Generate a cache key from URL and options\n   */\n  static generateKey(url: string, options?: Record<string, unknown>): string {\n    if (!options || Object.keys(options).length === 0) {\n      return url;\n    }\n\n    // Sort keys for consistent hashing\n    const sorted = Object.keys(options)\n      .sort()\n      .map((key) => `${key}=${JSON.stringify(options[key])}`)\n      .join('&');\n\n    return `${url}?${sorted}`;\n  }\n}\n","/**\n * Rate limiter implementation using token bucket algorithm\n * @module client/rate-limiter\n */\n\n/**\n * Rate limiter configuration\n */\nexport interface RateLimiterConfig {\n  /**\n   * Maximum number of requests per interval\n   * @default 100\n   */\n  maxRequests: number;\n\n  /**\n   * Time interval in milliseconds\n   * @default 60000 (1 minute)\n   */\n  interval: number;\n}\n\n/**\n * Token bucket rate limiter\n * Allows burst requests up to maxRequests, then refills tokens at a constant rate\n */\nexport class RateLimiter {\n  private tokens: number;\n  private lastRefill: number;\n  private readonly maxTokens: number;\n  private readonly refillRate: number;\n  private readonly queue: Array<() => void> = [];\n\n  constructor(config: RateLimiterConfig) {\n    this.maxTokens = config.maxRequests;\n    this.tokens = config.maxRequests;\n    this.lastRefill = Date.now();\n    // Tokens per millisecond\n    this.refillRate = config.maxRequests / config.interval;\n  }\n\n  /**\n   * Refill tokens based on time elapsed\n   */\n  private refill(): void {\n    const now = Date.now();\n    const elapsed = now - this.lastRefill;\n    const tokensToAdd = elapsed * this.refillRate;\n\n    this.tokens = Math.min(this.maxTokens, this.tokens + tokensToAdd);\n    this.lastRefill = now;\n  }\n\n  /**\n   * Try to acquire a token\n   * Returns true if token was acquired, false otherwise\n   */\n  private tryAcquire(): boolean {\n    this.refill();\n\n    if (this.tokens >= 1) {\n      this.tokens -= 1;\n      return true;\n    }\n\n    return false;\n  }\n\n  /**\n   * Wait until a token is available\n   * Returns a promise that resolves when a token is acquired\n   */\n  async acquire(): Promise<void> {\n    if (this.tryAcquire()) {\n      return Promise.resolve();\n    }\n\n    // Calculate wait time for next token\n    const waitTime = Math.ceil((1 - this.tokens) / this.refillRate);\n\n    return new Promise<void>((resolve) => {\n      const timeoutId = setTimeout(() => {\n        this.queue.shift();\n        void this.acquire().then(resolve);\n      }, waitTime);\n\n      this.queue.push(() => {\n        clearTimeout(timeoutId);\n        resolve();\n      });\n    });\n  }\n\n  /**\n   * Get current token count\n   */\n  getAvailableTokens(): number {\n    this.refill();\n    return Math.floor(this.tokens);\n  }\n\n  /**\n   * Get time until next token is available (in ms)\n   */\n  getTimeUntilNextToken(): number {\n    this.refill();\n\n    if (this.tokens >= 1) {\n      return 0;\n    }\n\n    return Math.ceil((1 - this.tokens) / this.refillRate);\n  }\n\n  /**\n   * Reset the rate limiter\n   */\n  reset(): void {\n    this.tokens = this.maxTokens;\n    this.lastRefill = Date.now();\n    this.queue.length = 0;\n  }\n\n  /**\n   * Get stats about the rate limiter\n   */\n  stats(): { availableTokens: number; maxTokens: number; queueLength: number } {\n    return {\n      availableTokens: this.getAvailableTokens(),\n      maxTokens: this.maxTokens,\n      queueLength: this.queue.length,\n    };\n  }\n}\n","/**\n * HTTP client implementation using ky\n * @module client/client\n */\n\nimport ky, { type KyInstance, type Options as KyOptions } from 'ky';\n\nimport { NetworkError, RequestAbortedError, TimeoutError } from '../types/error.js';\nimport { createLogger } from '../utils/logger.js';\n\nimport { ResponseCache } from './cache.js';\nimport { RateLimiter } from './rate-limiter.js';\n\nimport type { HttpClientConfig, HttpHooks, HttpResponse, RequestOptions } from './types.js';\n\n/**\n * Default configuration values\n */\nconst DEFAULT_CONFIG: Required<\n  Omit<HttpClientConfig, 'baseUrl' | 'headers' | 'userAgent' | 'rateLimit'>\n> = {\n  timeout: 30000,\n  retry: 3,\n  cache: true,\n  cacheTtl: 3600000, // 1 hour\n  debug: false,\n};\n\n/**\n * HTTP client for making requests with caching and retry logic\n */\nexport class HttpClient {\n  private client: KyInstance;\n  private cache: ResponseCache;\n  private rateLimiter?: RateLimiter;\n  private config: HttpClientConfig;\n  private hooks: HttpHooks = {};\n  private logger = createLogger('HttpClient');\n\n  constructor(config: HttpClientConfig = {}) {\n    this.config = { ...DEFAULT_CONFIG, ...config };\n    this.cache = new ResponseCache(1000, this.config.cacheTtl);\n\n    // Initialize rate limiter if configured\n    if (this.config.rateLimit) {\n      this.rateLimiter = new RateLimiter(this.config.rateLimit);\n    }\n\n    // Create ky instance with configuration\n    const kyOptions: KyOptions = {\n      timeout: this.config.timeout ?? false,\n      retry: {\n        limit: this.config.retry ?? 3,\n        methods: ['get', 'head', 'options', 'trace'],\n        statusCodes: [408, 413, 429, 500, 502, 503, 504],\n        backoffLimit: 3000,\n      },\n      headers: {\n        'User-Agent': this.config.userAgent ?? `nflreadts/${this.getVersion()}`,\n        ...this.config.headers,\n      },\n      hooks: {\n        beforeRequest: [\n          async (request) => {\n            if (this.config.debug) {\n              this.logger.debug(`Request: ${request.method} ${request.url}`);\n            }\n            if (this.hooks.beforeRequest) {\n              await this.hooks.beforeRequest(request.url, {} as RequestOptions);\n            }\n          },\n        ],\n        afterResponse: [\n          async (request, _options, response) => {\n            if (this.config.debug) {\n              this.logger.debug(`Response: ${response.status} ${request.url}`);\n            }\n            return (\n              (await this.hooks.afterResponse?.({\n                data: await response\n                  .clone()\n                  .json()\n                  .catch(() => undefined),\n                status: response.status,\n                headers: {},\n                fromCache: false,\n                url: request.url,\n              })) ?? response\n            );\n          },\n        ],\n      },\n    };\n\n    if (this.config.baseUrl) {\n      kyOptions.prefixUrl = this.config.baseUrl;\n    }\n\n    this.client = ky.create(kyOptions);\n  }\n\n  /**\n   * Set hooks for request/response interception\n   */\n  setHooks(hooks: HttpHooks): void {\n    this.hooks = hooks;\n  }\n\n  /**\n   * Make a GET request\n   */\n  async get<T = unknown>(url: string, options: RequestOptions = {}): Promise<HttpResponse<T>> {\n    return this.request<T>(url, { ...options, method: 'get' });\n  }\n\n  /**\n   * Make a POST request\n   */\n  async post<T = unknown>(\n    url: string,\n    data?: unknown,\n    options: RequestOptions = {}\n  ): Promise<HttpResponse<T>> {\n    return this.request<T>(url, {\n      ...options,\n      method: 'post',\n      json: data,\n    });\n  }\n\n  /**\n   * Make a PUT request\n   */\n  async put<T = unknown>(\n    url: string,\n    data?: unknown,\n    options: RequestOptions = {}\n  ): Promise<HttpResponse<T>> {\n    return this.request<T>(url, {\n      ...options,\n      method: 'put',\n      json: data,\n    });\n  }\n\n  /**\n   * Make a DELETE request\n   */\n  async delete<T = unknown>(url: string, options: RequestOptions = {}): Promise<HttpResponse<T>> {\n    return this.request<T>(url, { ...options, method: 'delete' });\n  }\n\n  /**\n   * Make a HEAD request\n   */\n  async head(url: string, options: RequestOptions = {}): Promise<HttpResponse<void>> {\n    return this.request<void>(url, { ...options, method: 'head' });\n  }\n\n  /**\n   * Core request method\n   */\n  private async request<T>(url: string, options: RequestOptions = {}): Promise<HttpResponse<T>> {\n    const {\n      cache = this.config.cache,\n      cacheTtl = this.config.cacheTtl,\n      cacheKey,\n      timeout = this.config.timeout,\n      retry = this.config.retry,\n      signal,\n      ...kyOptions\n    } = options;\n\n    // Only cache GET requests by default\n    const shouldCache = cache && (options.method === 'get' || options.method === undefined);\n    const finalCacheKey = cacheKey ?? ResponseCache.generateKey(url, kyOptions);\n\n    // Check cache first\n    if (shouldCache) {\n      const cached = this.cache.get<T>(finalCacheKey);\n      if (cached !== undefined) {\n        if (this.config.debug) {\n          this.logger.debug(`Cache hit: ${url}`);\n        }\n\n        const response: HttpResponse<T> = {\n          data: cached,\n          status: 200,\n          headers: {},\n          fromCache: true,\n          url,\n        };\n\n        if (this.hooks.afterResponse) {\n          await this.hooks.afterResponse(response);\n        }\n\n        return response;\n      }\n    }\n\n    // Apply rate limiting if configured\n    if (this.rateLimiter) {\n      await this.rateLimiter.acquire();\n      if (this.config.debug) {\n        const stats = this.rateLimiter.stats();\n        this.logger.debug(\n          `Rate limiter: ${stats.availableTokens}/${stats.maxTokens} tokens available`\n        );\n      }\n    }\n\n    // Make request\n    try {\n      const kyRequestOptions: KyOptions = {\n        ...kyOptions,\n        timeout: timeout ?? false,\n        retry: {\n          limit: retry ?? 3,\n          methods: ['get', 'head', 'options', 'trace'],\n          statusCodes: [408, 413, 429, 500, 502, 503, 504],\n        },\n        ...(signal && { signal }),\n      };\n\n      const response = await this.client(url, kyRequestOptions);\n\n      // Parse response based on content type or explicit format\n      const contentType = response.headers.get('content-type') ?? '';\n      let data: T;\n\n      if (contentType.includes('application/json')) {\n        data = (await response.json()) as T;\n      } else if (contentType.includes('text/')) {\n        data = (await response.text()) as T;\n      } else {\n        // Default to arrayBuffer for binary data\n        data = (await response.arrayBuffer()) as T;\n      }\n\n      // Cache successful responses\n      if (shouldCache && response.ok) {\n        const etag = response.headers.get('etag') ?? undefined;\n        const lastModified = response.headers.get('last-modified') ?? undefined;\n        this.cache.set(finalCacheKey, data, cacheTtl, etag, lastModified);\n      }\n\n      // Build response object\n      const headers: Record<string, string> = {};\n      response.headers.forEach((value, key) => {\n        headers[key] = value;\n      });\n\n      const httpResponse: HttpResponse<T> = {\n        data,\n        status: response.status,\n        headers,\n        fromCache: false,\n        url: response.url,\n      };\n\n      if (this.hooks.afterResponse) {\n        await this.hooks.afterResponse(httpResponse);\n      }\n\n      return httpResponse;\n    } catch (error) {\n      // Transform errors\n      let nflError: Error;\n\n      if (error instanceof Error) {\n        if (error.name === 'TimeoutError') {\n          nflError = new TimeoutError(`Request timeout: ${url}`, { url, timeout });\n        } else if (error.name === 'AbortError') {\n          nflError = new RequestAbortedError(`Request aborted: ${url}`, { url });\n        } else {\n          nflError = new NetworkError(`Network request failed: ${error.message}`, { url }, error);\n        }\n      } else {\n        nflError = new NetworkError(`Unknown error during request: ${url}`, { url });\n      }\n\n      if (this.hooks.onError) {\n        await this.hooks.onError(nflError, url);\n      }\n\n      throw nflError;\n    }\n  }\n\n  /**\n   * Clear the response cache\n   */\n  clearCache(): void {\n    this.cache.clear();\n  }\n\n  /**\n   * Get cache statistics\n   */\n  getCacheStats(): { size: number; maxSize: number; entries: string[] } {\n    return this.cache.stats();\n  }\n\n  /**\n   * Evict expired cache entries\n   */\n  evictExpiredCache(): number {\n    return this.cache.evictExpired();\n  }\n\n  /**\n   * Get rate limiter statistics\n   */\n  getRateLimiterStats(): {\n    availableTokens: number;\n    maxTokens: number;\n    queueLength: number;\n  } | null {\n    return this.rateLimiter?.stats() ?? null;\n  }\n\n  /**\n   * Reset rate limiter\n   */\n  resetRateLimiter(): void {\n    this.rateLimiter?.reset();\n  }\n\n  /**\n   * Get package version\n   */\n  private getVersion(): string {\n    // This will be replaced with actual version from package.json\n    return '0.1.0';\n  }\n}\n\n/**\n * Create a new HTTP client instance\n */\nexport function createHttpClient(config?: HttpClientConfig): HttpClient {\n  return new HttpClient(config);\n}\n","import type { SeasonType } from './common';\n\n/**\n *  Farthest season back for which player participation data exists\n */\nexport const MIN_PARTICIPATION_SEASON = 2016;\n\n/**\n * Historical team abbreviations (relocated/renamed teams)\n */\nexport const HISTORICAL_TEAMS = [\n  'SD', // San Diego Chargers (now LAC)\n  'STL', // St. Louis Rams (now LA)\n  'OAK', // Oakland Raiders (now LV)\n] as const;\n\n/**\n * Valid NFL team abbreviations\n * Standard abbreviations used across nflverse\n */\nexport const NFL_TEAMS = [\n  // AFC East\n  'BUF',\n  'MIA',\n  'NE',\n  'NYJ',\n  // AFC North\n  'BAL',\n  'CIN',\n  'CLE',\n  'PIT',\n  // AFC South\n  'HOU',\n  'IND',\n  'JAX',\n  'TEN',\n  // AFC West\n  'DEN',\n  'KC',\n  'LV',\n  'LAC',\n  // NFC East\n  'DAL',\n  'NYG',\n  'PHI',\n  'WAS',\n  // NFC North\n  'CHI',\n  'DET',\n  'GB',\n  'MIN',\n  // NFC South\n  'ATL',\n  'CAR',\n  'NO',\n  'TB',\n  // NFC West\n  'ARI',\n  'LA',\n  'SF',\n  'SEA',\n] as const;\n\n/**\n * Minimum valid NFL season (modern era)\n */\nexport const MIN_SEASON = 1999;\n\n/**\n * Maximum regular season week\n */\nexport const MAX_REGULAR_SEASON_WEEK = 18;\n\n/**\n * Maximum playoff week\n */\nexport const MAX_PLAYOFF_WEEK = 22;\n\n/**\n * Valid season types\n */\nexport const SEASON_TYPES: readonly SeasonType[] = ['REG', 'POST', 'PRE'] as const;\n\n/**\n * Minimum season with depth chart data available\n */\nexport const MIN_DEPTH_CHART_SEASON = 2001;\n","/**\n * Date and time utilities for NFL data\n * @module utils/datetime\n */\n\nimport type { DateString, Season, Week } from '../types/common.js';\n\n/**\n * Parse a date string in various formats to Date object\n */\nexport function parseDate(dateString: DateString): Date {\n  const date = new Date(dateString);\n  if (isNaN(date.getTime())) {\n    throw new Error(`Invalid date string: ${dateString}`);\n  }\n  return date;\n}\n\n/**\n * Format a Date object to YYYY-MM-DD string\n */\nexport function formatDate(date: Date): DateString {\n  const year = date.getFullYear();\n  const month = String(date.getMonth() + 1).padStart(2, '0');\n  const day = String(date.getDate()).padStart(2, '0');\n  return `${year}-${month}-${day}`;\n}\n\n/**\n * Get today's date as YYYY-MM-DD string\n */\nexport function getToday(): DateString {\n  return formatDate(new Date());\n}\n\n/**\n * Calculate the season from a date\n * NFL season runs from September (current year) to February (next year)\n */\nexport function getSeasonFromDate(date: Date): Season {\n  const year = date.getFullYear();\n  const month = date.getMonth(); // 0-11\n\n  // January-August: previous year's season\n  // September-December: current year's season\n  return month < 8 ? year - 1 : year;\n}\n\n/**\n * Get the current NFL season\n * Convenience function that returns the season for today's date\n */\nexport function getCurrentSeason(): Season {\n  return getSeasonFromDate(new Date());\n}\n\n/**\n * Get the approximate start date of an NFL season\n * Regular season typically starts the first Thursday after Labor Day (first Monday in September)\n */\nexport function getSeasonStartDate(season: Season): Date {\n  // Approximate: first week of September\n  return new Date(season, 8, 1); // Month is 0-indexed, so 8 = September\n}\n\n/**\n * Get the approximate end date of an NFL regular season\n * Regular season typically ends early January\n */\nexport function getSeasonEndDate(season: Season): Date {\n  // Regular season ends in early January of the following year\n  return new Date(season + 1, 0, 10); // January 10th of next year\n}\n\n/**\n * Check if a date falls within an NFL season\n */\nexport function isDateInSeason(date: Date, season: Season): boolean {\n  const start = getSeasonStartDate(season);\n  const end = getSeasonEndDate(season);\n  return date >= start && date <= end;\n}\n\n/**\n * Get the current NFL week based on date\n * This is an approximation based on typical NFL schedule\n */\nexport function getCurrentWeek(season?: Season): Week | null {\n  const now = new Date();\n  const currentSeason = season ?? getSeasonFromDate(now);\n\n  // If we're not in the specified season, return null\n  if (!isDateInSeason(now, currentSeason)) {\n    return null;\n  }\n\n  const seasonStart = getSeasonStartDate(currentSeason);\n  const daysSinceStart = Math.floor(\n    (now.getTime() - seasonStart.getTime()) / (1000 * 60 * 60 * 24)\n  );\n\n  // Approximate week number (7 days per week, starting at week 1)\n  const week = Math.floor(daysSinceStart / 7) + 1;\n\n  // Cap at 18 weeks for regular season\n  return Math.min(week, 18);\n}\n\n/**\n * Generate an array of seasons in a range\n */\nexport function generateSeasonRange(startSeason: Season, endSeason: Season): Season[] {\n  if (startSeason > endSeason) {\n    throw new Error('Start season must be before or equal to end season');\n  }\n\n  const seasons: Season[] = [];\n  for (let season = startSeason; season <= endSeason; season++) {\n    seasons.push(season);\n  }\n  return seasons;\n}\n\n/**\n * Generate an array of weeks in a range\n */\nexport function generateWeekRange(startWeek: Week, endWeek: Week): Week[] {\n  if (startWeek > endWeek) {\n    throw new Error('Start week must be before or equal to end week');\n  }\n\n  const weeks: Week[] = [];\n  for (let week = startWeek; week <= endWeek; week++) {\n    weeks.push(week);\n  }\n  return weeks;\n}\n\n/**\n * Get all weeks for a season type\n */\nexport function getWeeksForSeasonType(seasonType: 'REG' | 'POST' | 'PRE'): Week[] {\n  switch (seasonType) {\n    case 'REG':\n      return generateWeekRange(1 as Week, 18 as Week);\n    case 'POST':\n      return generateWeekRange(19 as Week, 22 as Week);\n    case 'PRE':\n      return generateWeekRange(1 as Week, 4 as Week);\n    default:\n      return [];\n  }\n}\n\n/**\n * Check if a date is in the future\n */\nexport function isFutureDate(date: Date): boolean {\n  return date.getTime() > Date.now();\n}\n\n/**\n * Check if a date is in the past\n */\nexport function isPastDate(date: Date): boolean {\n  return date.getTime() < Date.now();\n}\n\n/**\n * Get number of days between two dates\n */\nexport function daysBetween(date1: Date, date2: Date): number {\n  const diffMs = Math.abs(date2.getTime() - date1.getTime());\n  return Math.floor(diffMs / (1000 * 60 * 60 * 24));\n}\n\n/**\n * Add days to a date\n */\nexport function addDays(date: Date, days: number): Date {\n  const result = new Date(date);\n  result.setDate(result.getDate() + days);\n  return result;\n}\n\n/**\n * Format a date for display (e.g., \"January 1, 2024\")\n */\nexport function formatDateLong(date: Date): string {\n  return date.toLocaleDateString('en-US', {\n    year: 'numeric',\n    month: 'long',\n    day: 'numeric',\n  });\n}\n\n/**\n * Format a date for display (e.g., \"Jan 1, 2024\")\n */\nexport function formatDateShort(date: Date): string {\n  return date.toLocaleDateString('en-US', {\n    year: 'numeric',\n    month: 'short',\n    day: 'numeric',\n  });\n}\n","/**\n * Data parsing utilities\n * @module utils/parse\n */\n\nimport { asyncBufferFromFile, asyncBufferFromUrl, parquetReadObjects } from 'hyparquet';\nimport Papa from 'papaparse';\n\nimport { InvalidDataError } from '../types/error.js';\n\n/**\n * CSV parsing options\n */\nexport interface CsvParseOptions {\n  /**\n   * First row contains headers\n   * @default true\n   */\n  header?: boolean;\n\n  /**\n   * Skip empty lines\n   * @default true\n   */\n  skipEmptyLines?: boolean;\n\n  /**\n   * Dynamically type values\n   * @default true\n   */\n  dynamicTyping?: boolean;\n\n  /**\n   * Transform header names\n   */\n  transformHeader?: (header: string) => string;\n}\n\n/**\n * Parse result from CSV parsing\n */\nexport interface ParseResult<T = unknown> {\n  /**\n   * Parsed data rows\n   */\n  data: T[];\n\n  /**\n   * Parse errors\n   */\n  errors: Papa.ParseError[];\n\n  /**\n   * Metadata about the parse\n   */\n  meta: Papa.ParseMeta;\n}\n\n/**\n * Parse CSV string to array of objects\n */\nexport function parseCsv<T = Record<string, unknown>>(\n  csvString: string,\n  options: CsvParseOptions = {}\n): ParseResult<T> {\n  const { header = true, skipEmptyLines = true, dynamicTyping = true, transformHeader } = options;\n\n  const parseConfig: Papa.ParseConfig<T> = {\n    header,\n    skipEmptyLines: skipEmptyLines === true ? 'greedy' : false,\n    dynamicTyping,\n  };\n\n  if (transformHeader) {\n    parseConfig.transformHeader = transformHeader;\n  }\n\n  const result = Papa.parse<T>(csvString, parseConfig);\n\n  // Filter out delimiter detection warnings - these are just informational\n  // PapaParse will still parse the CSV correctly with the default comma delimiter\n  const criticalErrors = result.errors.filter((e) => e.type !== 'Delimiter');\n\n  if (criticalErrors.length > 0) {\n    const errorMessages = criticalErrors.map((e) => e.message).join('; ');\n    throw new InvalidDataError(`CSV parse errors: ${errorMessages}`, {\n      errors: criticalErrors,\n    });\n  }\n\n  return {\n    data: result.data,\n    errors: result.errors,\n    meta: result.meta,\n  };\n}\n\n/**\n * Parse CSV from a response\n */\nexport async function parseCsvFromResponse<T = Record<string, unknown>>(\n  response: Response,\n  options: CsvParseOptions = {}\n): Promise<ParseResult<T>> {\n  const csvString = await response.text();\n  return parseCsv<T>(csvString, options);\n}\n\n/**\n * Parse JSON string safely\n */\nexport function parseJson<T = unknown>(jsonString: string): T {\n  try {\n    return JSON.parse(jsonString) as T;\n  } catch (error) {\n    throw new InvalidDataError(\n      'Failed to parse JSON',\n      { originalError: error instanceof Error ? error.message : String(error) },\n      error instanceof Error ? error : undefined\n    );\n  }\n}\n\n/**\n * Parse JSON from a response\n */\nexport async function parseJsonFromResponse<T = unknown>(response: Response): Promise<T> {\n  try {\n    return (await response.json()) as T;\n  } catch (error) {\n    throw new InvalidDataError(\n      'Failed to parse JSON response',\n      { originalError: error instanceof Error ? error.message : String(error) },\n      error instanceof Error ? error : undefined\n    );\n  }\n}\n\n/**\n * Convert string to number safely\n */\nexport function parseNumber(value: unknown): number | null {\n  if (typeof value === 'number') {\n    return value;\n  }\n\n  if (typeof value === 'string') {\n    const num = Number(value);\n    return isNaN(num) ? null : num;\n  }\n\n  return null;\n}\n\n/**\n * Convert string to boolean\n */\nexport function parseBoolean(value: unknown): boolean | null {\n  if (typeof value === 'boolean') {\n    return value;\n  }\n\n  if (typeof value === 'string') {\n    const lower = value.toLowerCase().trim();\n    if (lower === 'true' || lower === '1' || lower === 'yes') {\n      return true;\n    }\n    if (lower === 'false' || lower === '0' || lower === 'no') {\n      return false;\n    }\n  }\n\n  if (typeof value === 'number') {\n    return value !== 0;\n  }\n\n  return null;\n}\n\n/**\n * Parse an integer safely\n */\nexport function parseIntSafe(value: unknown): number | null {\n  const num = parseNumber(value);\n  return num !== null ? Math.floor(num) : null;\n}\n\n/**\n * Parse a float safely\n */\nexport function parseFloatSafe(value: unknown): number | null {\n  return parseNumber(value);\n}\n\n/**\n * Clean column name (convert to snake_case, remove special chars)\n */\nexport function cleanColumnName(name: string): string {\n  return name\n    .trim()\n    .toLowerCase()\n    .replace(/\\s+/g, '_') // spaces to underscores\n    .replace(/[^a-z0-9_]/g, '') // remove special chars\n    .replace(/_+/g, '_') // multiple underscores to single\n    .replace(/^_|_$/g, ''); // remove leading/trailing underscores\n}\n\n/**\n * Transform CSV headers to clean column names\n */\nexport function transformCsvHeader(header: string): string {\n  return cleanColumnName(header);\n}\n\n/**\n * Detect delimiter in a CSV string\n */\nexport function detectDelimiter(csvString: string): string {\n  const sample = csvString.split('\\n')[0] ?? '';\n  const delimiters = [',', ';', '\\t', '|'];\n\n  let maxCount = 0;\n  let detectedDelimiter = ',';\n\n  for (const delimiter of delimiters) {\n    const count = sample.split(delimiter).length;\n    if (count > maxCount) {\n      maxCount = count;\n      detectedDelimiter = delimiter;\n    }\n  }\n\n  return detectedDelimiter;\n}\n\n/**\n * Convert array of objects to CSV string\n */\nexport function toCsv<T extends Record<string, unknown>>(\n  data: T[],\n  options: {\n    header?: boolean;\n    delimiter?: string;\n  } = {}\n): string {\n  const { header = true, delimiter = ',' } = options;\n\n  return Papa.unparse(data, {\n    header,\n    delimiter,\n  });\n}\n\n/**\n * Convert CSV to JSON\n */\nexport function csvToJson<T = Record<string, unknown>>(\n  csvString: string,\n  options: CsvParseOptions = {}\n): T[] {\n  const result = parseCsv<T>(csvString, options);\n  return result.data;\n}\n\n/**\n * Convert JSON to CSV\n */\nexport function jsonToCsv<T extends Record<string, unknown>>(data: T[]): string {\n  return toCsv(data);\n}\n\n/**\n * Parquet parsing options\n */\nexport interface ParquetParseOptions {\n  /**\n   * Columns to read (undefined = all columns)\n   */\n  columns?: string[];\n\n  /**\n   * Starting row index\n   */\n  rowStart?: number;\n\n  /**\n   * Ending row index (exclusive)\n   */\n  rowEnd?: number;\n}\n\n/**\n * Helper to build parquet read options with proper typing\n */\nfunction buildParquetReadOptions<T>(\n  file: T,\n  options: ParquetParseOptions\n): {\n  file: T;\n  columns?: string[];\n  rowStart?: number;\n  rowEnd?: number;\n} {\n  const readOptions: {\n    file: T;\n    columns?: string[];\n    rowStart?: number;\n    rowEnd?: number;\n  } = { file };\n\n  if (options.columns !== undefined) {\n    readOptions.columns = options.columns;\n  }\n  if (options.rowStart !== undefined) {\n    readOptions.rowStart = options.rowStart;\n  }\n  if (options.rowEnd !== undefined) {\n    readOptions.rowEnd = options.rowEnd;\n  }\n\n  return readOptions;\n}\n\n/**\n * Parse Parquet data from ArrayBuffer\n * @param buffer - ArrayBuffer containing Parquet data\n * @param options - Parsing options\n * @returns Parsed data as array of objects\n */\nexport async function parseParquet<T = Record<string, unknown>>(\n  buffer: ArrayBuffer,\n  options: ParquetParseOptions = {}\n): Promise<T[]> {\n  try {\n    // Create async buffer wrapper\n    const asyncBuffer = {\n      byteLength: buffer.byteLength,\n      slice(start: number, end?: number): Promise<ArrayBuffer> {\n        return Promise.resolve(buffer.slice(start, end));\n      },\n    };\n\n    const readOptions = buildParquetReadOptions(asyncBuffer, options);\n    const data = await parquetReadObjects(readOptions);\n\n    return data as T[];\n  } catch (error) {\n    throw new InvalidDataError(\n      `Failed to parse Parquet data: ${error instanceof Error ? error.message : 'Unknown error'}`,\n      { options },\n      error instanceof Error ? error : undefined\n    );\n  }\n}\n\n/**\n * Parse Parquet file from URL\n * @param url - URL to Parquet file\n * @param options - Parsing options\n * @returns Parsed data as array of objects\n */\nexport async function parseParquetFromUrl<T = Record<string, unknown>>(\n  url: string,\n  options: ParquetParseOptions = {}\n): Promise<T[]> {\n  try {\n    const file = await asyncBufferFromUrl({ url });\n    const readOptions = buildParquetReadOptions(file, options);\n    const data = await parquetReadObjects(readOptions);\n\n    return data as T[];\n  } catch (error) {\n    throw new InvalidDataError(\n      `Failed to parse Parquet from URL: ${error instanceof Error ? error.message : 'Unknown error'}`,\n      { url, options },\n      error instanceof Error ? error : undefined\n    );\n  }\n}\n\n/**\n * Parse Parquet file from local file path (Node.js only)\n * @param filePath - Path to Parquet file\n * @param options - Parsing options\n * @returns Parsed data as array of objects\n */\nexport async function parseParquetFromFile<T = Record<string, unknown>>(\n  filePath: string,\n  options: ParquetParseOptions = {}\n): Promise<T[]> {\n  try {\n    const file = await asyncBufferFromFile(filePath);\n    const readOptions = buildParquetReadOptions(file, options);\n    const data = await parquetReadObjects(readOptions);\n\n    return data as T[];\n  } catch (error) {\n    throw new InvalidDataError(\n      `Failed to parse Parquet from file: ${error instanceof Error ? error.message : 'Unknown error'}`,\n      { filePath, options },\n      error instanceof Error ? error : undefined\n    );\n  }\n}\n\n/**\n * Parse Parquet data from HTTP response\n * @param response - Response object containing Parquet data\n * @param options - Parsing options\n * @returns Parsed data as array of objects\n */\nexport async function parseParquetFromResponse<T = Record<string, unknown>>(\n  response: Response,\n  options: ParquetParseOptions = {}\n): Promise<T[]> {\n  try {\n    const buffer = await response.arrayBuffer();\n    return parseParquet<T>(buffer, options);\n  } catch (error) {\n    throw new InvalidDataError(\n      `Failed to parse Parquet from response: ${error instanceof Error ? error.message : 'Unknown error'}`,\n      { url: response.url, options },\n      error instanceof Error ? error : undefined\n    );\n  }\n}\n","import type { Season } from '../types/common';\nimport type { NormalizeSeasonsOptions } from '../types/utils';\nimport { getCurrentSeason } from './datetime';\n\n/**\n * Normalize season input into an array of seasons\n *\n * @param seasons - Season(s) to normalize. Can be:\n *   - `undefined`: Returns default season\n *   - `true`: Returns all seasons from minSeason to maxSeason\n *   - Single season: Returns array with that season\n *   - Array of seasons: Returns the array as-is\n * @param options - Configuration options\n * @returns Array of seasons\n *\n * @example\n * ```typescript\n * // Use current season (default)\n * normalizeSeasons(); // [2024]\n *\n * // Single season\n * normalizeSeasons(2023); // [2023]\n *\n * // Multiple seasons\n * normalizeSeasons([2022, 2023]); // [2022, 2023]\n *\n * // All seasons with custom range\n * normalizeSeasons(true, { minSeason: 1920, maxSeason: 2024 }); // [1920, 1921, ..., 2024]\n *\n * // All seasons with default range (1999-present)\n * normalizeSeasons(true); // [1999, 2000, ..., 2024]\n * ```\n */\nexport function normalizeSeasons(\n  seasons?: Season | Season[] | true,\n  options: NormalizeSeasonsOptions = {}\n): Season[] {\n  const currentSeason = getCurrentSeason();\n  const { minSeason = 1999, maxSeason = currentSeason, defaultSeason = currentSeason } = options;\n\n  // If undefined, use default season\n  if (seasons === undefined) {\n    return [defaultSeason];\n  }\n\n  // If true, return all available seasons from minSeason to maxSeason\n  if (seasons === true) {\n    const yearCount = maxSeason - minSeason + 1;\n    const allSeasons: Season[] = new Array<number>(yearCount);\n    for (let i = 0; i < yearCount; i++) {\n      allSeasons[i] = minSeason + i;\n    }\n    return allSeasons;\n  }\n\n  // If array, return as-is\n  if (Array.isArray(seasons)) {\n    return seasons;\n  }\n\n  // If single season, wrap in array\n  return [seasons];\n}\n","/**\n * URL building utilities for nflverse endpoints\n * @module utils/url\n */\n\nimport { getConfig } from '../config/manager.js';\n\nimport type { Season } from '../types/common.js';\n\n/**\n * Data file types available from nflverse\n */\nexport type DataFileType =\n  | 'pbp' // Play-by-play\n  | 'player_stats' // Player statistics\n  | 'rosters' // Team rosters\n  | 'schedules' // Game schedules\n  | 'teams' // Team information\n  | 'players' // Player information\n  | 'participation' // Participation data\n  | 'depth_charts' // Depth charts\n  | 'injuries' // Injury reports\n  | 'draft_picks' // Draft picks\n  | 'contracts' // Player contracts\n  | 'nextgen_stats' // Next Gen Stats\n  | 'qbr' // ESPN QBR\n  | 'pfr' // Pro Football Reference data\n  | 'snap_counts'; // Snap counts\n\n/**\n * File format for data downloads\n */\nexport type FileFormat = 'csv' | 'parquet' | 'rds' | 'json';\n\n/**\n * Build a URL for nflverse data\n */\nexport function buildNflverseUrl(\n  dataType: DataFileType,\n  fileName: string,\n  format: FileFormat = 'csv'\n): string {\n  const config = getConfig();\n  const baseUrl = config.dataSources.baseUrl;\n\n  // nflverse URLs follow pattern: {baseUrl}/{dataType}/{fileName}.{format}\n  return `${baseUrl}/${dataType}/${fileName}.${format}`;\n}\n\n/**\n * Build URL for play-by-play data\n */\nexport function buildPbpUrl(season: Season, format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('pbp', `play_by_play_${season}`, format);\n}\n\n/**\n * Build URL for player stats\n */\nexport function buildPlayerStatsUrl(season: Season, format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('player_stats', `player_stats_${season}`, format);\n}\n\n/**\n * Build URL for roster data\n */\nexport function buildRosterUrl(season: Season, format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('rosters', `roster_${season}`, format);\n}\n\n/**\n * Build URL for weekly roster data\n */\nexport function buildWeeklyRosterUrl(season: Season, format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('rosters', `roster_weekly_${season}`, format);\n}\n\n/**\n * Build URL for schedule data\n */\nexport function buildScheduleUrl(season: Season, format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('schedules', `sched_${season}`, format);\n}\n\n/**\n * Build URL for teams data\n */\nexport function buildTeamsUrl(format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('teams', 'teams', format);\n}\n\n/**\n * Build URL for players data\n */\nexport function buildPlayersUrl(format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('players', 'players', format);\n}\n\n/**\n * Build URL for participation data\n */\nexport function buildParticipationUrl(season: Season, format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('participation', `participation_${season}`, format);\n}\n\n/**\n * Build URL for depth charts\n */\nexport function buildDepthChartsUrl(season: Season, format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('depth_charts', `depth_charts_${season}`, format);\n}\n\n/**\n * Build URL for injuries data\n */\nexport function buildInjuriesUrl(season: Season, format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('injuries', `injuries_${season}`, format);\n}\n\n/**\n * Build URL for draft picks\n */\nexport function buildDraftPicksUrl(season: Season, format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('draft_picks', `draft_picks_${season}`, format);\n}\n\n/**\n * Build URL for contracts\n */\nexport function buildContractsUrl(format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('contracts', 'contracts', format);\n}\n\n/**\n * Build URL for Next Gen Stats\n */\nexport function buildNextGenStatsUrl(\n  season: Season,\n  statType: string,\n  format: FileFormat = 'csv'\n): string {\n  return buildNflverseUrl('nextgen_stats', `ngs_${statType}_${season}`, format);\n}\n\n/**\n * Build URL for snap counts\n */\nexport function buildSnapCountsUrl(season: Season, format: FileFormat = 'csv'): string {\n  return buildNflverseUrl('snap_counts', `snap_counts_${season}`, format);\n}\n\n/**\n * Parse query parameters into URL search params\n */\nexport function buildQueryString(\n  params: Record<string, string | number | boolean | undefined>\n): string {\n  const searchParams = new URLSearchParams();\n\n  for (const [key, value] of Object.entries(params)) {\n    if (value !== undefined && value !== null) {\n      searchParams.append(key, String(value));\n    }\n  }\n\n  const queryString = searchParams.toString();\n  return queryString ? `?${queryString}` : '';\n}\n\n/**\n * Add query parameters to a URL\n */\nexport function addQueryParams(\n  url: string,\n  params: Record<string, string | number | boolean | undefined>\n): string {\n  const queryString = buildQueryString(params);\n  return queryString ? `${url}${queryString}` : url;\n}\n\n/**\n * Extract filename from URL\n */\nexport function getFilenameFromUrl(url: string): string {\n  try {\n    const urlObj = new URL(url);\n    const pathname = urlObj.pathname;\n    const parts = pathname.split('/');\n    return parts[parts.length - 1] ?? 'unknown';\n  } catch {\n    return 'unknown';\n  }\n}\n\n/**\n * Check if URL is from nflverse\n */\nexport function isNflverseUrl(url: string): boolean {\n  try {\n    const urlObj = new URL(url);\n    return urlObj.hostname.includes('github.com') && url.includes('nflverse');\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Normalize URL (remove trailing slashes, etc.)\n */\nexport function normalizeUrl(url: string): string {\n  try {\n    const urlObj = new URL(url);\n    // Remove trailing slash from pathname\n    urlObj.pathname = urlObj.pathname.replace(/\\/$/, '');\n    return urlObj.toString();\n  } catch {\n    // If URL parsing fails, just remove trailing slash\n    return url.replace(/\\/$/, '');\n  }\n}\n\n/**\n * Join URL parts safely\n */\nexport function joinUrlParts(...parts: string[]): string {\n  return parts\n    .map((part, index) => {\n      // Remove leading slash from all parts except first\n      if (index > 0) {\n        part = part.replace(/^\\/+/, '');\n      }\n      // Remove trailing slash from all parts except last\n      if (index < parts.length - 1) {\n        part = part.replace(/\\/+$/, '');\n      }\n      return part;\n    })\n    .join('/');\n}\n","/**\n * Depth chart data loading functionality\n * @module data/depth-charts\n */\n\nimport { HttpClient } from '../client/client.js';\nimport { getConfig } from '../config/manager.js';\nimport type { Season } from '../types/common.js';\nimport { MIN_DEPTH_CHART_SEASON } from '../types/constants.js';\nimport type { DepthChartRecord, LoadDepthChartsOptions } from '../types/depth-chart.js';\nimport { ErrorCode, ValidationError } from '../types/error.js';\nimport { getCurrentSeason } from '../utils/datetime.js';\nimport { createLogger } from '../utils/logger.js';\nimport { parseCsv, parseParquet } from '../utils/parse.js';\nimport { normalizeSeasons } from '../utils/seasons.js';\nimport { buildDepthChartsUrl } from '../utils/url.js';\n\nconst logger = createLogger('depth-charts');\n\n/**\n * Load NFL weekly depth charts\n *\n * Returns weekly depth chart information showing position rankings (starters, backups, etc.)\n * for all teams. Depth charts are published weekly during the season.\n *\n * Data is available from 2001 to the current season.\n *\n * @param seasons - Season(s) to load. Can be:\n *   - Single season number (e.g., 2023)\n *   - Array of seasons (e.g., [2022, 2023])\n *   - `true` to load all available seasons (2001-present)\n *   - Undefined to load current season\n * @param options - Load options including format preference\n * @returns Promise resolving to array of depth chart records\n *\n * @throws {ValidationError} If any season is before 2001 or in the future\n *\n * @example\n * ```typescript\n * // Load current season depth charts\n * const charts = await loadDepthCharts();\n *\n * // Load specific season\n * const charts2023 = await loadDepthCharts(2023);\n *\n * // Load multiple seasons\n * const charts = await loadDepthCharts([2022, 2023]);\n *\n * // Load all available seasons (2001-present)\n * const allCharts = await loadDepthCharts(true);\n *\n * // Find starters for a specific team and week\n * const kcStarters = charts.filter(d =>\n *   d.team === 'KC' && d.week === 1 && d.pos_rank === 1\n * );\n * ```\n *\n * @see https://nflreadr.nflverse.com/reference/load_depth_charts.html\n */\nexport async function loadDepthCharts(\n  seasons?: Season | Season[] | true,\n  options: LoadDepthChartsOptions = {}\n): Promise<DepthChartRecord[]> {\n  const { format = 'csv', ...loadOptions } = options;\n\n  const config = getConfig();\n  const currentSeason = getCurrentSeason();\n\n  // Normalize seasons\n  const seasonsToLoad = normalizeSeasons(seasons, {\n    minSeason: MIN_DEPTH_CHART_SEASON,\n    maxSeason: currentSeason,\n    defaultSeason: currentSeason,\n  });\n\n  logger.info(\n    `Loading depth charts for ${seasonsToLoad.length} season(s): ${seasonsToLoad.join(', ')} (format: ${format})`\n  );\n\n  // Validate seasons\n  for (const season of seasonsToLoad) {\n    if (season < MIN_DEPTH_CHART_SEASON) {\n      throw new ValidationError(\n        `Season ${season} is before the minimum season (${MIN_DEPTH_CHART_SEASON}) for depth chart data`,\n        ErrorCode.INVALID_SEASON,\n        { season, minSeason: MIN_DEPTH_CHART_SEASON }\n      );\n    }\n    if (season > currentSeason) {\n      throw new ValidationError(\n        `Season ${season} is in the future (current season: ${currentSeason})`,\n        ErrorCode.INVALID_SEASON,\n        { season, currentSeason }\n      );\n    }\n  }\n\n  const client = new HttpClient(config.http);\n\n  // Build URLs for each season\n  const urls = seasonsToLoad.map((season) => buildDepthChartsUrl(season, format));\n\n  logger.debug(`Fetching from ${urls.length} URL(s)`);\n\n  // Fetch all seasons in parallel\n  const datasets: DepthChartRecord[][] = [];\n\n  const fetchPromises = urls.map(async (url) => {\n    const response = await client.get(url, loadOptions);\n\n    // Parse based on format\n    if (format === 'parquet') {\n      const buffer = response.data as ArrayBuffer;\n      return parseParquet<DepthChartRecord>(buffer);\n    } else {\n      const csvString =\n        typeof response.data === 'string'\n          ? response.data\n          : new TextDecoder().decode(response.data as ArrayBuffer);\n      const parseResult = parseCsv<DepthChartRecord>(csvString);\n      return parseResult.data;\n    }\n  });\n\n  const results = await Promise.all(fetchPromises);\n  datasets.push(...results);\n\n  logger.debug(`Received ${datasets.length} datasets`);\n\n  // Concatenate all datasets efficiently\n  const totalRows = datasets.reduce((sum, data) => sum + data.length, 0);\n  const result: DepthChartRecord[] = new Array<DepthChartRecord>(totalRows);\n\n  let offset = 0;\n  for (const data of datasets) {\n    for (let i = 0; i < data.length; i++) {\n      result[offset + i] = data[i]!;\n    }\n    offset += data.length;\n  }\n\n  logger.info(`Loaded ${result.length} depth chart records`);\n\n  return result;\n}\n","/**\n * Validation utilities\n * @module utils/validation\n */\n\nimport type { Season, SeasonType, TeamAbbr, Week } from '../types/common.js';\nimport {\n  HISTORICAL_TEAMS,\n  MAX_PLAYOFF_WEEK,\n  MAX_REGULAR_SEASON_WEEK,\n  MIN_SEASON,\n  NFL_TEAMS,\n  SEASON_TYPES,\n} from '../types/constants.js';\nimport { ErrorCode, ValidationError } from '../types/error.js';\nimport type { AnyTeamAbbr } from '../types/team.js';\nimport { getCurrentSeason } from './datetime.js';\n\n/**\n * Validate a season number\n */\nexport function isValidSeason(season: number): season is Season {\n  return (\n    Number.isInteger(season) && season >= MIN_SEASON && season <= getCurrentSeason() + 1 // Allow next season for scheduling\n  );\n}\n\n/**\n * Assert a season is valid, throwing ValidationError if not\n */\nexport function assertValidSeason(season: number): asserts season is Season {\n  if (!isValidSeason(season)) {\n    const maxSeason = getCurrentSeason() + 1;\n    throw new ValidationError(\n      `Invalid season: ${String(season)}. Must be between ${MIN_SEASON} and ${maxSeason}`,\n      ErrorCode.INVALID_SEASON,\n      { season, minSeason: MIN_SEASON, maxSeason }\n    );\n  }\n}\n\n/**\n * Validate a week number\n */\nexport function isValidWeek(week: number, seasonType: SeasonType = 'REG'): week is Week {\n  if (!Number.isInteger(week) || week < 1) {\n    return false;\n  }\n\n  switch (seasonType) {\n    case 'REG':\n      return week <= MAX_REGULAR_SEASON_WEEK;\n    case 'POST':\n      return week >= 19 && week <= MAX_PLAYOFF_WEEK;\n    case 'PRE':\n      return week <= 4; // Preseason typically has 4 weeks\n    default:\n      return false;\n  }\n}\n\n/**\n * Assert a week is valid, throwing ValidationError if not\n */\nexport function assertValidWeek(\n  week: number,\n  seasonType: SeasonType = 'REG'\n): asserts week is Week {\n  if (!isValidWeek(week, seasonType)) {\n    const maxWeek =\n      seasonType === 'REG' ? MAX_REGULAR_SEASON_WEEK : seasonType === 'POST' ? MAX_PLAYOFF_WEEK : 4;\n\n    throw new ValidationError(\n      `Invalid week: ${String(week)} for season type ${seasonType}. Must be between 1 and ${maxWeek}`,\n      ErrorCode.INVALID_WEEK,\n      { week, seasonType, maxWeek }\n    );\n  }\n}\n\n/**\n * Validate a team abbreviation (current teams only)\n */\nexport function isValidTeam(team: string): team is TeamAbbr {\n  return (NFL_TEAMS as readonly string[]).includes(team);\n}\n\n/**\n * Validate a team abbreviation (including historical teams)\n */\nexport function isValidTeamOrHistorical(team: string): team is AnyTeamAbbr {\n  return (\n    (NFL_TEAMS as readonly string[]).includes(team) ||\n    (HISTORICAL_TEAMS as readonly string[]).includes(team)\n  );\n}\n\n/**\n * Assert a team abbreviation is valid, throwing ValidationError if not\n */\nexport function assertValidTeam(team: string, allowHistorical = true): asserts team is TeamAbbr {\n  const isValid = allowHistorical ? isValidTeamOrHistorical(team) : isValidTeam(team);\n\n  if (!isValid) {\n    throw new ValidationError(`Invalid team abbreviation: ${team}`, ErrorCode.INVALID_TEAM, {\n      team,\n      allowHistorical,\n    });\n  }\n}\n\n/**\n * Validate a season type\n */\nexport function isValidSeasonType(seasonType: string): seasonType is SeasonType {\n  return SEASON_TYPES.includes(seasonType as SeasonType);\n}\n\n/**\n * Assert a season type is valid, throwing ValidationError if not\n */\nexport function assertValidSeasonType(seasonType: string): asserts seasonType is SeasonType {\n  if (!isValidSeasonType(seasonType)) {\n    throw new ValidationError(\n      `Invalid season type: ${seasonType}. Must be one of: ${SEASON_TYPES.join(', ')}`,\n      ErrorCode.INVALID_PARAMETER,\n      { seasonType, validTypes: SEASON_TYPES }\n    );\n  }\n}\n\n/**\n * Validate a player ID (basic format check)\n */\nexport function isValidPlayerId(playerId: string): boolean {\n  // Player IDs are typically in format: XX-XXXXXXX\n  return typeof playerId === 'string' && playerId.length > 0;\n}\n\n/**\n * Assert a player ID is valid, throwing ValidationError if not\n */\nexport function assertValidPlayerId(playerId: string): void {\n  if (!isValidPlayerId(playerId)) {\n    throw new ValidationError(`Invalid player ID: ${playerId}`, ErrorCode.INVALID_PLAYER, {\n      playerId,\n    });\n  }\n}\n\n/**\n * Validate an array of seasons\n */\nexport function validateSeasons(seasons: number[]): Season[] {\n  const validSeasons: Season[] = [];\n\n  for (const season of seasons) {\n    assertValidSeason(season);\n    validSeasons.push(season);\n  }\n\n  return validSeasons;\n}\n\n/**\n * Validate an array of teams\n */\nexport function validateTeams(teams: string[], allowHistorical = true): TeamAbbr[] {\n  const validTeams: TeamAbbr[] = [];\n\n  for (const team of teams) {\n    assertValidTeam(team, allowHistorical);\n    validTeams.push(team);\n  }\n\n  return validTeams;\n}\n\n/**\n * Normalize team abbreviation to handle common variations\n */\nexport function normalizeTeamAbbr(team: string): string {\n  const upper = team.toUpperCase().trim();\n\n  // Handle common variations\n  const variations: Record<string, string> = {\n    LAR: 'LA', // Los Angeles Rams\n    WSH: 'WAS', // Washington\n    WFT: 'WAS', // Washington Football Team (historical)\n  };\n\n  return variations[upper] ?? upper;\n}\n","/**\n * Participation data loading functions\n * @module data/participation\n */\n\nimport { HttpClient } from '../client/client.js';\nimport { getConfig } from '../config/manager.js';\nimport type { Season } from '../types/common.js';\nimport { MIN_PARTICIPATION_SEASON } from '../types/constants.js';\nimport { DataNotFoundError, Err, NetworkError, Ok, type Result } from '../types/error.js';\nimport type {\n  LoadParticipationOptions,\n  ParticipationData,\n  ParticipationRecord,\n} from '../types/participation.js';\n\nimport { createLogger } from '../utils/logger.js';\nimport { parseCsv, parseParquet } from '../utils/parse.js';\nimport { normalizeSeasons } from '../utils/seasons.js';\nimport { buildParticipationUrl } from '../utils/url.js';\nimport { assertValidSeason } from '../utils/validation.js';\n\nconst logger = createLogger('loadParticipation');\n\n// Participation data is available from 2016 onward\n\n/**\n * Load participation data for one or more NFL seasons\n *\n * This function fetches player participation data from the nflverse data repository.\n * Participation data shows which players were on the field for each play, including\n * offensive and defensive formations, personnel groupings, and coverage schemes.\n *\n * **Data Attribution:**\n * - Pre-2023: NFL NextGenStats\n * - 2023+: FTN Data\n * - License: CC-BY-SA 4.0\n * - Required attribution: \"FTN Data via nflverse\" or \"NFL NextGenStats via nflverse\"\n *\n * @param seasons - Season(s) to load. Can be:\n *   - A single season number (e.g., 2023)\n *   - An array of seasons (e.g., [2022, 2023])\n *   - `true` to load all available seasons (2016-present)\n *   - `undefined` to load the current season\n * @param options - Additional options for loading data\n * @returns Result containing array of participation records or an error\n *\n * @example\n * ```typescript\n * // Load current season\n * const participation = await loadParticipation();\n *\n * // Load specific season\n * const part2023 = await loadParticipation(2023);\n *\n * // Load multiple seasons\n * const partMulti = await loadParticipation([2022, 2023]);\n *\n * // Load all available data (2016+)\n * const partAll = await loadParticipation(true);\n *\n * // Load with parquet format (faster, smaller file size)\n * const partParquet = await loadParticipation(2023, { format: 'parquet' });\n * ```\n *\n * @see {@link https://nflreadr.nflverse.com/reference/load_participation.html | nflreadr::load_participation}\n */\nexport async function loadParticipation(\n  seasons?: Season | Season[] | true,\n  options: LoadParticipationOptions = {}\n): Promise<Result<ParticipationData, Error>> {\n  const { format = 'csv' } = options;\n\n  try {\n    // Determine which seasons to load (participation data available from 2016+)\n    const seasonsToLoad = normalizeSeasons(seasons, { minSeason: MIN_PARTICIPATION_SEASON });\n\n    logger.debug(`Loading participation data for seasons: ${seasonsToLoad.join(', ')}`);\n\n    // Validate all seasons upfront (both general validation and participation-specific)\n    for (const season of seasonsToLoad) {\n      // General season validation (1999+)\n      assertValidSeason(season);\n\n      // Participation data only available from 2016 onward\n      if (season < MIN_PARTICIPATION_SEASON) {\n        const message = `Participation data is only available from ${MIN_PARTICIPATION_SEASON} onward. Requested season: ${season}`;\n        throw new Error(message);\n      }\n    }\n\n    // Create a single HttpClient instance for all requests\n    const config = getConfig();\n    const client = new HttpClient({\n      timeout: config.http.timeout,\n      retry: config.http.retries,\n      cache: config.cache.enabled,\n      cacheTtl: config.cache.ttl,\n      debug: config.logging.debug,\n    });\n\n    // Load data for each season in parallel\n    const results = await Promise.all(\n      seasonsToLoad.map((season) => loadParticipationForSeason(season, format, client))\n    );\n\n    // Optimize array concatenation - collect all arrays first, then concat once\n    const dataArrays: ParticipationData[] = [];\n    for (const result of results) {\n      if (result.ok) {\n        dataArrays.push(result.value);\n      } else {\n        // If any season fails, return the error\n        return result;\n      }\n    }\n\n    // Single concatenation is much faster than repeated spread operations\n    const allData =\n      dataArrays.length === 1 ? dataArrays[0]! : ([] as ParticipationData).concat(...dataArrays);\n\n    logger.debug(`Loaded ${allData.length} participation records`);\n\n    return Ok(allData);\n  } catch (error) {\n    logger.error('Failed to load participation data', error);\n    return Err(error instanceof Error ? error : new Error(String(error)));\n  }\n}\n\n/**\n * Load participation data for a single season\n */\nasync function loadParticipationForSeason(\n  season: Season,\n  format: 'csv' | 'parquet',\n  client: HttpClient\n): Promise<Result<ParticipationData, Error>> {\n  try {\n    // Build URL for the season's data\n    const url = buildParticipationUrl(season, format);\n\n    logger.debug(`Fetching participation data from: ${url}`);\n\n    // Fetch the data\n    const response = await client.get(url);\n\n    if (response.status !== 200) {\n      return Err(\n        new DataNotFoundError(`Participation data not found for season ${season}`, {\n          season,\n          url,\n          status: response.status,\n        })\n      );\n    }\n\n    // Parse based on format\n    let data: ParticipationData;\n    if (format === 'parquet') {\n      // Parse parquet data from ArrayBuffer\n      const buffer = response.data as ArrayBuffer;\n      data = await parseParquet<ParticipationRecord>(buffer);\n    } else {\n      // Parse CSV data from string\n      const csvString =\n        typeof response.data === 'string'\n          ? response.data\n          : new TextDecoder().decode(response.data as ArrayBuffer);\n      const parseResult = parseCsv<ParticipationRecord>(csvString);\n      data = parseResult.data;\n    }\n\n    logger.debug(`Parsed ${data.length} participation records for season ${season}`);\n\n    return Ok(data);\n  } catch (error) {\n    if (error instanceof Error) {\n      logger.error(`Failed to load participation data for season ${season}`, error);\n\n      // Convert to appropriate error type\n      if (error.message.includes('fetch') || error.message.includes('network')) {\n        return Err(\n          new NetworkError(`Network error loading participation data for season ${season}`, {\n            season,\n            originalError: error.message,\n          })\n        );\n      }\n\n      return Err(error);\n    }\n\n    return Err(new Error(`Unknown error loading participation data for season ${season}`));\n  }\n}\n","/**\n * Play-by-play data loading functions\n * @module data/pbp\n */\n\nimport { HttpClient } from '../client/client.js';\nimport { getConfig } from '../config/manager.js';\nimport type { Season } from '../types/common.js';\nimport { DataNotFoundError, Err, NetworkError, Ok, type Result } from '../types/error.js';\nimport type { LoadPbpOptions, PlayByPlayData, PlayByPlayRecord } from '../types/pbp.js';\n\nimport { createLogger } from '../utils/logger.js';\nimport { parseCsv, parseParquet } from '../utils/parse.js';\nimport { normalizeSeasons } from '../utils/seasons.js';\nimport { buildPbpUrl } from '../utils/url.js';\nimport { assertValidSeason } from '../utils/validation.js';\n\nconst logger = createLogger('loadPbp');\n\n/**\n * Load play-by-play data for one or more NFL seasons\n *\n * This function fetches nflfastR play-by-play data from the nflverse data repository.\n * The data includes detailed information about every play in NFL games, including\n * game identifiers, play descriptions, Expected Points Added (EPA), Win Probability\n * Added (WPA), and much more.\n *\n * @param seasons - Season(s) to load. Can be:\n *   - A single season number (e.g., 2023)\n *   - An array of seasons (e.g., [2022, 2023])\n *   - `true` to load all available seasons (1999-present)\n *   - `undefined` to load the current season\n * @param options - Additional options for loading data\n * @returns Result containing array of play-by-play records or an error\n *\n * @example\n * ```typescript\n * // Load current season\n * const pbp = await loadPbp();\n *\n * // Load specific season\n * const pbp2023 = await loadPbp(2023);\n *\n * // Load multiple seasons\n * const pbpMulti = await loadPbp([2022, 2023]);\n *\n * // Load all available data\n * const pbpAll = await loadPbp(true);\n *\n * // Load with parquet format (faster, smaller file size)\n * const pbpParquet = await loadPbp(2023, { format: 'parquet' });\n * ```\n *\n * @see {@link https://nflreadr.nflverse.com/reference/load_pbp.html | nflreadr::load_pbp}\n * @see {@link https://www.nflfastr.com/articles/beginners_guide.html | nflfastR Beginner's Guide}\n */\nexport async function loadPbp(\n  seasons?: Season | Season[] | true,\n  options: LoadPbpOptions = {}\n): Promise<Result<PlayByPlayData, Error>> {\n  const { format = 'csv' } = options;\n\n  try {\n    // Determine which seasons to load\n    const seasonsToLoad = normalizeSeasons(seasons);\n\n    logger.debug(`Loading PBP data for seasons: ${seasonsToLoad.join(', ')}`);\n\n    // Validate all seasons upfront\n    for (const season of seasonsToLoad) {\n      assertValidSeason(season);\n    }\n\n    // Create a single HttpClient instance for all requests\n    // This allows connection pooling and cache sharing\n    const config = getConfig();\n    const client = new HttpClient({\n      timeout: config.http.timeout,\n      retry: config.http.retries,\n      cache: config.cache.enabled,\n      cacheTtl: config.cache.ttl,\n      debug: config.logging.debug,\n    });\n\n    // Load data for each season in parallel\n    const results = await Promise.all(\n      seasonsToLoad.map((season) => loadPbpForSeason(season, format, client))\n    );\n\n    // Optimize array concatenation - collect all arrays first, then concat once\n    // This avoids repeated array copying (O(n) instead of O(n²))\n    const dataArrays: PlayByPlayData[] = [];\n    for (const result of results) {\n      if (result.ok) {\n        dataArrays.push(result.value);\n      } else {\n        // If any season fails, return the error\n        return result;\n      }\n    }\n\n    // Single concatenation is much faster than repeated spread operations\n    const allData =\n      dataArrays.length === 1 ? dataArrays[0]! : ([] as PlayByPlayData).concat(...dataArrays);\n\n    logger.debug(`Loaded ${allData.length} play-by-play records`);\n\n    return Ok(allData);\n  } catch (error) {\n    logger.error('Failed to load PBP data', error);\n    return Err(error instanceof Error ? error : new Error(String(error)));\n  }\n}\n\n/**\n * Load play-by-play data for a single season\n * Now accepts a pre-configured HttpClient for better performance\n */\nasync function loadPbpForSeason(\n  season: Season,\n  format: 'csv' | 'parquet',\n  client: HttpClient\n): Promise<Result<PlayByPlayData, Error>> {\n  try {\n    // Build URL for the season's data\n    const url = buildPbpUrl(season, format);\n\n    logger.debug(`Fetching PBP data from: ${url}`);\n\n    // Fetch the data\n    const response = await client.get(url);\n\n    if (response.status !== 200) {\n      return Err(\n        new DataNotFoundError(`Play-by-play data not found for season ${season}`, {\n          season,\n          url,\n          status: response.status,\n        })\n      );\n    }\n\n    // Parse based on format\n    let data: PlayByPlayData;\n    if (format === 'parquet') {\n      // Parse parquet data from ArrayBuffer\n      const buffer = response.data as ArrayBuffer;\n      data = await parseParquet<PlayByPlayRecord>(buffer);\n    } else {\n      // Parse CSV data from string\n      // Optimize: avoid conditional check by using TextDecoder only when needed\n      const csvString =\n        typeof response.data === 'string'\n          ? response.data\n          : new TextDecoder().decode(response.data as ArrayBuffer);\n      const parseResult = parseCsv<PlayByPlayRecord>(csvString);\n      data = parseResult.data;\n    }\n\n    logger.debug(`Parsed ${data.length} records for season ${season}`);\n\n    return Ok(data);\n  } catch (error) {\n    if (error instanceof Error) {\n      logger.error(`Failed to load PBP for season ${season}`, error);\n\n      // Convert to appropriate error type\n      if (error.message.includes('fetch') || error.message.includes('network')) {\n        return Err(\n          new NetworkError(`Network error loading play-by-play data for season ${season}`, {\n            season,\n            originalError: error.message,\n          })\n        );\n      }\n\n      return Err(error);\n    }\n\n    return Err(new Error(`Unknown error loading play-by-play data for season ${season}`));\n  }\n}\n","/**\n * Player stats data loading functions\n * @module data/playerstats\n */\n\nimport { HttpClient } from '../client/client.js';\nimport { getConfig } from '../config/manager.js';\nimport type { Season } from '../types/common.js';\nimport { DataNotFoundError, Err, NetworkError, Ok, type Result } from '../types/error.js';\nimport type {\n  LoadPlayerStatsOptions,\n  PlayerStatsData,\n  PlayerStatsRecord,\n  SummaryLevel,\n} from '../types/player-stats.js';\n\nimport { createLogger } from '../utils/logger.js';\nimport { parseCsv, parseParquet } from '../utils/parse.js';\nimport { normalizeSeasons } from '../utils/seasons.js';\nimport { buildPlayerStatsUrl } from '../utils/url.js';\nimport { assertValidSeason } from '../utils/validation.js';\n\nconst logger = createLogger('loadPlayerStats');\n\n/**\n * Load player statistics for one or more NFL seasons\n *\n * This function fetches player statistics from the nflverse data repository.\n * The data includes comprehensive player performance metrics that aim to match\n * NFL official box scores and season summaries, covering passing, rushing,\n * receiving, defensive, kicking, and special teams statistics.\n *\n * @param seasons - Season(s) to load. Can be:\n *   - A single season number (e.g., 2023)\n *   - An array of seasons (e.g., [2022, 2023])\n *   - `true` to load all available seasons (1999-present)\n *   - `undefined` to load the current season\n * @param options - Additional options for loading data\n * @returns Result containing array of player stats records or an error\n *\n * @example\n * ```typescript\n * // Load current season weekly stats\n * const stats = await loadPlayerStats();\n *\n * // Load specific season\n * const stats2023 = await loadPlayerStats(2023);\n *\n * // Load multiple seasons\n * const statsMulti = await loadPlayerStats([2022, 2023]);\n *\n * // Load regular season totals\n * const regStats = await loadPlayerStats(2023, { summaryLevel: 'reg' });\n *\n * // Load postseason totals\n * const postStats = await loadPlayerStats(2023, { summaryLevel: 'post' });\n *\n * // Load combined regular + postseason totals\n * const fullStats = await loadPlayerStats(2023, { summaryLevel: 'reg+post' });\n *\n * // Load with parquet format (faster, smaller file size)\n * const statsParquet = await loadPlayerStats(2023, { format: 'parquet' });\n * ```\n *\n * @see {@link https://nflreadr.nflverse.com/reference/load_player_stats.html | nflreadr::load_player_stats}\n */\nexport async function loadPlayerStats(\n  seasons?: Season | Season[] | true,\n  options: LoadPlayerStatsOptions = {}\n): Promise<Result<PlayerStatsData, Error>> {\n  const { format = 'csv', summaryLevel = 'week' } = options;\n\n  try {\n    // Determine which seasons to load\n    const seasonsToLoad = normalizeSeasons(seasons);\n\n    logger.debug(\n      `Loading player stats for seasons: ${seasonsToLoad.join(', ')}, level: ${summaryLevel}`\n    );\n\n    // Validate all seasons upfront\n    for (const season of seasonsToLoad) {\n      assertValidSeason(season);\n    }\n\n    // Create a single HttpClient instance for all requests\n    const config = getConfig();\n    const client = new HttpClient({\n      timeout: config.http.timeout,\n      retry: config.http.retries,\n      cache: config.cache.enabled,\n      cacheTtl: config.cache.ttl,\n      debug: config.logging.debug,\n    });\n\n    // Load data for each season in parallel\n    const results = await Promise.all(\n      seasonsToLoad.map((season) => loadPlayerStatsForSeason(season, format, summaryLevel, client))\n    );\n\n    // Optimize array concatenation - collect all arrays first, then concat once\n    const dataArrays: PlayerStatsData[] = [];\n    for (const result of results) {\n      if (result.ok) {\n        dataArrays.push(result.value);\n      } else {\n        // If any season fails, return the error\n        return result;\n      }\n    }\n\n    // Single concatenation is much faster than repeated spread operations\n    const allData =\n      dataArrays.length === 1 ? dataArrays[0]! : ([] as PlayerStatsData).concat(...dataArrays);\n\n    logger.debug(`Loaded ${allData.length} player stats records`);\n\n    return Ok(allData);\n  } catch (error) {\n    logger.error('Failed to load player stats', error);\n    return Err(error instanceof Error ? error : new Error(String(error)));\n  }\n}\n\n/**\n * Load player stats for a single season\n */\nasync function loadPlayerStatsForSeason(\n  season: Season,\n  format: 'csv' | 'parquet',\n  summaryLevel: SummaryLevel,\n  client: HttpClient\n): Promise<Result<PlayerStatsData, Error>> {\n  try {\n    // Build URL for the season's data\n    // Note: summaryLevel affects which file we fetch\n    const url = buildPlayerStatsUrl(season, format);\n\n    logger.debug(`Fetching player stats from: ${url}`);\n\n    // Fetch the data\n    const response = await client.get(url);\n\n    if (response.status !== 200) {\n      return Err(\n        new DataNotFoundError(`Player stats not found for season ${season}`, {\n          season,\n          url,\n          status: response.status,\n          summaryLevel,\n        })\n      );\n    }\n\n    // Parse based on format\n    let data: PlayerStatsData;\n    if (format === 'parquet') {\n      // Parse parquet data from ArrayBuffer\n      const buffer = response.data as ArrayBuffer;\n      data = await parseParquet<PlayerStatsRecord>(buffer);\n    } else {\n      // Parse CSV data from string\n      const csvString =\n        typeof response.data === 'string'\n          ? response.data\n          : new TextDecoder().decode(response.data as ArrayBuffer);\n      const parseResult = parseCsv<PlayerStatsRecord>(csvString);\n      data = parseResult.data;\n    }\n\n    // Apply summary level filtering/aggregation\n    data = applySummaryLevel(data, summaryLevel);\n\n    logger.debug(\n      `Parsed ${data.length} player stats records for season ${season} (level: ${summaryLevel})`\n    );\n\n    return Ok(data);\n  } catch (error) {\n    if (error instanceof Error) {\n      logger.error(`Failed to load player stats for season ${season}`, error);\n\n      // Convert to appropriate error type\n      if (error.message.includes('fetch') || error.message.includes('network')) {\n        return Err(\n          new NetworkError(`Network error loading player stats for season ${season}`, {\n            season,\n            originalError: error.message,\n          })\n        );\n      }\n\n      return Err(error);\n    }\n\n    return Err(new Error(`Unknown error loading player stats for season ${season}`));\n  }\n}\n\n/**\n * Apply summary level filtering/aggregation to player stats data\n * - 'week': Return all weekly data (no change)\n * - 'reg': Filter to regular season only, aggregate by player\n * - 'post': Filter to postseason only, aggregate by player\n * - 'reg+post': Aggregate all weeks by player\n */\nfunction applySummaryLevel(data: PlayerStatsData, summaryLevel: SummaryLevel): PlayerStatsData {\n  // If week level, return data as-is\n  if (summaryLevel === 'week') {\n    return data;\n  }\n\n  // Filter based on summary level\n  let filteredData = data;\n  if (summaryLevel === 'reg') {\n    // Regular season: weeks 1-18\n    filteredData = data.filter((record) => {\n      const week = record.week;\n      return week !== null && week >= 1 && week <= 18;\n    });\n  } else if (summaryLevel === 'post') {\n    // Postseason: weeks 19+\n    filteredData = data.filter((record) => {\n      const week = record.week;\n      return week !== null && week >= 19;\n    });\n  }\n  // For 'reg+post', we use all data (no filter)\n\n  // Aggregate by player\n  return aggregatePlayerStats(filteredData);\n}\n\n/**\n * List of numeric fields to aggregate when summing player stats\n * Defined at module level for reuse across aggregation calls\n */\nconst AGGREGATABLE_FIELDS = [\n  // Passing stats\n  'completions',\n  'attempts',\n  'passing_yards',\n  'passing_tds',\n  'interceptions',\n  'sacks',\n  'sack_yards',\n  'sack_fumbles',\n  'sack_fumbles_lost',\n  'passing_air_yards',\n  'passing_yards_after_catch',\n  'passing_first_downs',\n  'passing_epa',\n  'passing_2pt_conversions',\n  'pacr',\n  'dakota',\n  // Rushing stats\n  'carries',\n  'rushing_yards',\n  'rushing_tds',\n  'rushing_fumbles',\n  'rushing_fumbles_lost',\n  'rushing_first_downs',\n  'rushing_epa',\n  'rushing_2pt_conversions',\n  // Receiving stats\n  'receptions',\n  'targets',\n  'receiving_yards',\n  'receiving_tds',\n  'receiving_air_yards',\n  'receiving_yards_after_catch',\n  'receiving_epa',\n  'receiving_fumbles',\n  'receiving_fumbles_lost',\n  'receiving_first_downs',\n  'receiving_2pt_conversions',\n  // Defensive stats\n  'def_tackles_solo',\n  'def_tackles_with_assist',\n  'def_tackles_combined',\n  'def_tackles_for_loss',\n  'def_sacks',\n  'def_qb_hits',\n  'def_interceptions',\n  'def_interception_yards',\n  'def_interception_tds',\n  'def_pass_defended',\n  'def_fumbles_forced',\n  'def_fumble_recoveries',\n  'def_fumble_recovery_yards',\n  'def_fumble_recovery_tds',\n  'def_safeties',\n  // Kicking stats\n  'fg_made',\n  'fg_att',\n  'fg_missed',\n  'fg_blocked',\n  'fg_made_0_19',\n  'fg_made_20_29',\n  'fg_made_30_39',\n  'fg_made_40_49',\n  'fg_made_50_59',\n  'fg_made_60_plus',\n  'pat_made',\n  'pat_att',\n  'pat_missed',\n  'pat_blocked',\n  // Fantasy stats\n  'fantasy_points',\n  'fantasy_points_ppr',\n  // Special teams\n  'special_teams_tds',\n] as const;\n\n/**\n * Aggregate player stats by summing numeric fields for each player\n * Groups by player_id and sums all numeric stat fields\n */\nfunction aggregatePlayerStats(data: PlayerStatsData): PlayerStatsData {\n  if (data.length === 0) {\n    return data;\n  }\n\n  // Single-pass aggregation: group and sum simultaneously\n  const playerMap = new Map<string, PlayerStatsRecord>();\n\n  for (const record of data) {\n    const playerId = record.player_id;\n    let aggregated = playerMap.get(playerId);\n\n    if (!aggregated) {\n      // First record for this player - clone and reset week\n      // Spread preserves all numeric fields (including 0s and nulls)\n      aggregated = {\n        ...record,\n        week: null, // Aggregated stats have no week\n      };\n      playerMap.set(playerId, aggregated);\n    } else {\n      // Aggregate all numeric stat fields using loop for DRY code\n      for (const field of AGGREGATABLE_FIELDS) {\n        const aggValue = aggregated[field] as number | null | undefined;\n        const recValue = record[field] as number | null | undefined;\n        (aggregated as Record<string, number | null | undefined>)[field] =\n          (aggValue ?? 0) + (recValue ?? 0);\n      }\n    }\n  }\n\n  // Convert map to array and calculate derived fields\n  const aggregated: PlayerStatsData = [];\n  for (const record of playerMap.values()) {\n    // Calculate derived percentage fields\n    if (record.fg_att && record.fg_att > 0) {\n      record.fg_pct = (record.fg_made ?? 0) / record.fg_att;\n    }\n\n    aggregated.push(record);\n  }\n\n  return aggregated;\n}\n","/**\n * Player data loading functionality\n * @module data/players\n */\n\nimport { HttpClient } from '../client/client.js';\nimport type { LoadPlayersOptions, PlayerRecord } from '../types';\nimport { getLogger } from '../utils/logger.js';\nimport { parseCsv, parseParquet } from '../utils/parse.js';\nimport { buildPlayersUrl } from '../utils/url.js';\n\nconst logger = getLogger();\n\n/**\n * Load all-time player database\n *\n * Returns comprehensive player information including all player IDs across different systems\n * (ESPN, PFF, PFR, OTC, etc.), biographical data, and draft information.\n *\n * The player database is maintained across all NFL history and includes players from\n * multiple sources with cross-referenced IDs.\n *\n * @param options - Load options including format preference\n * @returns Promise resolving to array of player records\n *\n * @example\n * ```typescript\n * // Load all players (CSV format)\n * const players = await loadPlayers();\n *\n * // Load using Parquet format for better performance\n * const players = await loadPlayers({ format: 'parquet' });\n *\n * // Find a specific player\n * const mahomes = players.find(p => p.display_name === 'Patrick Mahomes');\n * console.log(mahomes?.gsis_id); // '00-0033873'\n * ```\n *\n * @see https://nflreadr.nflverse.com/reference/load_players.html\n */\nexport async function loadPlayers(options: LoadPlayersOptions = {}): Promise<PlayerRecord[]> {\n  const { format = 'csv', ...loadOptions } = options;\n\n  logger.info(`Loading players data (format: ${format})`);\n\n  const client = new HttpClient();\n\n  // Build URL for the format\n  const url = buildPlayersUrl(format);\n\n  logger.debug(`Fetching from: ${url}`);\n\n  // Fetch the data\n  const response = await client.get(url, loadOptions);\n\n  // Parse based on format\n  let data: PlayerRecord[];\n\n  if (format === 'parquet') {\n    const buffer = response.data as ArrayBuffer;\n    data = await parseParquet<PlayerRecord>(buffer);\n  } else {\n    const csvString =\n      typeof response.data === 'string'\n        ? response.data\n        : new TextDecoder().decode(response.data as ArrayBuffer);\n    const parseResult = parseCsv<PlayerRecord>(csvString);\n    data = parseResult.data;\n  }\n\n  logger.info(`Loaded ${data.length} player records`);\n\n  return data;\n}\n","/**\n * Load roster data\n * @module data/rosters\n */\n\nimport type { Season } from '../types/common.js';\nimport type { LoadRostersOptions, RosterRecord } from '../types/roster.js';\n\nimport { HttpClient } from '../client/client.js';\nimport { getConfig } from '../config/manager.js';\nimport { ErrorCode, ValidationError } from '../types/error.js';\nimport { getCurrentSeason } from '../utils/datetime.js';\nimport { createLogger } from '../utils/logger.js';\nimport { parseCsv, parseParquet } from '../utils/parse.js';\nimport { normalizeSeasons } from '../utils/seasons.js';\nimport { buildRosterUrl } from '../utils/url.js';\n\nconst logger = createLogger('rosters');\n\n/**\n * Load season-level NFL roster data\n *\n * Returns roster information for specified season(s). Data includes player\n * biographical information, team assignments, positions, and various player IDs\n * across different data sources.\n *\n * Data is available from 1920 to the current season.\n *\n * @param seasons - Season(s) to load. Can be:\n *   - Single season number (e.g., 2023)\n *   - Array of seasons (e.g., [2022, 2023])\n *   - `true` to load ALL available seasons (1920-present) - use with caution!\n *   - Omit to load current season (or previous season if before March)\n * @param options - Load options including format and caching\n * @returns Promise resolving to array of roster records\n *\n * @example\n * ```typescript\n * // Load current season roster\n * const rosters = await loadRosters();\n *\n * // Load specific season\n * const rosters2023 = await loadRosters(2023);\n *\n * // Load multiple seasons\n * const rosters = await loadRosters([2022, 2023]);\n *\n * // Load all seasons (careful - this is a LOT of data!)\n * const allRosters = await loadRosters(true);\n *\n * // Use Parquet format for better performance\n * const rosters = await loadRosters(2023, { format: 'parquet' });\n * ```\n *\n * @see https://nflreadr.nflverse.com/reference/load_rosters.html\n */\nexport async function loadRosters(\n  seasons?: Season | Season[] | true,\n  options: LoadRostersOptions = {}\n): Promise<RosterRecord[]> {\n  const { format = 'csv', ...loadOptions } = options;\n\n  // Determine which seasons to load\n  const currentSeason = getCurrentSeason();\n  const minSeason = 1920;\n\n  // Normalize seasons input\n  const seasonsToLoad = normalizeSeasons(seasons, {\n    minSeason,\n    maxSeason: currentSeason,\n    defaultSeason: currentSeason,\n  });\n\n  logger.info(`Loading rosters for seasons: ${seasonsToLoad.join(', ')}`);\n\n  // Validate seasons\n  for (const season of seasonsToLoad) {\n    if (season < minSeason) {\n      throw new ValidationError(\n        `Season ${season} is before the minimum season (${minSeason})`,\n        ErrorCode.INVALID_SEASON,\n        {\n          season,\n          minSeason,\n        }\n      );\n    }\n    if (season > currentSeason) {\n      throw new ValidationError(`Season ${season} is in the future`, ErrorCode.INVALID_SEASON, {\n        season,\n        currentSeason,\n      });\n    }\n  }\n\n  // Build URLs for all seasons\n  const urls = seasonsToLoad.map((season) => buildRosterUrl(season, format));\n\n  // Fetch all seasons in parallel\n  const config = getConfig();\n  const client = new HttpClient({\n    timeout: config.http.timeout,\n    retry: config.http.retries,\n    cache: config.cache.enabled,\n    cacheTtl: config.cache.ttl,\n    debug: config.logging.debug,\n  });\n  const datasets: RosterRecord[][] = [];\n\n  const fetchPromises = urls.map(async (url) => {\n    logger.debug(`Fetching roster data from: ${url}`);\n\n    const response = await client.get(url, loadOptions);\n\n    // Parse based on format\n    if (format === 'parquet') {\n      const buffer = response.data as ArrayBuffer;\n      return parseParquet<RosterRecord>(buffer);\n    } else {\n      const csvString =\n        typeof response.data === 'string'\n          ? response.data\n          : new TextDecoder().decode(response.data as ArrayBuffer);\n      const parseResult = parseCsv<RosterRecord>(csvString);\n      return parseResult.data;\n    }\n  });\n\n  const results = await Promise.all(fetchPromises);\n  datasets.push(...results);\n\n  logger.debug(`Received ${datasets.length} datasets`);\n\n  // Pre-allocate result array for better performance\n  const totalRows = datasets.reduce((sum, data) => sum + data.length, 0);\n  const result: RosterRecord[] = new Array<RosterRecord>(totalRows);\n\n  // Concatenate all datasets efficiently\n  let offset = 0;\n  for (const data of datasets) {\n    for (let i = 0; i < data.length; i++) {\n      result[offset + i] = data[i]!;\n    }\n    offset += data.length;\n  }\n\n  logger.info(`Loaded ${result.length} roster records`);\n\n  return result;\n}\n"]}