@codenkay/video-nsgplayer-core 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors/PlayerError.ts","../src/auth/AuthManager.ts","../src/config/defaults.ts","../src/events/EventEmitter.ts","../src/security/redaction.ts","../src/logging/Logger.ts","../src/auth/AuthParamsStore.ts","../src/playback/PlaybackSourceManager.ts","../src/playback/RefreshManager.ts","../src/playback/liveEdge.ts","../src/streaming/authParamsLoader.ts","../src/streaming/HlsEngine.ts","../src/player/createVideoPlayer.ts"],"sourcesContent":["export { createVideoPlayer, type VideoPlayer } from \"./player/createVideoPlayer\";\nexport {\n DEFAULT_PLAYER_CONFIG,\n DEFAULT_PLAYER_BEHAVIOR,\n DEFAULT_CONTROLS,\n DEFAULT_THEME,\n DEFAULT_WATERMARK,\n PLAYBACK_RATES,\n PACKAGE_VERSION,\n mergePlayerConfig,\n themeToCssVars,\n assertNoSecretsInConfig,\n isPlainObject,\n SECRET_SCAN_MAX_DEPTH,\n} from \"./config/defaults\";\nexport {\n PlayerErrorCode,\n createPlayerError,\n redactSensitive,\n type PlayerError,\n} from \"./errors/PlayerError\";\nexport { AuthParamsStore } from \"./auth/AuthParamsStore\";\nexport { AuthManager } from \"./auth/AuthManager\";\nexport { PlaybackSourceManager } from \"./playback/PlaybackSourceManager\";\nexport { RefreshManager } from \"./playback/RefreshManager\";\nexport {\n rewriteHlsRequestUrl,\n createAuthParamsLoader,\n resolveBuiltinHlsLoader,\n isEncryptionKeyUrl,\n} from \"./streaming/authParamsLoader\";\nexport {\n DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS,\n getLiveEdgeTime,\n isAtLiveEdge,\n seekToLiveEdge,\n type LiveMediaSnapshot,\n type SeekToLiveResult,\n} from \"./playback/liveEdge\";\nexport { EventEmitter } from \"./events/EventEmitter\";\nexport { redactObject, redactValue } from \"./security/redaction\";\nexport type * from \"./types\";\n","export enum PlayerErrorCode {\n INVALID_CONFIGURATION = \"INVALID_CONFIGURATION\",\n AUTHENTICATION_FAILED = \"AUTHENTICATION_FAILED\",\n AUTH_TOKEN_REFRESH_FAILED = \"AUTH_TOKEN_REFRESH_FAILED\",\n TOKEN_EXPIRED = \"TOKEN_EXPIRED\",\n TOKEN_REFRESH_FAILED = \"TOKEN_REFRESH_FAILED\",\n SOURCE_RESOLUTION_FAILED = \"SOURCE_RESOLUTION_FAILED\",\n MANIFEST_LOAD_FAILED = \"MANIFEST_LOAD_FAILED\",\n SEGMENT_LOAD_FAILED = \"SEGMENT_LOAD_FAILED\",\n NETWORK_ERROR = \"NETWORK_ERROR\",\n PLAYBACK_ERROR = \"PLAYBACK_ERROR\",\n UNSUPPORTED_BROWSER = \"UNSUPPORTED_BROWSER\",\n AUTOPLAY_BLOCKED = \"AUTOPLAY_BLOCKED\",\n UNKNOWN = \"UNKNOWN\",\n}\n\nexport type PlayerError = {\n code: PlayerErrorCode;\n message: string;\n category: \"config\" | \"auth\" | \"network\" | \"playback\" | \"unknown\";\n fatal: boolean;\n retryable: boolean;\n timestamp: number;\n cause?: unknown;\n};\n\nexport function createPlayerError(\n code: PlayerErrorCode,\n message: string,\n options?: Partial<Omit<PlayerError, \"code\" | \"message\" | \"timestamp\">>,\n): PlayerError {\n return {\n code,\n message: redactSensitive(message),\n category: options?.category ?? \"unknown\",\n fatal: options?.fatal ?? true,\n retryable: options?.retryable ?? false,\n timestamp: Date.now(),\n cause: options?.cause,\n };\n}\n\nexport function redactSensitive(input: string): string {\n return input\n .replace(/(Bearer\\s+)[^\\s]+/gi, \"$1[REDACTED]\")\n .replace(/([?&](token|expires|signature|sig)=)[^&]+/gi, \"$1[REDACTED]\")\n .replace(/(Authorization:\\s*)[^\\s]+/gi, \"$1[REDACTED]\");\n}\n","import {\n createPlayerError,\n PlayerErrorCode,\n} from \"../errors/PlayerError\";\nimport type { Logger } from \"../logging/Logger\";\nimport type {\n AuthConfig,\n AuthToken,\n AuthTokenProviderContext,\n} from \"../types\";\n\n/**\n * Manages provider auth-token lifecycle (independent from signed playback URL).\n * Single-flight refresh; never stores clientSecret.\n * Unauthorized recoveries are bounded to prevent infinite 401 → refresh loops.\n */\nexport class AuthManager {\n private token: AuthToken | null = null;\n private inFlight: Promise<AuthToken> | null = null;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private destroyed = false;\n /** Consecutive unauthorized refresh attempts (reset on success). */\n private unauthorizedAttempts = 0;\n private readonly maxUnauthorizedRetries: number;\n\n constructor(\n private readonly auth: AuthConfig | undefined,\n private readonly refreshBeforeExpiryMs: number,\n private readonly logger: Logger,\n private readonly onRefreshed?: (token: AuthToken) => void,\n private readonly onError?: (message: string, retryable: boolean) => void,\n maxUnauthorizedRetries = 1,\n ) {\n this.maxUnauthorizedRetries = Math.max(0, maxUnauthorizedRetries);\n }\n\n getAccessToken(): string | null {\n return this.token?.accessToken ?? null;\n }\n\n getExpiresAt(): number | null {\n return this.token?.expiresAt ?? null;\n }\n\n async ensureToken(\n context: AuthTokenProviderContext,\n ): Promise<AuthToken | null> {\n if (!this.auth?.getToken) return null;\n if (this.destroyed) return null;\n\n if (\n this.token &&\n context.reason !== \"unauthorized\" &&\n context.reason !== \"manual\" &&\n this.token.expiresAt - Date.now() > this.refreshBeforeExpiryMs\n ) {\n return this.token;\n }\n\n return this.refresh(context);\n }\n\n async refresh(context: AuthTokenProviderContext): Promise<AuthToken> {\n if (!this.auth?.getToken) {\n throw createPlayerError(\n PlayerErrorCode.INVALID_CONFIGURATION,\n \"auth.getToken is required for authenticated playback\",\n { category: \"config\", fatal: true, retryable: false },\n );\n }\n\n if (context.reason === \"unauthorized\") {\n if (this.unauthorizedAttempts >= this.maxUnauthorizedRetries) {\n const message =\n \"Auth token refresh aborted: exceeded bounded unauthorized retry limit\";\n this.onError?.(message, false);\n throw createPlayerError(\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED,\n message,\n { category: \"auth\", fatal: true, retryable: false },\n );\n }\n this.unauthorizedAttempts += 1;\n }\n\n if (this.inFlight) return this.inFlight;\n\n this.inFlight = (async () => {\n try {\n const next = await this.auth!.getToken(context);\n if (\n !next?.accessToken ||\n typeof next.expiresAt !== \"number\" ||\n next.expiresAt <= 0\n ) {\n throw createPlayerError(\n PlayerErrorCode.AUTHENTICATION_FAILED,\n \"auth.getToken returned an invalid token payload\",\n { category: \"auth\", fatal: true, retryable: true },\n );\n }\n this.token = next;\n if (context.reason !== \"unauthorized\") {\n this.unauthorizedAttempts = 0;\n }\n this.scheduleProactiveRefresh();\n this.onRefreshed?.(next);\n this.logger.debug(\"Auth token refreshed\", {\n reason: context.reason,\n expiresAt: next.expiresAt,\n });\n return next;\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n (error as { code: string }).code ===\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED\n ) {\n throw error;\n }\n const message =\n error instanceof Error ? error.message : \"Auth token refresh failed\";\n const retryable = this.unauthorizedAttempts <= this.maxUnauthorizedRetries;\n this.onError?.(message, retryable);\n throw createPlayerError(\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED,\n message,\n { category: \"auth\", fatal: !retryable, retryable, cause: error },\n );\n } finally {\n this.inFlight = null;\n }\n })();\n\n return this.inFlight;\n }\n\n private scheduleProactiveRefresh(): void {\n if (this.timer) clearTimeout(this.timer);\n if (!this.token || this.destroyed) return;\n const delay = Math.max(\n 5_000,\n this.token.expiresAt - Date.now() - this.refreshBeforeExpiryMs,\n );\n this.timer = setTimeout(() => {\n void this.refresh({\n reason: \"expiring\",\n videoId: undefined,\n }).catch(() => {\n /* onError already notified */\n });\n }, delay);\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n this.token = null;\n this.inFlight = null;\n }\n}\n","import type {\n ControlsConfig,\n PlayerBehaviorConfig,\n PlayerConfig,\n ThemeConfig,\n WatermarkConfig,\n} from \"../types\";\n\nexport const PLAYBACK_RATES = [0.5, 0.75, 1, 1.25, 1.5, 2] as const;\n\nexport const PACKAGE_VERSION = \"0.1.8\";\n\nexport const DEFAULT_PLAYER_BEHAVIOR: Required<PlayerBehaviorConfig> = {\n autoplay: true,\n startMuted: true,\n volume: 1,\n startPosition: 0,\n skipSeconds: 10,\n speedOptionCount: PLAYBACK_RATES.length,\n zoomEnabled: true,\n defaultZoom: 1,\n playbackRates: PLAYBACK_RATES,\n};\n\nexport const DEFAULT_CONTROLS: Required<ControlsConfig> = {\n enabled: true,\n showQuality: true,\n showSpeed: true,\n showCaptions: true,\n showAudio: true,\n showVolume: true,\n showFullscreen: true,\n showZoom: true,\n showSkip: true,\n showLive: true,\n seekCueDurationMs: 720,\n keyboardShortcuts: true,\n};\n\nexport const DEFAULT_THEME: Required<ThemeConfig> = {\n playIconPreset: \"triangle\",\n playButtonBackground: \"#ffffff\",\n playButtonIconColor: \"#ffffff\",\n seekTrackColor: \"#334155\",\n seekProgressColor: \"#38bdf8\",\n seekBufferedColor: \"#64748b\",\n timeColor: \"#e2e8f0\",\n controlIconColor: \"#f1f5f9\",\n focusRingColor: \"#38bdf8\",\n spinnerColor: \"#38bdf8\",\n volumeIconColor: \"#f1f5f9\",\n volumeTrackColor: \"#334155\",\n volumeProgressColor: \"#38bdf8\",\n qualityOptionTextColor: \"#e2e8f0\",\n qualityOptionBackground: \"#020617\",\n qualityOptionActiveBackground: \"#0c4a6e\",\n qualityOptionActiveTextColor: \"#bae6fd\",\n speedOptionTextColor: \"#e2e8f0\",\n speedOptionBackground: \"#020617\",\n speedOptionActiveBackground: \"#0c4a6e\",\n speedOptionActiveTextColor: \"#bae6fd\",\n zoomIconColor: \"#f1f5f9\",\n skipIconColor: \"#f1f5f9\",\n skipCueBackground: \"#ffffff\",\n skipCueTextColor: \"#ffffff\",\n liveDotColor: \"#ef4444\",\n};\n\nexport const DEFAULT_WATERMARK: Required<WatermarkConfig> = {\n enabled: true,\n text: \"\",\n durationMs: 10_000,\n intervalMaxMs: 300_000,\n};\n\nexport const DEFAULT_PLAYER_CONFIG: PlayerConfig = {\n player: DEFAULT_PLAYER_BEHAVIOR,\n controls: DEFAULT_CONTROLS,\n theme: DEFAULT_THEME,\n watermark: DEFAULT_WATERMARK,\n streaming: {\n engine: \"hls\",\n hls: {\n enableWorker: true,\n lowLatencyMode: true,\n backBufferLength: 90,\n fatalRecoveryLimit: 3,\n },\n },\n logging: { enabled: false, level: \"error\" },\n debug: { enabled: false, network: false, events: false, state: false },\n accessibility: { reducedMotion: false },\n};\n\nconst FORBIDDEN_SECRET_KEYS = [\n \"clientsecret\",\n \"apisecret\",\n \"privatekey\",\n \"video_api_secret\",\n \"basicauthpassword\",\n \"password\",\n] as const;\n\n/** Never descend into these — DOM hosts or credential callback bags. */\nconst SKIP_DEEP_SCAN_KEYS = new Set([\n \"mount\",\n \"auth\",\n \"playback\",\n \"gettoken\",\n \"getsource\",\n \"refreshsource\",\n \"keyproxyurlbuilder\",\n \"getkeyaccesstoken\",\n]);\n\n/** Hard cap so pathological graphs cannot blow the stack. */\nexport const SECRET_SCAN_MAX_DEPTH = 32;\n\n/**\n * True only for JSON-like plain objects (`{}` / `Object.create(null)`).\n * Excludes DOM nodes, class instances, arrays, dates, etc.\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n if (Array.isArray(value)) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction normalizeConfigKey(key: string): string {\n return key.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n}\n\nfunction isForbiddenSecretKey(key: string): boolean {\n const lower = normalizeConfigKey(key);\n return FORBIDDEN_SECRET_KEYS.some((k) => lower.includes(k));\n}\n\nfunction throwForbidden(path: string, key: string): never {\n throw new Error(\n `INVALID_CONFIGURATION: Forbidden secret key \"${path}${key}\" must never be passed to the browser SDK. Keep clientSecret on your server/BFF and use auth.getToken().`,\n );\n}\n\n/**\n * Scans plain config objects for forbidden secret key names.\n *\n * Enterprise guarantees:\n * - Never deep-walks DOM / host / class instances (plain-object only)\n * - Does not descend into `mount` / `auth` / `playback` (shallow key check only)\n * - Cycle-safe via WeakSet\n * - Depth-capped + iterative (no call-stack recursion)\n */\nexport function assertNoSecretsInConfig(raw: unknown): void {\n if (!isPlainObject(raw) && !Array.isArray(raw)) return;\n\n const seen = new WeakSet<object>();\n const stack: Array<{ value: unknown; path: string; depth: number }> = [\n { value: raw, path: \"\", depth: 0 },\n ];\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n if (current.depth > SECRET_SCAN_MAX_DEPTH) continue;\n\n const { value, path, depth } = current;\n\n if (Array.isArray(value)) {\n if (seen.has(value)) continue;\n seen.add(value);\n for (let i = 0; i < value.length; i += 1) {\n const item = value[i];\n if (isPlainObject(item) || Array.isArray(item)) {\n stack.push({ value: item, path: `${path}[${i}]`, depth: depth + 1 });\n }\n }\n continue;\n }\n\n if (!isPlainObject(value)) continue;\n if (seen.has(value)) continue;\n seen.add(value);\n\n for (const [key, child] of Object.entries(value)) {\n const normalized = normalizeConfigKey(key);\n\n if (isForbiddenSecretKey(key)) {\n throwForbidden(path, key);\n }\n\n // mount: host node — never inspect further\n if (normalized === \"mount\") continue;\n\n // auth / playback / callback fields: shallow secret-key check only\n if (SKIP_DEEP_SCAN_KEYS.has(normalized)) {\n if (isPlainObject(child)) {\n for (const nestedKey of Object.keys(child)) {\n if (isForbiddenSecretKey(nestedKey)) {\n throwForbidden(`${path}${key}.`, nestedKey);\n }\n }\n }\n continue;\n }\n\n if (isPlainObject(child) || Array.isArray(child)) {\n stack.push({\n value: child,\n path: path ? `${path}${key}.` : `${key}.`,\n depth: depth + 1,\n });\n }\n }\n }\n}\n\nexport type PlayerConfigPartial = Partial<{\n player: Partial<PlayerBehaviorConfig>;\n controls: Partial<ControlsConfig>;\n theme: Partial<ThemeConfig>;\n watermark: Partial<WatermarkConfig>;\n streaming: {\n engine?: \"hls\";\n hls?: Partial<PlayerConfig[\"streaming\"][\"hls\"]>;\n keyProxyUrlBuilder?: PlayerConfig[\"streaming\"][\"keyProxyUrlBuilder\"];\n getKeyAccessToken?: PlayerConfig[\"streaming\"][\"getKeyAccessToken\"];\n };\n logging: Partial<PlayerConfig[\"logging\"]>;\n debug: Partial<PlayerConfig[\"debug\"]>;\n accessibility: Partial<PlayerConfig[\"accessibility\"]>;\n}>;\n\nexport function mergePlayerConfig(partial?: PlayerConfigPartial): PlayerConfig {\n assertNoSecretsInConfig(partial);\n return {\n player: { ...DEFAULT_PLAYER_BEHAVIOR, ...partial?.player },\n controls: { ...DEFAULT_CONTROLS, ...partial?.controls },\n theme: { ...DEFAULT_THEME, ...partial?.theme },\n watermark: { ...DEFAULT_WATERMARK, ...partial?.watermark },\n streaming: {\n engine: \"hls\",\n hls: {\n ...DEFAULT_PLAYER_CONFIG.streaming.hls,\n ...partial?.streaming?.hls,\n },\n keyProxyUrlBuilder: partial?.streaming?.keyProxyUrlBuilder,\n getKeyAccessToken: partial?.streaming?.getKeyAccessToken,\n },\n logging: { ...DEFAULT_PLAYER_CONFIG.logging, ...partial?.logging },\n debug: { ...DEFAULT_PLAYER_CONFIG.debug, ...partial?.debug },\n accessibility: {\n ...DEFAULT_PLAYER_CONFIG.accessibility,\n ...partial?.accessibility,\n },\n };\n}\n\n/** Maps theme colors to CSS custom properties for UI adapters. */\nexport function themeToCssVars(\n theme: Required<ThemeConfig>,\n): Record<string, string> {\n return {\n \"--player-play-btn-bg\": theme.playButtonBackground,\n \"--player-play-btn-icon\": theme.playButtonIconColor,\n \"--player-seek-track\": theme.seekTrackColor,\n \"--player-seek-progress\": theme.seekProgressColor,\n \"--player-seek-buffered\": theme.seekBufferedColor,\n \"--player-time\": theme.timeColor,\n \"--player-control-icon\": theme.controlIconColor,\n \"--player-focus-ring\": theme.focusRingColor,\n \"--player-spinner\": theme.spinnerColor,\n \"--player-volume-icon\": theme.volumeIconColor,\n \"--player-volume-track\": theme.volumeTrackColor,\n \"--player-volume-progress\": theme.volumeProgressColor,\n \"--player-quality-text\": theme.qualityOptionTextColor,\n \"--player-quality-bg\": theme.qualityOptionBackground,\n \"--player-quality-active-bg\": theme.qualityOptionActiveBackground,\n \"--player-quality-active-text\": theme.qualityOptionActiveTextColor,\n \"--player-speed-text\": theme.speedOptionTextColor,\n \"--player-speed-bg\": theme.speedOptionBackground,\n \"--player-speed-active-bg\": theme.speedOptionActiveBackground,\n \"--player-speed-active-text\": theme.speedOptionActiveTextColor,\n \"--player-zoom-icon\": theme.zoomIconColor,\n \"--player-skip-icon\": theme.skipIconColor,\n \"--player-skip-cue-bg\": theme.skipCueBackground,\n \"--player-skip-cue-text\": theme.skipCueTextColor,\n \"--player-live-dot\": theme.liveDotColor,\n };\n}\n","import type { PlayerEventMap } from \"../types\";\n\ntype Handler<T> = T extends void ? () => void : (payload: T) => void;\n\nexport class EventEmitter {\n private listeners = new Map<keyof PlayerEventMap, Set<Function>>();\n\n on<K extends keyof PlayerEventMap>(\n event: K,\n handler: Handler<PlayerEventMap[K]>,\n ): () => void {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(handler);\n return () => this.off(event, handler);\n }\n\n off<K extends keyof PlayerEventMap>(\n event: K,\n handler: Handler<PlayerEventMap[K]>,\n ): void {\n this.listeners.get(event)?.delete(handler);\n }\n\n emit<K extends keyof PlayerEventMap>(\n event: K,\n ...args: PlayerEventMap[K] extends void ? [] : [PlayerEventMap[K]]\n ): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const handler of set) {\n try {\n (handler as Function)(...args);\n } catch {\n // never let listener failures break the player\n }\n }\n }\n\n removeAll(): void {\n this.listeners.clear();\n }\n}\n","const SENSITIVE_KEYS =\n /^(authorization|cookie|set-cookie|x-api-key|token|accessToken|access_token|clientSecret|password)$/i;\n\nconst REDACT_MAX_DEPTH = 32;\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n if (Array.isArray(value)) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction redactStringUrl(value: string): string {\n if (!/^https?:\\/\\//i.test(value) || !/[?&](token|expires)=/i.test(value)) {\n return value;\n }\n try {\n const url = new URL(value);\n for (const param of [\"token\", \"expires\", \"signature\", \"sig\"]) {\n if (url.searchParams.has(param)) {\n url.searchParams.set(param, \"[REDACTED]\");\n }\n }\n return url.toString();\n } catch {\n return \"[REDACTED_URL]\";\n }\n}\n\nexport function redactValue(\n key: string,\n value: unknown,\n seen: WeakSet<object> = new WeakSet(),\n depth = 0,\n): unknown {\n if (SENSITIVE_KEYS.test(key)) return \"[REDACTED]\";\n if (typeof value === \"string\") return redactStringUrl(value);\n if (Array.isArray(value)) {\n if (depth >= REDACT_MAX_DEPTH || seen.has(value)) return \"[REDACTED_CYCLE]\";\n seen.add(value);\n return value.map((item, index) =>\n redactValue(String(index), item, seen, depth + 1),\n );\n }\n if (isPlainObject(value)) {\n return redactObject(value, seen, depth + 1);\n }\n return value;\n}\n\n/**\n * Redacts sensitive fields. Cycle-safe and depth-capped.\n * Only walks plain objects/arrays — never DOM / host graphs.\n */\nexport function redactObject(\n obj: Record<string, unknown>,\n seen: WeakSet<object> = new WeakSet(),\n depth = 0,\n): Record<string, unknown> {\n if (depth > REDACT_MAX_DEPTH) return { \"[REDACTED]\": \"max_depth\" };\n if (seen.has(obj)) return { \"[REDACTED]\": \"cycle\" };\n seen.add(obj);\n\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n out[key] = redactValue(key, value, seen, depth);\n }\n return out;\n}\n","import { redactObject } from \"../security/redaction\";\nimport type { LoggingConfig } from \"../types\";\n\nconst LEVELS = [\"silent\", \"error\", \"warn\", \"info\", \"debug\", \"trace\"] as const;\n\nexport class Logger {\n constructor(private config: Required<LoggingConfig>) {}\n\n update(config: Partial<LoggingConfig>): void {\n this.config = { ...this.config, ...config } as Required<LoggingConfig>;\n }\n\n private shouldLog(level: (typeof LEVELS)[number]): boolean {\n if (!this.config.enabled || this.config.level === \"silent\") return false;\n return LEVELS.indexOf(level) <= LEVELS.indexOf(this.config.level);\n }\n\n private write(\n level: \"error\" | \"warn\" | \"info\" | \"debug\",\n message: string,\n details?: Record<string, unknown>,\n ): void {\n if (!this.shouldLog(level)) return;\n const payload = details ? redactObject(details) : undefined;\n const fn = console[level] ?? console.log;\n if (payload) fn(`[nsg-player] ${message}`, payload);\n else fn(`[nsg-player] ${message}`);\n }\n\n error(message: string, details?: Record<string, unknown>): void {\n this.write(\"error\", message, details);\n }\n\n warn(message: string, details?: Record<string, unknown>): void {\n this.write(\"warn\", message, details);\n }\n\n info(message: string, details?: Record<string, unknown>): void {\n this.write(\"info\", message, details);\n }\n\n debug(message: string, details?: Record<string, unknown>): void {\n this.write(\"debug\", message, details);\n }\n}\n","/**\n * Mutable store of the latest playback authorization query parameters.\n * Updated on renewal without recreating the HLS player.\n */\nexport class AuthParamsStore {\n private params: URLSearchParams;\n\n constructor(initial?: URLSearchParams | Record<string, string>) {\n if (initial instanceof URLSearchParams) {\n this.params = new URLSearchParams(initial);\n } else if (initial) {\n this.params = new URLSearchParams(initial);\n } else {\n this.params = new URLSearchParams();\n }\n }\n\n getSnapshot(): URLSearchParams {\n return new URLSearchParams(this.params);\n }\n\n toRecord(): Record<string, string> {\n const out: Record<string, string> = {};\n this.params.forEach((value, key) => {\n out[key] = value;\n });\n return out;\n }\n\n /** True when at least one auth query param is stored. */\n hasParams(): boolean {\n return [...this.params.keys()].length > 0;\n }\n\n toString(): string {\n return this.params.toString();\n }\n\n update(next: URLSearchParams | Record<string, string>): void {\n this.params =\n next instanceof URLSearchParams\n ? new URLSearchParams(next)\n : new URLSearchParams(next);\n }\n\n /**\n * Merges current auth params onto a target URL, preserving unrelated query keys.\n * Critical for child HLS playlists/segments that omit signed query params.\n */\n applyToUrl(rawUrl: string, baseOrigin?: string): string {\n const target = new URL(\n rawUrl,\n baseOrigin ??\n (typeof location !== \"undefined\" ? location.origin : \"http://localhost\"),\n );\n this.params.forEach((value, key) => {\n target.searchParams.set(key, value);\n });\n return target.toString();\n }\n}\n","import {\n createPlayerError,\n PlayerErrorCode,\n} from \"../errors/PlayerError\";\nimport type { Logger } from \"../logging/Logger\";\nimport type {\n PlaybackCredentialConfig,\n PlaybackSource,\n PlaybackSourceContext,\n} from \"../types\";\nimport { AuthParamsStore } from \"../auth/AuthParamsStore\";\n\n/**\n * Resolves and refreshes signed playback sources via consumer callbacks.\n */\nexport class PlaybackSourceManager {\n private source: PlaybackSource | null = null;\n private inFlight: Promise<PlaybackSource> | null = null;\n readonly authParams = new AuthParamsStore();\n\n constructor(\n private readonly playback: PlaybackCredentialConfig | undefined,\n private readonly logger: Logger,\n ) {}\n\n getSource(): PlaybackSource | null {\n return this.source;\n }\n\n getExpiresAt(): number | null {\n return this.source?.expiresAt ?? null;\n }\n\n async load(\n context: PlaybackSourceContext,\n ): Promise<PlaybackSource> {\n if (!this.playback?.getSource) {\n throw createPlayerError(\n PlayerErrorCode.INVALID_CONFIGURATION,\n \"playback.getSource is required when not using sourceUrl\",\n { category: \"config\", fatal: true, retryable: false },\n );\n }\n return this.run(context, () => this.playback!.getSource(context));\n }\n\n async refresh(\n context: PlaybackSourceContext,\n ): Promise<PlaybackSource> {\n const refresher =\n this.playback?.refreshSource ?? this.playback?.getSource;\n if (!refresher) {\n throw createPlayerError(\n PlayerErrorCode.INVALID_CONFIGURATION,\n \"playback.refreshSource or playback.getSource is required\",\n { category: \"config\", fatal: true, retryable: false },\n );\n }\n return this.run(context, () => refresher(context));\n }\n\n applyDirectSource(source: PlaybackSource): void {\n this.source = source;\n this.applyAuthParams(source);\n }\n\n private async run(\n context: PlaybackSourceContext,\n fn: () => Promise<PlaybackSource>,\n ): Promise<PlaybackSource> {\n if (this.inFlight) return this.inFlight;\n\n this.inFlight = (async () => {\n try {\n const next = await fn();\n if (!next?.url || typeof next.expiresAt !== \"number\") {\n throw createPlayerError(\n PlayerErrorCode.SOURCE_RESOLUTION_FAILED,\n \"Playback source callback returned an invalid payload\",\n { category: \"playback\", fatal: true, retryable: true },\n );\n }\n this.source = next;\n this.applyAuthParams(next);\n this.logger.debug(\"Playback source resolved\", {\n reason: context.reason,\n expiresAt: next.expiresAt,\n });\n return next;\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error) throw error;\n throw createPlayerError(\n PlayerErrorCode.SOURCE_RESOLUTION_FAILED,\n error instanceof Error ? error.message : \"Source resolution failed\",\n { category: \"playback\", fatal: true, retryable: true, cause: error },\n );\n } finally {\n this.inFlight = null;\n }\n })();\n\n return this.inFlight;\n }\n\n private applyAuthParams(source: PlaybackSource): void {\n if (source.authParams) {\n this.authParams.update(source.authParams);\n return;\n }\n try {\n const url = new URL(source.url);\n const params: Record<string, string> = {};\n url.searchParams.forEach((value, key) => {\n params[key] = value;\n });\n if (source.token) params.token = source.token;\n this.authParams.update(params);\n } catch {\n if (source.token) {\n this.authParams.update({ token: source.token });\n }\n }\n }\n\n destroy(): void {\n this.source = null;\n this.inFlight = null;\n }\n}\n","import type { AuthManager } from \"../auth/AuthManager\";\nimport type { Logger } from \"../logging/Logger\";\nimport type { PlaybackSourceManager } from \"./PlaybackSourceManager\";\n\nexport type RefreshReason =\n | \"proactive\"\n | \"frag_error\"\n | \"level_error\"\n | \"key_error\"\n | \"fatal_network\"\n | \"manual\";\n\nexport type RefreshManagerOptions = {\n videoId: string;\n authManager: AuthManager;\n sourceManager: PlaybackSourceManager;\n refreshBeforeExpiryMs: number;\n renewMaxRetries: number;\n renewBackoffMs: number;\n coalesceMs: number;\n logger: Logger;\n isDestroyed: () => boolean;\n onRenewing?: () => void;\n onRenewed?: (expiresAt: number) => void;\n onFatal?: (message: string) => void;\n};\n\n/**\n * Schedules signed-URL renewal (playback clock) with single-flight + coalesce.\n * Ensures auth token is fresh before calling refreshSource.\n */\nexport class RefreshManager {\n private timer: ReturnType<typeof setTimeout> | null = null;\n private coalesceTimer: ReturnType<typeof setTimeout> | null = null;\n private inFlight = false;\n private consecutiveFailures = 0;\n private stopped = false;\n private pendingReason: RefreshReason | null = null;\n\n constructor(private readonly options: RefreshManagerOptions) {}\n\n start(initialExpiresAt: number): void {\n this.schedule(initialExpiresAt);\n }\n\n requestRenew(reason: RefreshReason = \"frag_error\"): void {\n if (this.stopped || this.options.isDestroyed()) return;\n this.pendingReason = reason;\n if (this.coalesceTimer) return;\n this.coalesceTimer = setTimeout(() => {\n this.coalesceTimer = null;\n const reasonToUse = this.pendingReason ?? \"frag_error\";\n this.pendingReason = null;\n void this.renew(reasonToUse);\n }, this.options.coalesceMs);\n }\n\n stop(): void {\n this.stopped = true;\n if (this.timer) clearTimeout(this.timer);\n if (this.coalesceTimer) clearTimeout(this.coalesceTimer);\n this.timer = null;\n this.coalesceTimer = null;\n }\n\n private schedule(expiresAt: number): void {\n if (this.timer) clearTimeout(this.timer);\n if (this.stopped) return;\n const delay = Math.max(\n 5_000,\n expiresAt - Date.now() - this.options.refreshBeforeExpiryMs,\n );\n this.timer = setTimeout(() => {\n void this.renew(\"proactive\");\n }, delay);\n }\n\n private async renew(reason: RefreshReason): Promise<void> {\n if (this.stopped || this.options.isDestroyed() || this.inFlight) {\n if (this.inFlight) this.pendingReason = reason;\n return;\n }\n this.inFlight = true;\n this.options.onRenewing?.();\n\n try {\n await this.options.authManager.ensureToken({\n reason: reason === \"proactive\" ? \"expiring\" : \"unauthorized\",\n videoId: this.options.videoId,\n });\n\n const source = await this.options.sourceManager.refresh({\n videoId: this.options.videoId,\n reason:\n reason === \"proactive\"\n ? \"expiring\"\n : reason === \"manual\"\n ? \"manual\"\n : \"auth_error\",\n });\n\n this.consecutiveFailures = 0;\n this.options.onRenewed?.(source.expiresAt);\n this.schedule(source.expiresAt);\n this.options.logger.debug(\"Playback source renewed\", { reason });\n } catch (error) {\n this.consecutiveFailures += 1;\n const message = refreshErrorMessage(error);\n this.options.logger.warn(\"Playback refresh failed\", {\n reason,\n failure: this.consecutiveFailures,\n message,\n });\n\n if (this.consecutiveFailures >= this.options.renewMaxRetries) {\n this.options.onFatal?.(message);\n } else {\n const backoff =\n this.options.renewBackoffMs * this.consecutiveFailures;\n this.timer = setTimeout(() => {\n void this.renew(reason);\n }, backoff);\n }\n } finally {\n this.inFlight = false;\n if (this.pendingReason && !this.stopped) {\n const pending = this.pendingReason;\n this.pendingReason = null;\n void this.renew(pending);\n }\n }\n }\n}\n\nfunction refreshErrorMessage(error: unknown): string {\n if (error instanceof Error && error.message) return error.message;\n if (\n error &&\n typeof error === \"object\" &&\n \"message\" in error &&\n typeof (error as { message: unknown }).message === \"string\" &&\n (error as { message: string }).message\n ) {\n return (error as { message: string }).message;\n }\n return \"Playback refresh failed\";\n}\n","/**\n * Live-edge helpers for HLS DVR / live streams.\n * Uses HTMLMediaElement.seekable when available; falls back to duration.\n */\n\nexport const DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS = 3;\n\nexport type SeekableLike = {\n length: number;\n start: (index: number) => number;\n end: (index: number) => number;\n};\n\nexport type LiveMediaSnapshot = {\n currentTime: number;\n duration: number;\n seekable: SeekableLike;\n};\n\n/**\n * Returns the latest seekable end (live edge), or null when unknown.\n */\nexport function getLiveEdgeTime(\n media: Pick<LiveMediaSnapshot, \"duration\" | \"seekable\">,\n): number | null {\n const { seekable, duration } = media;\n try {\n if (seekable.length > 0) {\n const end = seekable.end(seekable.length - 1);\n if (Number.isFinite(end) && end >= 0) {\n return end;\n }\n }\n } catch {\n // Some browsers throw while seekable is updating mid-load.\n }\n\n if (Number.isFinite(duration) && duration > 0) {\n return duration;\n }\n\n return null;\n}\n\n/**\n * True when playback is within `toleranceSeconds` of the live edge.\n */\nexport function isAtLiveEdge(\n media: LiveMediaSnapshot,\n toleranceSeconds: number = DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS,\n): boolean {\n const edge = getLiveEdgeTime(media);\n if (edge === null) {\n return true;\n }\n const lag = edge - media.currentTime;\n return lag <= Math.max(0, toleranceSeconds);\n}\n\nexport type SeekToLiveResult =\n | { moved: true; edge: number }\n | { moved: false; reason: \"already_at_live\" | \"edge_unavailable\"; edge: number | null };\n\nexport type SeekableMediaElement = {\n currentTime: number;\n duration: number;\n seekable: SeekableLike;\n};\n\n/**\n * Seeks to the live edge. Returns whether the playhead moved.\n */\nexport function seekToLiveEdge(\n media: SeekableMediaElement,\n options?: {\n toleranceSeconds?: number;\n /** Leave a tiny buffer behind the absolute end for decoder stability. */\n edgeOffsetSeconds?: number;\n },\n): SeekToLiveResult {\n const tolerance =\n options?.toleranceSeconds ?? DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS;\n const edgeOffset = options?.edgeOffsetSeconds ?? 0.25;\n const edge = getLiveEdgeTime(media);\n\n if (edge === null) {\n return { moved: false, reason: \"edge_unavailable\", edge: null };\n }\n\n if (isAtLiveEdge(media, tolerance)) {\n return { moved: false, reason: \"already_at_live\", edge };\n }\n\n const target = Math.max(0, edge - edgeOffset);\n media.currentTime = target;\n return { moved: true, edge };\n}\n","import type Hls from \"hls.js\";\nimport { XhrLoader as BuiltinXhrLoader } from \"hls.js\";\nimport type {\n LoaderCallbacks,\n LoaderConfiguration,\n LoaderContext,\n LoaderStats,\n} from \"hls.js\";\nimport type { AuthParamsStore } from \"../auth/AuthParamsStore\";\nimport type { StreamingConfig } from \"../types\";\n\ntype HlsLoaderInstance = {\n stats: LoaderStats;\n load(\n context: LoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<LoaderContext>,\n ): void;\n destroy(): void;\n abort?: () => void;\n};\n\ntype HlsLoader = new (config: object) => HlsLoaderInstance;\n\nconst ENC_KEY_PATH_RE = /enc\\.key$/i;\nconst BUILTIN_LOADER_NAMES = new Set([\"XhrLoader\", \"FetchLoader\"]);\n\nexport type AuthParamsLoaderOptions = {\n videoId?: string;\n keyProxyUrlBuilder?: StreamingConfig[\"keyProxyUrlBuilder\"];\n getKeyAccessToken?: StreamingConfig[\"getKeyAccessToken\"];\n};\n\nexport function isEncryptionKeyUrl(\n rawUrl: string,\n baseOrigin: string = typeof location !== \"undefined\"\n ? location.origin\n : \"http://localhost\",\n): boolean {\n try {\n return ENC_KEY_PATH_RE.test(new URL(rawUrl, baseOrigin).pathname);\n } catch {\n return /enc\\.key/i.test(rawUrl);\n }\n}\n\n/**\n * Always resolve a builtin hls.js loader (XhrLoader).\n *\n * Never trust `Hls.DefaultConfig.loader` alone — if it was reassigned to a\n * custom wrapper, `extends` / nested `inner.load()` chains blow Firefox's\n * stack (`InternalError: too much recursion`).\n */\nexport function resolveBuiltinHlsLoader(HlsClass: typeof Hls): HlsLoader {\n // Module export is immune to DefaultConfig pollution.\n if (typeof BuiltinXhrLoader === \"function\") {\n return BuiltinXhrLoader as unknown as HlsLoader;\n }\n\n const start = HlsClass.DefaultConfig.loader as HlsLoader;\n let current: HlsLoader | null = start;\n const seen = new Set<HlsLoader>();\n\n while (current && !seen.has(current)) {\n seen.add(current);\n const name = typeof current.name === \"string\" ? current.name : \"\";\n if (BUILTIN_LOADER_NAMES.has(name)) {\n return current;\n }\n const parentCtor = Object.getPrototypeOf(current.prototype)\n ?.constructor as HlsLoader | undefined;\n if (\n !parentCtor ||\n parentCtor === (Object as unknown as HlsLoader) ||\n parentCtor === (Function as unknown as HlsLoader)\n ) {\n break;\n }\n current = parentCtor;\n }\n\n return start;\n}\n\n/**\n * Rewrites an HLS request URL so signed auth query params are present.\n *\n * AES `enc.key` handling (enterprise priority order):\n * 1. `keyProxyUrlBuilder` — same-origin BFF (production; server IP must pass CDN/WAF)\n * 2. Otherwise keep CDN/API URL and apply signed `token`/`expires` (and related) query\n * params — same auth model as segments on Appextech CDN hosts\n * 3. Optional `getKeyAccessToken` is applied at load-time (Bearer), not in this rewrite\n */\nexport function rewriteHlsRequestUrl(\n rawUrl: string,\n store: AuthParamsStore,\n options: AuthParamsLoaderOptions = {},\n baseOrigin: string = typeof location !== \"undefined\"\n ? location.origin\n : \"http://localhost\",\n): string {\n if (!rawUrl) return rawUrl;\n\n const parsed = new URL(rawUrl, baseOrigin);\n const isKey = ENC_KEY_PATH_RE.test(parsed.pathname);\n\n if (isKey && options.keyProxyUrlBuilder && options.videoId) {\n const snapshot = store.toRecord();\n return options.keyProxyUrlBuilder({\n videoId: options.videoId,\n keyUrl: parsed.toString(),\n token: snapshot.token,\n expires: snapshot.expires,\n username: snapshot.username,\n mobile: snapshot.mobile,\n });\n }\n\n if (!store.hasParams()) return parsed.toString();\n return store.applyToUrl(rawUrl, baseOrigin);\n}\n\nfunction createLoaderStats(): LoaderStats {\n const now = performance.now();\n return {\n aborted: false,\n loaded: 0,\n retry: 0,\n total: 0,\n chunkCount: 0,\n bwEstimate: 0,\n loading: { start: now, first: 0, end: 0 },\n parsing: { start: 0, end: 0 },\n buffering: { start: 0, first: 0, end: 0 },\n };\n}\n\n/**\n * Browser-direct enc.key fetch with optional API Bearer + signed query URL.\n * Prefer this only when the key host allows CORS + Authorization (Video API\n * origin). CDN hosts typically authenticate via query params only — use XHR.\n */\nasync function loadEncryptionKeyWithFetch(\n context: LoaderContext,\n callbacks: LoaderCallbacks<LoaderContext>,\n accessToken: string | null | undefined,\n signal: AbortSignal,\n): Promise<void> {\n const stats = createLoaderStats();\n stats.loading.first = performance.now();\n\n const headers: Record<string, string> = {\n Accept: \"*/*\",\n ...(context.headers as Record<string, string> | undefined),\n };\n if (accessToken) {\n headers.Authorization = `Bearer ${accessToken}`;\n }\n\n const response = await fetch(context.url, {\n method: \"GET\",\n headers,\n credentials: \"omit\",\n cache: \"no-store\",\n signal,\n });\n\n if (!response.ok) {\n callbacks.onError(\n {\n code: response.status,\n text: response.statusText || `enc.key HTTP ${response.status}`,\n },\n context,\n response,\n stats,\n );\n return;\n }\n\n const data = await response.arrayBuffer();\n const end = performance.now();\n stats.loading.end = end;\n stats.loaded = data.byteLength;\n stats.total = data.byteLength;\n\n // Guard against HTML challenge pages mislabeled as keys.\n const head = new TextDecoder().decode(data.slice(0, 32));\n if (/<!DOCTYPE|<html/i.test(head)) {\n callbacks.onError(\n {\n code: 403,\n text: \"enc.key returned HTML (CDN challenge/block), not an AES key\",\n },\n context,\n response,\n stats,\n );\n return;\n }\n\n callbacks.onSuccess(\n {\n url: response.url || context.url,\n data,\n code: response.status,\n },\n stats,\n context,\n response,\n );\n}\n\n/**\n * hls.js loader that:\n * - Re-applies signed auth query params on every media request\n * - Loads AES `enc.key` via BFF / optional Bearer fetch / signed-query XHR\n *\n * Uses composition (not `extends DefaultConfig.loader`) so repeated mounts,\n * HMR, or a polluted DefaultConfig cannot nest `super.load()` into recursion.\n */\nexport function createAuthParamsLoader(\n HlsClass: typeof Hls,\n store: AuthParamsStore,\n options: AuthParamsLoaderOptions = {},\n): HlsLoader {\n const BaseLoader = resolveBuiltinHlsLoader(HlsClass);\n\n return class AuthParamsLoader {\n readonly stats: LoaderStats;\n private readonly inner: HlsLoaderInstance;\n private keyAbort: AbortController | null = null;\n\n constructor(config: object) {\n this.inner = new BaseLoader(config);\n // hls.js mutates loader.stats on the instance — share the same object.\n this.stats = this.inner.stats;\n }\n\n abort(): void {\n this.keyAbort?.abort();\n this.keyAbort = null;\n this.inner.abort?.();\n }\n\n destroy(): void {\n this.keyAbort?.abort();\n this.keyAbort = null;\n this.inner.destroy();\n }\n\n load(\n context: LoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<LoaderContext>,\n ): void {\n if (!context.url) {\n this.inner.load(context, config, callbacks);\n return;\n }\n\n try {\n const originalUrl = context.url;\n const isKey = isEncryptionKeyUrl(originalUrl);\n const usingKeyProxy = Boolean(\n isKey && options.keyProxyUrlBuilder && options.videoId,\n );\n context.url = rewriteHlsRequestUrl(originalUrl, store, options);\n\n if (usingKeyProxy) {\n this.inner.load(context, config, callbacks);\n return;\n }\n\n if (isKey && typeof options.getKeyAccessToken === \"function\") {\n const accessToken = options.getKeyAccessToken() ?? null;\n if (accessToken) {\n this.keyAbort?.abort();\n this.keyAbort = new AbortController();\n const timeoutMs =\n typeof config?.timeout === \"number\" && config.timeout > 0\n ? config.timeout\n : 20_000;\n const timer = setTimeout(() => this.keyAbort?.abort(), timeoutMs);\n\n void loadEncryptionKeyWithFetch(\n context,\n callbacks,\n accessToken,\n this.keyAbort.signal,\n )\n .catch((error: unknown) => {\n const stats = createLoaderStats();\n const aborted =\n error instanceof DOMException && error.name === \"AbortError\";\n callbacks.onError(\n {\n code: 0,\n text: aborted\n ? \"enc.key fetch aborted/timeout\"\n : error instanceof Error\n ? error.message\n : \"enc.key fetch failed\",\n },\n context,\n null,\n stats,\n );\n })\n .finally(() => {\n clearTimeout(timer);\n });\n return;\n }\n }\n } catch {\n // Fall through to default loader.\n }\n\n this.inner.load(context, config, callbacks);\n }\n };\n}\n","import type { AuthParamsStore } from \"../auth/AuthParamsStore\";\nimport type { Logger } from \"../logging/Logger\";\nimport type {\n HlsQualityLevel,\n HlsSupportMode,\n PlayerState,\n QualitySelection,\n StreamingConfig,\n} from \"../types\";\nimport { createAuthParamsLoader } from \"./authParamsLoader\";\n\nexport type HlsEngineCallbacks = {\n onStateChange?: (state: PlayerState) => void;\n onSupportMode?: (mode: HlsSupportMode) => void;\n onFatalError?: (message: string) => void;\n onAuthRecoveryNeeded?: (reason: string) => void;\n onQualitiesChange?: (levels: HlsQualityLevel[]) => void;\n onQualitySelectionChange?: (selection: QualitySelection) => void;\n onEnded?: () => void;\n};\n\nexport type HlsEngineOptions = {\n videoEl: HTMLVideoElement;\n playbackUrl: string;\n authParams: AuthParamsStore;\n autoplay: boolean;\n startMuted: boolean;\n startPosition?: number;\n volume?: number;\n videoId?: string;\n keyProxyUrlBuilder?: StreamingConfig[\"keyProxyUrlBuilder\"];\n getKeyAccessToken?: StreamingConfig[\"getKeyAccessToken\"];\n hlsConfig: {\n enableWorker: boolean;\n lowLatencyMode: boolean;\n backBufferLength: number;\n fatalRecoveryLimit: number;\n };\n logger: Logger;\n callbacks: HlsEngineCallbacks;\n};\n\nfunction isAuthHttpStatus(code: unknown): boolean {\n return code === 401 || code === 403;\n}\n\n/**\n * Dual-path HLS engine: hls.js when supported, otherwise native Safari HLS.\n *\n * Signed CDN playback requires auth query params on every HLS request\n * (playlists, segments, and AES `enc.key` on CDN hosts).\n *\n * Optional `streaming.keyProxyUrlBuilder` (same-origin BFF) or\n * `streaming.getKeyAccessToken` (browser Bearer) for Video API–origin keys\n * when query-signed CDN access is insufficient.\n */\nexport class HlsEngine {\n private hls: import(\"hls.js\").default | null = null;\n private destroyed = false;\n private supportMode: HlsSupportMode = \"unsupported\";\n private networkRecoveryCount = 0;\n private mediaRecoveryCount = 0;\n private qualities: HlsQualityLevel[] = [];\n private qualitySelection: QualitySelection = \"auto\";\n\n constructor(private readonly options: HlsEngineOptions) {}\n\n async start(): Promise<void> {\n const { videoEl, playbackUrl, startMuted, volume } = this.options;\n\n videoEl.muted = startMuted;\n if (typeof volume === \"number\") {\n videoEl.volume = Math.min(1, Math.max(0, volume));\n }\n\n const Hls = (await import(\"hls.js\")).default;\n\n if (Hls.isSupported()) {\n this.supportMode = \"hls.js\";\n this.options.callbacks.onSupportMode?.(\"hls.js\");\n await this.startWithHlsJs(Hls, playbackUrl);\n return;\n }\n\n if (videoEl.canPlayType(\"application/vnd.apple.mpegurl\")) {\n this.supportMode = \"native\";\n this.options.callbacks.onSupportMode?.(\"native\");\n videoEl.src = this.options.authParams.applyToUrl(playbackUrl);\n this.bindMediaEvents();\n this.options.callbacks.onStateChange?.(\"ready\");\n await this.applyStartPositionAndAutoplay();\n return;\n }\n\n this.supportMode = \"unsupported\";\n this.options.callbacks.onSupportMode?.(\"unsupported\");\n this.options.callbacks.onFatalError?.(\n \"HLS is not supported in this browser\",\n );\n }\n\n private async startWithHlsJs(\n Hls: typeof import(\"hls.js\").default,\n playbackUrl: string,\n ): Promise<void> {\n const {\n videoEl,\n authParams,\n hlsConfig,\n callbacks,\n videoId,\n keyProxyUrlBuilder,\n getKeyAccessToken,\n } = this.options;\n\n const loader = createAuthParamsLoader(Hls, authParams, {\n videoId,\n keyProxyUrlBuilder,\n getKeyAccessToken,\n });\n\n this.hls = new Hls({\n enableWorker: hlsConfig.enableWorker,\n lowLatencyMode: hlsConfig.lowLatencyMode,\n backBufferLength: hlsConfig.backBufferLength,\n loader: loader as typeof Hls.DefaultConfig.loader,\n });\n\n this.hls.attachMedia(videoEl);\n this.hls.loadSource(authParams.applyToUrl(playbackUrl));\n\n this.hls.on(Hls.Events.MANIFEST_PARSED, (_event, data) => {\n if (this.destroyed) return;\n this.qualities = (data.levels ?? []).map((level, index) => ({\n index,\n height: level.height ?? 0,\n width: level.width ?? 0,\n bitrate: level.bitrate ?? 0,\n label:\n level.height != null && level.height > 0\n ? `${level.height}p`\n : `Level ${index}`,\n }));\n callbacks.onQualitiesChange?.(this.qualities);\n callbacks.onStateChange?.(\"ready\");\n void this.applyStartPositionAndAutoplay();\n });\n\n this.hls.on(Hls.Events.ERROR, (_event, data) => {\n this.handleHlsError(Hls, data);\n });\n\n this.bindMediaEvents();\n }\n\n private handleHlsError(\n Hls: typeof import(\"hls.js\").default,\n data: {\n fatal: boolean;\n type: string;\n details: string;\n response?: { code?: number };\n },\n ): void {\n if (this.destroyed) return;\n const { callbacks, hlsConfig } = this.options;\n const status = data.response?.code;\n\n // Only treat real HTTP auth failures as credential expiry.\n // Status 0 / undefined is usually CORS/abort — renewing cannot fix that.\n const authFailure = isAuthHttpStatus(status);\n\n if (data.details === Hls.ErrorDetails.KEY_LOAD_ERROR) {\n if (authFailure) {\n callbacks.onAuthRecoveryNeeded?.(\"key_error\");\n if (!data.fatal) return;\n } else if (!data.fatal) {\n // Do not require getKeyAccessToken/keyProxy — CDN keys use signed query.\n // Surface the real failure (HTTP / network) instead of a configure gate.\n callbacks.onFatalError?.(\n status\n ? `Encryption key load failed (HTTP ${status}).`\n : \"Encryption key load failed (network/CORS). Ensure signed query params are applied, or use keyProxyUrlBuilder / getKeyAccessToken when the key host requires API Bearer.\",\n );\n return;\n }\n }\n\n if (!data.fatal) {\n if (\n authFailure &&\n data.type === Hls.ErrorTypes.NETWORK_ERROR &&\n (data.details === Hls.ErrorDetails.FRAG_LOAD_ERROR ||\n data.details === Hls.ErrorDetails.LEVEL_LOAD_ERROR)\n ) {\n callbacks.onAuthRecoveryNeeded?.(\n data.details === Hls.ErrorDetails.LEVEL_LOAD_ERROR\n ? \"level_error\"\n : \"frag_error\",\n );\n }\n return;\n }\n\n if (data.type === Hls.ErrorTypes.NETWORK_ERROR) {\n this.networkRecoveryCount += 1;\n if (this.networkRecoveryCount <= hlsConfig.fatalRecoveryLimit) {\n if (authFailure) {\n callbacks.onAuthRecoveryNeeded?.(\"fatal_network\");\n }\n this.hls?.startLoad();\n return;\n }\n }\n\n if (data.type === Hls.ErrorTypes.MEDIA_ERROR) {\n this.mediaRecoveryCount += 1;\n if (this.mediaRecoveryCount <= hlsConfig.fatalRecoveryLimit) {\n this.hls?.recoverMediaError();\n return;\n }\n }\n\n callbacks.onFatalError?.(data.details || \"Fatal HLS error\");\n }\n\n private async applyStartPositionAndAutoplay(): Promise<void> {\n if (this.destroyed) return;\n const { videoEl, autoplay, startPosition } = this.options;\n\n if (typeof startPosition === \"number\" && startPosition > 0) {\n const seek = () => {\n if (this.destroyed) return;\n try {\n videoEl.currentTime = startPosition;\n } catch {\n // Ignore seek before seekable ranges are ready.\n }\n };\n if (videoEl.seekable.length > 0) {\n seek();\n } else {\n videoEl.addEventListener(\"loadedmetadata\", seek, { once: true });\n }\n }\n\n if (!autoplay) return;\n try {\n await videoEl.play();\n } catch {\n if (!videoEl.muted) {\n videoEl.muted = true;\n try {\n await videoEl.play();\n } catch {\n this.options.logger.warn(\"Autoplay blocked\");\n }\n }\n }\n }\n\n private bindMediaEvents(): void {\n const { videoEl, callbacks } = this.options;\n videoEl.addEventListener(\"playing\", () =>\n callbacks.onStateChange?.(\"playing\"),\n );\n videoEl.addEventListener(\"pause\", () => {\n if (!videoEl.ended) callbacks.onStateChange?.(\"paused\");\n });\n videoEl.addEventListener(\"waiting\", () =>\n callbacks.onStateChange?.(\"buffering\"),\n );\n videoEl.addEventListener(\"ended\", () => {\n callbacks.onStateChange?.(\"ended\");\n callbacks.onEnded?.();\n });\n }\n\n updateAuthParams(): void {\n if (this.supportMode === \"native\" && this.options.videoEl) {\n const time = this.options.videoEl.currentTime;\n const wasPaused = this.options.videoEl.paused;\n this.options.videoEl.src = this.options.authParams.applyToUrl(\n this.options.playbackUrl,\n );\n this.options.videoEl.currentTime = time;\n if (!wasPaused) void this.options.videoEl.play();\n }\n }\n\n resumeAfterAuthRenew(): void {\n this.networkRecoveryCount = 0;\n this.hls?.startLoad();\n this.updateAuthParams();\n }\n\n setQuality(selection: QualitySelection): void {\n this.qualitySelection = selection;\n if (!this.hls) return;\n this.hls.currentLevel = selection === \"auto\" ? -1 : selection;\n this.options.callbacks.onQualitySelectionChange?.(selection);\n }\n\n getQuality(): QualitySelection {\n return this.qualitySelection;\n }\n\n getQualities(): HlsQualityLevel[] {\n return this.qualities;\n }\n\n getSupportMode(): HlsSupportMode {\n return this.supportMode;\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.hls?.destroy();\n this.hls = null;\n const { videoEl } = this.options;\n videoEl.removeAttribute(\"src\");\n videoEl.load();\n }\n}\n","import { AuthManager } from \"../auth/AuthManager\";\nimport {\n assertNoSecretsInConfig,\n mergePlayerConfig,\n PACKAGE_VERSION,\n} from \"../config/defaults\";\nimport {\n createPlayerError,\n PlayerErrorCode,\n type PlayerError,\n} from \"../errors/PlayerError\";\nimport { EventEmitter } from \"../events/EventEmitter\";\nimport { Logger } from \"../logging/Logger\";\nimport { PlaybackSourceManager } from \"../playback/PlaybackSourceManager\";\nimport { RefreshManager } from \"../playback/RefreshManager\";\nimport {\n isAtLiveEdge,\n seekToLiveEdge,\n type SeekToLiveResult,\n} from \"../playback/liveEdge\";\nimport { HlsEngine } from \"../streaming/HlsEngine\";\nimport type {\n BufferedRange,\n CreateVideoPlayerOptions,\n PlayerConfig,\n PlayerDiagnostics,\n PlayerState,\n QualitySelection,\n} from \"../types\";\n\nfunction expiryStatus(\n expiresAt: number | null,\n safetyMs: number,\n): PlayerDiagnostics[\"authExpiryStatus\"] {\n if (expiresAt === null || expiresAt <= 0) return \"unknown\";\n const remaining = expiresAt - Date.now();\n if (remaining <= 0) return \"expired\";\n if (remaining <= safetyMs) return \"expiring_soon\";\n return \"valid\";\n}\n\nfunction generateSessionId(): string {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n return `ps_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport type VideoPlayer = {\n play: () => Promise<void>;\n pause: () => void;\n seek: (time: number) => void;\n /** Jump to the latest live edge. No-op when already at live. */\n goToLive: () => SeekToLiveResult;\n isLive: () => boolean;\n isAtLiveEdge: () => boolean;\n getCurrentTime: () => number;\n getDuration: () => number;\n setVolume: (volume: number) => void;\n getVolume: () => number;\n mute: () => void;\n unmute: () => void;\n isMuted: () => boolean;\n setPlaybackRate: (rate: number) => void;\n getPlaybackRate: () => number;\n getState: () => PlayerState;\n getBufferedRanges: () => BufferedRange[];\n getQuality: () => QualitySelection;\n setQuality: (selection: QualitySelection | string) => void;\n getAvailableQualities: () => ReturnType<HlsEngine[\"getQualities\"]>;\n enterFullscreen: () => Promise<void>;\n exitFullscreen: () => Promise<void>;\n isFullscreen: () => boolean;\n reload: () => Promise<void>;\n destroy: () => void;\n getDiagnostics: () => PlayerDiagnostics;\n getConfig: () => PlayerConfig;\n updateConfig: (partial: Parameters<typeof mergePlayerConfig>[0]) => void;\n on: EventEmitter[\"on\"];\n off: EventEmitter[\"off\"];\n};\n\n/**\n * Creates a framework-agnostic video player.\n * Never pass clientSecret — use auth.getToken / playback.getSource callbacks.\n */\nexport function createVideoPlayer(\n options: CreateVideoPlayerOptions,\n): VideoPlayer {\n // Scan only config-shaped fields — never deep-walk mount (HTMLVideoElement)\n // or credential callback objects (auth / playback).\n assertNoSecretsInConfig({\n videoId: options.videoId,\n sourceUrl: options.sourceUrl,\n player: options.player,\n controls: options.controls,\n theme: options.theme,\n watermark: options.watermark,\n streaming: options.streaming,\n logging: options.logging,\n debug: options.debug,\n accessibility: options.accessibility,\n });\n\n let config = mergePlayerConfig({\n player: options.player,\n controls: options.controls,\n theme: options.theme,\n watermark: options.watermark,\n streaming: options.streaming,\n logging: options.logging,\n debug: options.debug,\n accessibility: options.accessibility,\n });\n\n const events = new EventEmitter();\n const logger = new Logger(config.logging);\n const playbackSessionId = generateSessionId();\n\n let state: PlayerState = \"idle\";\n let destroyed = false;\n let lastError: PlayerError | null = null;\n let videoEl = options.mount ?? null;\n let engine: HlsEngine | null = null;\n let refreshManager: RefreshManager | null = null;\n let fullscreenEl: HTMLElement | null = null;\n let isLiveStream = false;\n\n const setState = (next: PlayerState) => {\n if (destroyed && next !== \"destroyed\") return;\n state = next;\n events.emit(\"statechange\", { state: next });\n };\n\n const authManager = new AuthManager(\n options.auth,\n options.auth?.refreshBeforeExpiryMs ?? 60_000,\n logger,\n (token) => events.emit(\"authrefresh\", { expiresAt: token.expiresAt }),\n (message, retryable) =>\n events.emit(\"autherror\", { message, retryable }),\n );\n\n const sourceManager = new PlaybackSourceManager(options.playback, logger);\n\n const ensureVideoElement = (): HTMLVideoElement => {\n if (!videoEl) {\n throw createPlayerError(\n PlayerErrorCode.INVALID_CONFIGURATION,\n \"A video element must be provided via mount before starting playback\",\n { category: \"config\", fatal: true, retryable: false },\n );\n }\n return videoEl;\n };\n\n const startPlayback = async (): Promise<void> => {\n if (destroyed) return;\n setState(\"loading\");\n lastError = null;\n\n const videoId = options.videoId ?? \"unknown\";\n\n try {\n await authManager.ensureToken({\n reason: \"initial\",\n videoId: options.videoId,\n });\n\n let playbackUrl: string;\n let expiresAt: number;\n\n if (options.sourceUrl) {\n const source = {\n url: options.sourceUrl,\n expiresAt: Date.now() + 24 * 60 * 60 * 1000,\n live: /\\/hls-web-live\\//i.test(options.sourceUrl),\n };\n sourceManager.applyDirectSource(source);\n playbackUrl = source.url;\n expiresAt = source.expiresAt;\n isLiveStream = Boolean(source.live);\n } else {\n const source = await sourceManager.load({\n videoId,\n reason: \"initial\",\n });\n playbackUrl = source.url;\n expiresAt = source.expiresAt;\n isLiveStream = Boolean(source.live);\n }\n\n const el = ensureVideoElement();\n engine?.destroy();\n engine = new HlsEngine({\n videoEl: el,\n playbackUrl,\n authParams: sourceManager.authParams,\n autoplay: config.player.autoplay,\n startMuted: config.player.startMuted,\n startPosition: config.player.startPosition,\n volume: config.player.volume,\n videoId: options.videoId,\n keyProxyUrlBuilder: config.streaming.keyProxyUrlBuilder,\n // Optional: browser Bearer for Video API–origin enc.key (CORS-dependent).\n // CDN keys use signed query via the auth loader (no Bearer) — same as\n // segments. Apps can pass getKeyAccessToken or rely on keyProxyUrlBuilder.\n // When unset, defaults to AuthManager token only if explicitly requested\n // via streaming.getKeyAccessToken; otherwise query-signed XHR.\n getKeyAccessToken: config.streaming.getKeyAccessToken,\n hlsConfig: config.streaming.hls,\n logger,\n callbacks: {\n onStateChange: (s) => {\n setState(s);\n if (s === \"ready\") events.emit(\"ready\");\n if (s === \"playing\") {\n events.emit(\"play\");\n events.emit(\"playing\");\n }\n if (s === \"paused\") events.emit(\"pause\");\n if (s === \"buffering\") events.emit(\"buffering\");\n if (s === \"ended\") events.emit(\"ended\");\n },\n onFatalError: (message) => {\n lastError = createPlayerError(\n PlayerErrorCode.PLAYBACK_ERROR,\n message,\n { category: \"playback\", fatal: true, retryable: true },\n );\n setState(\"error\");\n events.emit(\"error\", {\n code: lastError.code,\n message: lastError.message,\n fatal: true,\n });\n },\n onAuthRecoveryNeeded: (reason) => {\n refreshManager?.requestRenew(\n reason as \"frag_error\" | \"level_error\" | \"key_error\" | \"fatal_network\",\n );\n },\n onQualitiesChange: () => {\n /* consumers poll getAvailableQualities */\n },\n onQualitySelectionChange: (selection) => {\n const level = engine\n ?.getQualities()\n .find((q) => q.index === selection);\n events.emit(\"qualitychange\", {\n selection,\n label: typeof selection === \"number\" ? level?.label : \"auto\",\n });\n },\n onEnded: () => events.emit(\"ended\"),\n },\n });\n\n await engine.start();\n\n if (!options.sourceUrl && options.playback) {\n refreshManager?.stop();\n refreshManager = new RefreshManager({\n videoId,\n authManager,\n sourceManager,\n refreshBeforeExpiryMs:\n options.playback.refreshBeforeExpiryMs ?? 30_000,\n renewMaxRetries: options.playback.renewMaxRetries ?? 3,\n renewBackoffMs: options.playback.renewBackoffMs ?? 2_000,\n coalesceMs: options.playback.authRecoveryCoalesceMs ?? 1_000,\n logger,\n isDestroyed: () => destroyed,\n onRenewing: () => setState(\"renewing\"),\n onRenewed: (nextExpiresAt) => {\n engine?.resumeAfterAuthRenew();\n if (!destroyed) {\n const el = videoEl;\n if (el && !el.paused && !el.ended) {\n setState(\"playing\");\n } else {\n setState(\"ready\");\n }\n }\n events.emit(\"tokenrefresh\", { expiresAt: nextExpiresAt });\n events.emit(\"sourcechange\", { expiresAt: nextExpiresAt });\n },\n onFatal: (message) => {\n lastError = createPlayerError(\n PlayerErrorCode.TOKEN_REFRESH_FAILED,\n message,\n { category: \"auth\", fatal: true, retryable: true },\n );\n setState(\"error\");\n events.emit(\"error\", {\n code: lastError.code,\n message: lastError.message,\n fatal: true,\n });\n },\n });\n refreshManager.start(expiresAt);\n }\n\n options.analytics?.onEvent?.({\n type: \"PLAYER_INITIALIZED\",\n payload: { videoId, playbackSessionId },\n });\n } catch (error) {\n const playerError =\n error && typeof error === \"object\" && \"code\" in error\n ? (error as PlayerError)\n : createPlayerError(\n PlayerErrorCode.UNKNOWN,\n error instanceof Error ? error.message : \"Failed to start player\",\n { category: \"unknown\", fatal: true, retryable: true, cause: error },\n );\n lastError = playerError;\n setState(\"error\");\n events.emit(\"error\", {\n code: playerError.code,\n message: playerError.message,\n fatal: playerError.fatal,\n });\n throw playerError;\n }\n };\n\n // Auto-start when mount is provided\n if (options.mount) {\n void startPlayback().catch(() => {\n /* error already emitted */\n });\n }\n\n const api: VideoPlayer = {\n async play() {\n await ensureVideoElement().play();\n },\n pause() {\n ensureVideoElement().pause();\n },\n seek(time: number) {\n const el = ensureVideoElement();\n const duration = Number.isFinite(el.duration) ? el.duration : time;\n el.currentTime = Math.min(Math.max(0, time), duration);\n },\n goToLive() {\n const el = ensureVideoElement();\n return seekToLiveEdge(el);\n },\n isLive() {\n return isLiveStream;\n },\n isAtLiveEdge() {\n if (!isLiveStream || !videoEl) {\n return true;\n }\n return isAtLiveEdge(videoEl);\n },\n getCurrentTime() {\n return videoEl?.currentTime ?? 0;\n },\n getDuration() {\n return videoEl?.duration ?? 0;\n },\n setVolume(volume: number) {\n const el = ensureVideoElement();\n el.volume = Math.min(1, Math.max(0, volume));\n events.emit(\"volumechange\", { volume: el.volume, muted: el.muted });\n },\n getVolume() {\n return videoEl?.volume ?? 0;\n },\n mute() {\n const el = ensureVideoElement();\n el.muted = true;\n events.emit(\"volumechange\", { volume: el.volume, muted: true });\n },\n unmute() {\n const el = ensureVideoElement();\n el.muted = false;\n events.emit(\"volumechange\", { volume: el.volume, muted: false });\n },\n isMuted() {\n return videoEl?.muted ?? false;\n },\n setPlaybackRate(rate: number) {\n ensureVideoElement().playbackRate = rate;\n },\n getPlaybackRate() {\n return videoEl?.playbackRate ?? 1;\n },\n getState() {\n return state;\n },\n getBufferedRanges() {\n const el = videoEl;\n if (!el) return [];\n const ranges: BufferedRange[] = [];\n for (let i = 0; i < el.buffered.length; i += 1) {\n ranges.push({ start: el.buffered.start(i), end: el.buffered.end(i) });\n }\n return ranges;\n },\n getQuality() {\n return engine?.getQuality() ?? \"auto\";\n },\n setQuality(selection: QualitySelection | string) {\n if (selection === \"auto\") {\n engine?.setQuality(\"auto\");\n return;\n }\n if (typeof selection === \"number\") {\n engine?.setQuality(selection);\n return;\n }\n const match = engine\n ?.getQualities()\n .find((q) => q.label === selection || `${q.height}p` === selection);\n if (match) engine?.setQuality(match.index);\n },\n getAvailableQualities() {\n return engine?.getQualities() ?? [];\n },\n async enterFullscreen() {\n const target = fullscreenEl ?? videoEl?.parentElement ?? videoEl;\n if (target && \"requestFullscreen\" in target) {\n await target.requestFullscreen();\n events.emit(\"fullscreenchange\", { isFullscreen: true });\n }\n },\n async exitFullscreen() {\n if (document.fullscreenElement) {\n await document.exitFullscreen();\n events.emit(\"fullscreenchange\", { isFullscreen: false });\n }\n },\n isFullscreen() {\n return Boolean(document.fullscreenElement);\n },\n async reload() {\n refreshManager?.stop();\n engine?.destroy();\n await startPlayback();\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n refreshManager?.stop();\n refreshManager = null;\n engine?.destroy();\n engine = null;\n authManager.destroy();\n sourceManager.destroy();\n setState(\"destroyed\");\n events.emit(\"destroy\");\n events.removeAll();\n options.analytics?.onEvent?.({ type: \"PLAYER_DESTROYED\" });\n },\n getDiagnostics() {\n const buffered = api.getBufferedRanges();\n return {\n playerVersion: PACKAGE_VERSION,\n currentState: state,\n hlsSupport: engine?.getSupportMode() ?? \"unsupported\",\n videoId: options.videoId ?? null,\n currentTime: api.getCurrentTime(),\n duration: api.getDuration(),\n bufferedEnd: buffered.length ? buffered[buffered.length - 1]!.end : 0,\n currentQuality:\n api.getQuality() === \"auto\"\n ? \"auto\"\n : engine?.getQualities().find((q) => q.index === api.getQuality())\n ?.label ?? null,\n playbackSessionId,\n authExpiryStatus: expiryStatus(\n authManager.getExpiresAt(),\n options.auth?.refreshBeforeExpiryMs ?? 60_000,\n ),\n sourceExpiryStatus: expiryStatus(\n sourceManager.getExpiresAt(),\n options.playback?.refreshBeforeExpiryMs ?? 30_000,\n ),\n lastError: lastError?.message ?? null,\n };\n },\n getConfig() {\n return config;\n },\n updateConfig(partial) {\n config = mergePlayerConfig({\n player: { ...config.player, ...partial?.player },\n controls: { ...config.controls, ...partial?.controls },\n theme: { ...config.theme, ...partial?.theme },\n watermark: { ...config.watermark, ...partial?.watermark },\n streaming: {\n engine: \"hls\",\n hls: { ...config.streaming.hls, ...partial?.streaming?.hls },\n keyProxyUrlBuilder:\n partial?.streaming?.keyProxyUrlBuilder ??\n config.streaming.keyProxyUrlBuilder,\n getKeyAccessToken:\n partial?.streaming?.getKeyAccessToken ??\n config.streaming.getKeyAccessToken,\n },\n logging: { ...config.logging, ...partial?.logging },\n debug: { ...config.debug, ...partial?.debug },\n accessibility: {\n ...config.accessibility,\n ...partial?.accessibility,\n },\n });\n logger.update(config.logging);\n },\n on: events.on.bind(events),\n off: events.off.bind(events),\n };\n\n // Allow attaching mount after create\n (api as VideoPlayer & { attach: (el: HTMLVideoElement, container?: HTMLElement) => Promise<void> }).attach =\n async (el: HTMLVideoElement, container?: HTMLElement) => {\n videoEl = el;\n fullscreenEl = container ?? null;\n await startPlayback();\n };\n\n return api;\n}\n\nexport type { CreateVideoPlayerOptions };\n"],"mappings":"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","names":["PlayerErrorCode","isPlainObject","BuiltinXhrLoader","el"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors/PlayerError.ts","../src/auth/AuthManager.ts","../src/config/defaults.ts","../src/events/EventEmitter.ts","../src/security/redaction.ts","../src/logging/Logger.ts","../src/auth/AuthParamsStore.ts","../src/playback/PlaybackSourceManager.ts","../src/playback/RefreshManager.ts","../src/playback/liveEdge.ts","../src/streaming/authParamsLoader.ts","../src/streaming/HlsEngine.ts","../src/player/createVideoPlayer.ts"],"sourcesContent":["export { createVideoPlayer, type VideoPlayer } from \"./player/createVideoPlayer\";\nexport {\n DEFAULT_PLAYER_CONFIG,\n DEFAULT_PLAYER_BEHAVIOR,\n DEFAULT_CONTROLS,\n DEFAULT_THEME,\n DEFAULT_WATERMARK,\n PLAYBACK_RATES,\n PACKAGE_VERSION,\n mergePlayerConfig,\n themeToCssVars,\n assertNoSecretsInConfig,\n isPlainObject,\n SECRET_SCAN_MAX_DEPTH,\n} from \"./config/defaults\";\nexport {\n PlayerErrorCode,\n createPlayerError,\n redactSensitive,\n type PlayerError,\n} from \"./errors/PlayerError\";\nexport { AuthParamsStore } from \"./auth/AuthParamsStore\";\nexport { AuthManager } from \"./auth/AuthManager\";\nexport { PlaybackSourceManager } from \"./playback/PlaybackSourceManager\";\nexport { RefreshManager } from \"./playback/RefreshManager\";\nexport {\n rewriteHlsRequestUrl,\n createAuthParamsLoader,\n resolveBuiltinHlsLoader,\n isEncryptionKeyUrl,\n} from \"./streaming/authParamsLoader\";\nexport {\n DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS,\n getLiveEdgeTime,\n isAtLiveEdge,\n seekToLiveEdge,\n type LiveMediaSnapshot,\n type SeekToLiveResult,\n} from \"./playback/liveEdge\";\nexport { EventEmitter } from \"./events/EventEmitter\";\nexport { redactObject, redactValue } from \"./security/redaction\";\nexport type * from \"./types\";\n","export enum PlayerErrorCode {\n INVALID_CONFIGURATION = \"INVALID_CONFIGURATION\",\n AUTHENTICATION_FAILED = \"AUTHENTICATION_FAILED\",\n AUTH_TOKEN_REFRESH_FAILED = \"AUTH_TOKEN_REFRESH_FAILED\",\n TOKEN_EXPIRED = \"TOKEN_EXPIRED\",\n TOKEN_REFRESH_FAILED = \"TOKEN_REFRESH_FAILED\",\n SOURCE_RESOLUTION_FAILED = \"SOURCE_RESOLUTION_FAILED\",\n MANIFEST_LOAD_FAILED = \"MANIFEST_LOAD_FAILED\",\n SEGMENT_LOAD_FAILED = \"SEGMENT_LOAD_FAILED\",\n NETWORK_ERROR = \"NETWORK_ERROR\",\n PLAYBACK_ERROR = \"PLAYBACK_ERROR\",\n UNSUPPORTED_BROWSER = \"UNSUPPORTED_BROWSER\",\n AUTOPLAY_BLOCKED = \"AUTOPLAY_BLOCKED\",\n UNKNOWN = \"UNKNOWN\",\n}\n\nexport type PlayerError = {\n code: PlayerErrorCode;\n message: string;\n category: \"config\" | \"auth\" | \"network\" | \"playback\" | \"unknown\";\n fatal: boolean;\n retryable: boolean;\n timestamp: number;\n cause?: unknown;\n};\n\nexport function createPlayerError(\n code: PlayerErrorCode,\n message: string,\n options?: Partial<Omit<PlayerError, \"code\" | \"message\" | \"timestamp\">>,\n): PlayerError {\n return {\n code,\n message: redactSensitive(message),\n category: options?.category ?? \"unknown\",\n fatal: options?.fatal ?? true,\n retryable: options?.retryable ?? false,\n timestamp: Date.now(),\n cause: options?.cause,\n };\n}\n\nexport function redactSensitive(input: string): string {\n return input\n .replace(/(Bearer\\s+)[^\\s]+/gi, \"$1[REDACTED]\")\n .replace(/([?&](token|expires|signature|sig)=)[^&]+/gi, \"$1[REDACTED]\")\n .replace(/(Authorization:\\s*)[^\\s]+/gi, \"$1[REDACTED]\");\n}\n","import {\n createPlayerError,\n PlayerErrorCode,\n} from \"../errors/PlayerError\";\nimport type { Logger } from \"../logging/Logger\";\nimport type {\n AuthConfig,\n AuthToken,\n AuthTokenProviderContext,\n} from \"../types\";\n\n/**\n * Manages provider auth-token lifecycle (independent from signed playback URL).\n * Single-flight refresh; never stores clientSecret.\n * Unauthorized recoveries are bounded to prevent infinite 401 → refresh loops.\n */\nexport class AuthManager {\n private token: AuthToken | null = null;\n private inFlight: Promise<AuthToken> | null = null;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private destroyed = false;\n /** Consecutive unauthorized refresh attempts (reset on success). */\n private unauthorizedAttempts = 0;\n private readonly maxUnauthorizedRetries: number;\n\n constructor(\n private readonly auth: AuthConfig | undefined,\n private readonly refreshBeforeExpiryMs: number,\n private readonly logger: Logger,\n private readonly onRefreshed?: (token: AuthToken) => void,\n private readonly onError?: (message: string, retryable: boolean) => void,\n maxUnauthorizedRetries = 1,\n ) {\n this.maxUnauthorizedRetries = Math.max(0, maxUnauthorizedRetries);\n }\n\n getAccessToken(): string | null {\n return this.token?.accessToken ?? null;\n }\n\n getExpiresAt(): number | null {\n return this.token?.expiresAt ?? null;\n }\n\n async ensureToken(\n context: AuthTokenProviderContext,\n ): Promise<AuthToken | null> {\n if (!this.auth?.getToken) return null;\n if (this.destroyed) return null;\n\n if (\n this.token &&\n context.reason !== \"unauthorized\" &&\n context.reason !== \"manual\" &&\n this.token.expiresAt - Date.now() > this.refreshBeforeExpiryMs\n ) {\n return this.token;\n }\n\n return this.refresh(context);\n }\n\n async refresh(context: AuthTokenProviderContext): Promise<AuthToken> {\n if (!this.auth?.getToken) {\n throw createPlayerError(\n PlayerErrorCode.INVALID_CONFIGURATION,\n \"auth.getToken is required for authenticated playback\",\n { category: \"config\", fatal: true, retryable: false },\n );\n }\n\n if (context.reason === \"unauthorized\") {\n if (this.unauthorizedAttempts >= this.maxUnauthorizedRetries) {\n const message =\n \"Auth token refresh aborted: exceeded bounded unauthorized retry limit\";\n this.onError?.(message, false);\n throw createPlayerError(\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED,\n message,\n { category: \"auth\", fatal: true, retryable: false },\n );\n }\n this.unauthorizedAttempts += 1;\n }\n\n if (this.inFlight) return this.inFlight;\n\n this.inFlight = (async () => {\n try {\n const next = await this.auth!.getToken(context);\n if (\n !next?.accessToken ||\n typeof next.expiresAt !== \"number\" ||\n next.expiresAt <= 0\n ) {\n throw createPlayerError(\n PlayerErrorCode.AUTHENTICATION_FAILED,\n \"auth.getToken returned an invalid token payload\",\n { category: \"auth\", fatal: true, retryable: true },\n );\n }\n this.token = next;\n if (context.reason !== \"unauthorized\") {\n this.unauthorizedAttempts = 0;\n }\n this.scheduleProactiveRefresh();\n this.onRefreshed?.(next);\n this.logger.debug(\"Auth token refreshed\", {\n reason: context.reason,\n expiresAt: next.expiresAt,\n });\n return next;\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n (error as { code: string }).code ===\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED\n ) {\n throw error;\n }\n const message =\n error instanceof Error ? error.message : \"Auth token refresh failed\";\n const retryable = this.unauthorizedAttempts <= this.maxUnauthorizedRetries;\n this.onError?.(message, retryable);\n throw createPlayerError(\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED,\n message,\n { category: \"auth\", fatal: !retryable, retryable, cause: error },\n );\n } finally {\n this.inFlight = null;\n }\n })();\n\n return this.inFlight;\n }\n\n private scheduleProactiveRefresh(): void {\n if (this.timer) clearTimeout(this.timer);\n if (!this.token || this.destroyed) return;\n const delay = Math.max(\n 5_000,\n this.token.expiresAt - Date.now() - this.refreshBeforeExpiryMs,\n );\n this.timer = setTimeout(() => {\n void this.refresh({\n reason: \"expiring\",\n videoId: undefined,\n }).catch(() => {\n /* onError already notified */\n });\n }, delay);\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n this.token = null;\n this.inFlight = null;\n }\n}\n","import type {\n ControlsConfig,\n PlayerBehaviorConfig,\n PlayerConfig,\n ThemeConfig,\n WatermarkConfig,\n} from \"../types\";\n\nexport const PLAYBACK_RATES = [0.5, 0.75, 1, 1.25, 1.5, 2] as const;\n\nexport const PACKAGE_VERSION = \"0.1.8\";\n\nexport const DEFAULT_PLAYER_BEHAVIOR: Required<PlayerBehaviorConfig> = {\n autoplay: true,\n startMuted: true,\n volume: 1,\n startPosition: 0,\n skipSeconds: 10,\n speedOptionCount: PLAYBACK_RATES.length,\n zoomEnabled: true,\n defaultZoom: 1,\n playbackRates: PLAYBACK_RATES,\n};\n\nexport const DEFAULT_CONTROLS: Required<ControlsConfig> = {\n enabled: true,\n showQuality: true,\n showSpeed: true,\n showCaptions: true,\n showAudio: true,\n showVolume: true,\n showFullscreen: true,\n showZoom: true,\n showSkip: true,\n showLive: true,\n seekCueDurationMs: 720,\n keyboardShortcuts: true,\n};\n\nexport const DEFAULT_THEME: Required<ThemeConfig> = {\n playIconPreset: \"triangle\",\n playButtonBackground: \"#ffffff\",\n playButtonIconColor: \"#ffffff\",\n seekTrackColor: \"#334155\",\n seekProgressColor: \"#38bdf8\",\n seekBufferedColor: \"#64748b\",\n timeColor: \"#e2e8f0\",\n controlIconColor: \"#f1f5f9\",\n focusRingColor: \"#38bdf8\",\n spinnerColor: \"#38bdf8\",\n volumeIconColor: \"#f1f5f9\",\n volumeTrackColor: \"#334155\",\n volumeProgressColor: \"#38bdf8\",\n qualityOptionTextColor: \"#e2e8f0\",\n qualityOptionBackground: \"#020617\",\n qualityOptionActiveBackground: \"#0c4a6e\",\n qualityOptionActiveTextColor: \"#bae6fd\",\n speedOptionTextColor: \"#e2e8f0\",\n speedOptionBackground: \"#020617\",\n speedOptionActiveBackground: \"#0c4a6e\",\n speedOptionActiveTextColor: \"#bae6fd\",\n zoomIconColor: \"#f1f5f9\",\n skipIconColor: \"#f1f5f9\",\n skipCueBackground: \"#ffffff\",\n skipCueTextColor: \"#ffffff\",\n liveDotColor: \"#ef4444\",\n};\n\nexport const DEFAULT_WATERMARK: Required<WatermarkConfig> = {\n enabled: true,\n text: \"\",\n durationMs: 10_000,\n intervalMaxMs: 300_000,\n};\n\nexport const DEFAULT_PLAYER_CONFIG: PlayerConfig = {\n player: DEFAULT_PLAYER_BEHAVIOR,\n controls: DEFAULT_CONTROLS,\n theme: DEFAULT_THEME,\n watermark: DEFAULT_WATERMARK,\n streaming: {\n engine: \"hls\",\n hls: {\n enableWorker: true,\n lowLatencyMode: true,\n backBufferLength: 90,\n fatalRecoveryLimit: 3,\n },\n },\n logging: { enabled: false, level: \"error\" },\n debug: { enabled: false, network: false, events: false, state: false },\n accessibility: { reducedMotion: false },\n};\n\nconst FORBIDDEN_SECRET_KEYS = [\n \"clientsecret\",\n \"apisecret\",\n \"privatekey\",\n \"video_api_secret\",\n \"basicauthpassword\",\n \"password\",\n] as const;\n\n/** Never descend into these — DOM hosts or credential callback bags. */\nconst SKIP_DEEP_SCAN_KEYS = new Set([\n \"mount\",\n \"auth\",\n \"playback\",\n \"gettoken\",\n \"getsource\",\n \"refreshsource\",\n \"keyproxyurlbuilder\",\n \"getkeyaccesstoken\",\n]);\n\n/** Hard cap so pathological graphs cannot blow the stack. */\nexport const SECRET_SCAN_MAX_DEPTH = 32;\n\n/**\n * True only for JSON-like plain objects (`{}` / `Object.create(null)`).\n * Excludes DOM nodes, class instances, arrays, dates, etc.\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n if (Array.isArray(value)) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction normalizeConfigKey(key: string): string {\n return key.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n}\n\nfunction isForbiddenSecretKey(key: string): boolean {\n const lower = normalizeConfigKey(key);\n return FORBIDDEN_SECRET_KEYS.some((k) => lower.includes(k));\n}\n\nfunction throwForbidden(path: string, key: string): never {\n throw new Error(\n `INVALID_CONFIGURATION: Forbidden secret key \"${path}${key}\" must never be passed to the browser SDK. Keep clientSecret on your server/BFF and use auth.getToken().`,\n );\n}\n\n/**\n * Scans plain config objects for forbidden secret key names.\n *\n * Enterprise guarantees:\n * - Never deep-walks DOM / host / class instances (plain-object only)\n * - Does not descend into `mount` / `auth` / `playback` (shallow key check only)\n * - Cycle-safe via WeakSet\n * - Depth-capped + iterative (no call-stack recursion)\n */\nexport function assertNoSecretsInConfig(raw: unknown): void {\n if (!isPlainObject(raw) && !Array.isArray(raw)) return;\n\n const seen = new WeakSet<object>();\n const stack: Array<{ value: unknown; path: string; depth: number }> = [\n { value: raw, path: \"\", depth: 0 },\n ];\n\n while (stack.length > 0) {\n const current = stack.pop()!;\n if (current.depth > SECRET_SCAN_MAX_DEPTH) continue;\n\n const { value, path, depth } = current;\n\n if (Array.isArray(value)) {\n if (seen.has(value)) continue;\n seen.add(value);\n for (let i = 0; i < value.length; i += 1) {\n const item = value[i];\n if (isPlainObject(item) || Array.isArray(item)) {\n stack.push({ value: item, path: `${path}[${i}]`, depth: depth + 1 });\n }\n }\n continue;\n }\n\n if (!isPlainObject(value)) continue;\n if (seen.has(value)) continue;\n seen.add(value);\n\n for (const [key, child] of Object.entries(value)) {\n const normalized = normalizeConfigKey(key);\n\n if (isForbiddenSecretKey(key)) {\n throwForbidden(path, key);\n }\n\n // mount: host node — never inspect further\n if (normalized === \"mount\") continue;\n\n // auth / playback / callback fields: shallow secret-key check only\n if (SKIP_DEEP_SCAN_KEYS.has(normalized)) {\n if (isPlainObject(child)) {\n for (const nestedKey of Object.keys(child)) {\n if (isForbiddenSecretKey(nestedKey)) {\n throwForbidden(`${path}${key}.`, nestedKey);\n }\n }\n }\n continue;\n }\n\n if (isPlainObject(child) || Array.isArray(child)) {\n stack.push({\n value: child,\n path: path ? `${path}${key}.` : `${key}.`,\n depth: depth + 1,\n });\n }\n }\n }\n}\n\nexport type PlayerConfigPartial = Partial<{\n player: Partial<PlayerBehaviorConfig>;\n controls: Partial<ControlsConfig>;\n theme: Partial<ThemeConfig>;\n watermark: Partial<WatermarkConfig>;\n streaming: {\n engine?: \"hls\";\n hls?: Partial<PlayerConfig[\"streaming\"][\"hls\"]>;\n keyProxyUrlBuilder?: PlayerConfig[\"streaming\"][\"keyProxyUrlBuilder\"];\n getKeyAccessToken?: PlayerConfig[\"streaming\"][\"getKeyAccessToken\"];\n };\n logging: Partial<PlayerConfig[\"logging\"]>;\n debug: Partial<PlayerConfig[\"debug\"]>;\n accessibility: Partial<PlayerConfig[\"accessibility\"]>;\n}>;\n\nexport function mergePlayerConfig(partial?: PlayerConfigPartial): PlayerConfig {\n assertNoSecretsInConfig(partial);\n return {\n player: { ...DEFAULT_PLAYER_BEHAVIOR, ...partial?.player },\n controls: { ...DEFAULT_CONTROLS, ...partial?.controls },\n theme: { ...DEFAULT_THEME, ...partial?.theme },\n watermark: { ...DEFAULT_WATERMARK, ...partial?.watermark },\n streaming: {\n engine: \"hls\",\n hls: {\n ...DEFAULT_PLAYER_CONFIG.streaming.hls,\n ...partial?.streaming?.hls,\n },\n keyProxyUrlBuilder: partial?.streaming?.keyProxyUrlBuilder,\n getKeyAccessToken: partial?.streaming?.getKeyAccessToken,\n },\n logging: { ...DEFAULT_PLAYER_CONFIG.logging, ...partial?.logging },\n debug: { ...DEFAULT_PLAYER_CONFIG.debug, ...partial?.debug },\n accessibility: {\n ...DEFAULT_PLAYER_CONFIG.accessibility,\n ...partial?.accessibility,\n },\n };\n}\n\n/** Maps theme colors to CSS custom properties for UI adapters. */\nexport function themeToCssVars(\n theme: Required<ThemeConfig>,\n): Record<string, string> {\n return {\n \"--player-play-btn-bg\": theme.playButtonBackground,\n \"--player-play-btn-icon\": theme.playButtonIconColor,\n \"--player-seek-track\": theme.seekTrackColor,\n \"--player-seek-progress\": theme.seekProgressColor,\n \"--player-seek-buffered\": theme.seekBufferedColor,\n \"--player-time\": theme.timeColor,\n \"--player-control-icon\": theme.controlIconColor,\n \"--player-focus-ring\": theme.focusRingColor,\n \"--player-spinner\": theme.spinnerColor,\n \"--player-volume-icon\": theme.volumeIconColor,\n \"--player-volume-track\": theme.volumeTrackColor,\n \"--player-volume-progress\": theme.volumeProgressColor,\n \"--player-quality-text\": theme.qualityOptionTextColor,\n \"--player-quality-bg\": theme.qualityOptionBackground,\n \"--player-quality-active-bg\": theme.qualityOptionActiveBackground,\n \"--player-quality-active-text\": theme.qualityOptionActiveTextColor,\n \"--player-speed-text\": theme.speedOptionTextColor,\n \"--player-speed-bg\": theme.speedOptionBackground,\n \"--player-speed-active-bg\": theme.speedOptionActiveBackground,\n \"--player-speed-active-text\": theme.speedOptionActiveTextColor,\n \"--player-zoom-icon\": theme.zoomIconColor,\n \"--player-skip-icon\": theme.skipIconColor,\n \"--player-skip-cue-bg\": theme.skipCueBackground,\n \"--player-skip-cue-text\": theme.skipCueTextColor,\n \"--player-live-dot\": theme.liveDotColor,\n };\n}\n","import type { PlayerEventMap } from \"../types\";\n\ntype Handler<T> = T extends void ? () => void : (payload: T) => void;\n\nexport class EventEmitter {\n private listeners = new Map<keyof PlayerEventMap, Set<Function>>();\n\n on<K extends keyof PlayerEventMap>(\n event: K,\n handler: Handler<PlayerEventMap[K]>,\n ): () => void {\n let set = this.listeners.get(event);\n if (!set) {\n set = new Set();\n this.listeners.set(event, set);\n }\n set.add(handler);\n return () => this.off(event, handler);\n }\n\n off<K extends keyof PlayerEventMap>(\n event: K,\n handler: Handler<PlayerEventMap[K]>,\n ): void {\n this.listeners.get(event)?.delete(handler);\n }\n\n emit<K extends keyof PlayerEventMap>(\n event: K,\n ...args: PlayerEventMap[K] extends void ? [] : [PlayerEventMap[K]]\n ): void {\n const set = this.listeners.get(event);\n if (!set) return;\n for (const handler of set) {\n try {\n (handler as Function)(...args);\n } catch {\n // never let listener failures break the player\n }\n }\n }\n\n removeAll(): void {\n this.listeners.clear();\n }\n}\n","const SENSITIVE_KEYS =\n /^(authorization|cookie|set-cookie|x-api-key|token|accessToken|access_token|clientSecret|password)$/i;\n\nconst REDACT_MAX_DEPTH = 32;\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") return false;\n if (Array.isArray(value)) return false;\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nfunction redactStringUrl(value: string): string {\n if (!/^https?:\\/\\//i.test(value) || !/[?&](token|expires)=/i.test(value)) {\n return value;\n }\n try {\n const url = new URL(value);\n for (const param of [\"token\", \"expires\", \"signature\", \"sig\"]) {\n if (url.searchParams.has(param)) {\n url.searchParams.set(param, \"[REDACTED]\");\n }\n }\n return url.toString();\n } catch {\n return \"[REDACTED_URL]\";\n }\n}\n\nexport function redactValue(\n key: string,\n value: unknown,\n seen: WeakSet<object> = new WeakSet(),\n depth = 0,\n): unknown {\n if (SENSITIVE_KEYS.test(key)) return \"[REDACTED]\";\n if (typeof value === \"string\") return redactStringUrl(value);\n if (Array.isArray(value)) {\n if (depth >= REDACT_MAX_DEPTH || seen.has(value)) return \"[REDACTED_CYCLE]\";\n seen.add(value);\n return value.map((item, index) =>\n redactValue(String(index), item, seen, depth + 1),\n );\n }\n if (isPlainObject(value)) {\n return redactObject(value, seen, depth + 1);\n }\n return value;\n}\n\n/**\n * Redacts sensitive fields. Cycle-safe and depth-capped.\n * Only walks plain objects/arrays — never DOM / host graphs.\n */\nexport function redactObject(\n obj: Record<string, unknown>,\n seen: WeakSet<object> = new WeakSet(),\n depth = 0,\n): Record<string, unknown> {\n if (depth > REDACT_MAX_DEPTH) return { \"[REDACTED]\": \"max_depth\" };\n if (seen.has(obj)) return { \"[REDACTED]\": \"cycle\" };\n seen.add(obj);\n\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n out[key] = redactValue(key, value, seen, depth);\n }\n return out;\n}\n","import { redactObject } from \"../security/redaction\";\nimport type { LoggingConfig } from \"../types\";\n\nconst LEVELS = [\"silent\", \"error\", \"warn\", \"info\", \"debug\", \"trace\"] as const;\n\nexport class Logger {\n constructor(private config: Required<LoggingConfig>) {}\n\n update(config: Partial<LoggingConfig>): void {\n this.config = { ...this.config, ...config } as Required<LoggingConfig>;\n }\n\n private shouldLog(level: (typeof LEVELS)[number]): boolean {\n if (!this.config.enabled || this.config.level === \"silent\") return false;\n return LEVELS.indexOf(level) <= LEVELS.indexOf(this.config.level);\n }\n\n private write(\n level: \"error\" | \"warn\" | \"info\" | \"debug\",\n message: string,\n details?: Record<string, unknown>,\n ): void {\n if (!this.shouldLog(level)) return;\n const payload = details ? redactObject(details) : undefined;\n const fn = console[level] ?? console.log;\n if (payload) fn(`[nsg-player] ${message}`, payload);\n else fn(`[nsg-player] ${message}`);\n }\n\n error(message: string, details?: Record<string, unknown>): void {\n this.write(\"error\", message, details);\n }\n\n warn(message: string, details?: Record<string, unknown>): void {\n this.write(\"warn\", message, details);\n }\n\n info(message: string, details?: Record<string, unknown>): void {\n this.write(\"info\", message, details);\n }\n\n debug(message: string, details?: Record<string, unknown>): void {\n this.write(\"debug\", message, details);\n }\n}\n","/**\n * Mutable store of the latest playback authorization query parameters.\n * Updated on renewal without recreating the HLS player.\n */\nexport class AuthParamsStore {\n private params: URLSearchParams;\n\n constructor(initial?: URLSearchParams | Record<string, string>) {\n if (initial instanceof URLSearchParams) {\n this.params = new URLSearchParams(initial);\n } else if (initial) {\n this.params = new URLSearchParams(initial);\n } else {\n this.params = new URLSearchParams();\n }\n }\n\n getSnapshot(): URLSearchParams {\n return new URLSearchParams(this.params);\n }\n\n toRecord(): Record<string, string> {\n const out: Record<string, string> = {};\n this.params.forEach((value, key) => {\n out[key] = value;\n });\n return out;\n }\n\n /** True when at least one auth query param is stored. */\n hasParams(): boolean {\n return [...this.params.keys()].length > 0;\n }\n\n toString(): string {\n return this.params.toString();\n }\n\n update(next: URLSearchParams | Record<string, string>): void {\n this.params =\n next instanceof URLSearchParams\n ? new URLSearchParams(next)\n : new URLSearchParams(next);\n }\n\n /**\n * Merges current auth params onto a target URL, preserving unrelated query keys.\n * Critical for child HLS playlists/segments that omit signed query params.\n */\n applyToUrl(rawUrl: string, baseOrigin?: string): string {\n const target = new URL(\n rawUrl,\n baseOrigin ??\n (typeof location !== \"undefined\" ? location.origin : \"http://localhost\"),\n );\n this.params.forEach((value, key) => {\n target.searchParams.set(key, value);\n });\n return target.toString();\n }\n}\n","import {\n createPlayerError,\n PlayerErrorCode,\n} from \"../errors/PlayerError\";\nimport type { Logger } from \"../logging/Logger\";\nimport type {\n PlaybackCredentialConfig,\n PlaybackSource,\n PlaybackSourceContext,\n} from \"../types\";\nimport { AuthParamsStore } from \"../auth/AuthParamsStore\";\n\n/**\n * Resolves and refreshes signed playback sources via consumer callbacks.\n */\nexport class PlaybackSourceManager {\n private source: PlaybackSource | null = null;\n private inFlight: Promise<PlaybackSource> | null = null;\n readonly authParams = new AuthParamsStore();\n\n constructor(\n private readonly playback: PlaybackCredentialConfig | undefined,\n private readonly logger: Logger,\n ) {}\n\n getSource(): PlaybackSource | null {\n return this.source;\n }\n\n getExpiresAt(): number | null {\n return this.source?.expiresAt ?? null;\n }\n\n async load(\n context: PlaybackSourceContext,\n ): Promise<PlaybackSource> {\n if (!this.playback?.getSource) {\n throw createPlayerError(\n PlayerErrorCode.INVALID_CONFIGURATION,\n \"playback.getSource is required when not using sourceUrl\",\n { category: \"config\", fatal: true, retryable: false },\n );\n }\n return this.run(context, () => this.playback!.getSource(context));\n }\n\n async refresh(\n context: PlaybackSourceContext,\n ): Promise<PlaybackSource> {\n const refresher =\n this.playback?.refreshSource ?? this.playback?.getSource;\n if (!refresher) {\n throw createPlayerError(\n PlayerErrorCode.INVALID_CONFIGURATION,\n \"playback.refreshSource or playback.getSource is required\",\n { category: \"config\", fatal: true, retryable: false },\n );\n }\n return this.run(context, () => refresher(context));\n }\n\n applyDirectSource(source: PlaybackSource): void {\n this.source = source;\n this.applyAuthParams(source);\n }\n\n private async run(\n context: PlaybackSourceContext,\n fn: () => Promise<PlaybackSource>,\n ): Promise<PlaybackSource> {\n if (this.inFlight) return this.inFlight;\n\n this.inFlight = (async () => {\n try {\n const next = await fn();\n if (!next?.url || typeof next.expiresAt !== \"number\") {\n throw createPlayerError(\n PlayerErrorCode.SOURCE_RESOLUTION_FAILED,\n \"Playback source callback returned an invalid payload\",\n { category: \"playback\", fatal: true, retryable: true },\n );\n }\n this.source = next;\n this.applyAuthParams(next);\n this.logger.debug(\"Playback source resolved\", {\n reason: context.reason,\n expiresAt: next.expiresAt,\n });\n return next;\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error) throw error;\n throw createPlayerError(\n PlayerErrorCode.SOURCE_RESOLUTION_FAILED,\n error instanceof Error ? error.message : \"Source resolution failed\",\n { category: \"playback\", fatal: true, retryable: true, cause: error },\n );\n } finally {\n this.inFlight = null;\n }\n })();\n\n return this.inFlight;\n }\n\n private applyAuthParams(source: PlaybackSource): void {\n if (source.authParams) {\n this.authParams.update(source.authParams);\n return;\n }\n try {\n const url = new URL(source.url);\n const params: Record<string, string> = {};\n url.searchParams.forEach((value, key) => {\n params[key] = value;\n });\n if (source.token) params.token = source.token;\n this.authParams.update(params);\n } catch {\n if (source.token) {\n this.authParams.update({ token: source.token });\n }\n }\n }\n\n destroy(): void {\n this.source = null;\n this.inFlight = null;\n }\n}\n","import type { AuthManager } from \"../auth/AuthManager\";\nimport type { Logger } from \"../logging/Logger\";\nimport type { PlaybackSourceManager } from \"./PlaybackSourceManager\";\n\nexport type RefreshReason =\n | \"proactive\"\n | \"frag_error\"\n | \"level_error\"\n | \"key_error\"\n | \"fatal_network\"\n | \"manual\";\n\nexport type RefreshManagerOptions = {\n videoId: string;\n authManager: AuthManager;\n sourceManager: PlaybackSourceManager;\n refreshBeforeExpiryMs: number;\n renewMaxRetries: number;\n renewBackoffMs: number;\n coalesceMs: number;\n logger: Logger;\n isDestroyed: () => boolean;\n onRenewing?: () => void;\n onRenewed?: (expiresAt: number) => void;\n onFatal?: (message: string) => void;\n};\n\n/**\n * Schedules signed-URL renewal (playback clock) with single-flight + coalesce.\n * Ensures auth token is fresh before calling refreshSource.\n */\nexport class RefreshManager {\n private timer: ReturnType<typeof setTimeout> | null = null;\n private coalesceTimer: ReturnType<typeof setTimeout> | null = null;\n private inFlight = false;\n private consecutiveFailures = 0;\n private stopped = false;\n private pendingReason: RefreshReason | null = null;\n\n constructor(private readonly options: RefreshManagerOptions) {}\n\n start(initialExpiresAt: number): void {\n this.schedule(initialExpiresAt);\n }\n\n requestRenew(reason: RefreshReason = \"frag_error\"): void {\n if (this.stopped || this.options.isDestroyed()) return;\n this.pendingReason = reason;\n if (this.coalesceTimer) return;\n this.coalesceTimer = setTimeout(() => {\n this.coalesceTimer = null;\n const reasonToUse = this.pendingReason ?? \"frag_error\";\n this.pendingReason = null;\n void this.renew(reasonToUse);\n }, this.options.coalesceMs);\n }\n\n stop(): void {\n this.stopped = true;\n if (this.timer) clearTimeout(this.timer);\n if (this.coalesceTimer) clearTimeout(this.coalesceTimer);\n this.timer = null;\n this.coalesceTimer = null;\n }\n\n private schedule(expiresAt: number): void {\n if (this.timer) clearTimeout(this.timer);\n if (this.stopped) return;\n const delay = Math.max(\n 5_000,\n expiresAt - Date.now() - this.options.refreshBeforeExpiryMs,\n );\n this.timer = setTimeout(() => {\n void this.renew(\"proactive\");\n }, delay);\n }\n\n private async renew(reason: RefreshReason): Promise<void> {\n if (this.stopped || this.options.isDestroyed() || this.inFlight) {\n if (this.inFlight) this.pendingReason = reason;\n return;\n }\n this.inFlight = true;\n this.options.onRenewing?.();\n\n try {\n await this.options.authManager.ensureToken({\n reason: reason === \"proactive\" ? \"expiring\" : \"unauthorized\",\n videoId: this.options.videoId,\n });\n\n const source = await this.options.sourceManager.refresh({\n videoId: this.options.videoId,\n reason:\n reason === \"proactive\"\n ? \"expiring\"\n : reason === \"manual\"\n ? \"manual\"\n : \"auth_error\",\n });\n\n this.consecutiveFailures = 0;\n this.options.onRenewed?.(source.expiresAt);\n this.schedule(source.expiresAt);\n this.options.logger.debug(\"Playback source renewed\", { reason });\n } catch (error) {\n this.consecutiveFailures += 1;\n const message = refreshErrorMessage(error);\n this.options.logger.warn(\"Playback refresh failed\", {\n reason,\n failure: this.consecutiveFailures,\n message,\n });\n\n if (this.consecutiveFailures >= this.options.renewMaxRetries) {\n this.options.onFatal?.(message);\n } else {\n const backoff =\n this.options.renewBackoffMs * this.consecutiveFailures;\n this.timer = setTimeout(() => {\n void this.renew(reason);\n }, backoff);\n }\n } finally {\n this.inFlight = false;\n if (this.pendingReason && !this.stopped) {\n const pending = this.pendingReason;\n this.pendingReason = null;\n void this.renew(pending);\n }\n }\n }\n}\n\nfunction refreshErrorMessage(error: unknown): string {\n if (error instanceof Error && error.message) return error.message;\n if (\n error &&\n typeof error === \"object\" &&\n \"message\" in error &&\n typeof (error as { message: unknown }).message === \"string\" &&\n (error as { message: string }).message\n ) {\n return (error as { message: string }).message;\n }\n return \"Playback refresh failed\";\n}\n","/**\n * Live-edge helpers for HLS DVR / live streams.\n * Uses HTMLMediaElement.seekable when available; falls back to duration.\n */\n\nexport const DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS = 3;\n\nexport type SeekableLike = {\n length: number;\n start: (index: number) => number;\n end: (index: number) => number;\n};\n\nexport type LiveMediaSnapshot = {\n currentTime: number;\n duration: number;\n seekable: SeekableLike;\n};\n\n/**\n * Returns the latest seekable end (live edge), or null when unknown.\n */\nexport function getLiveEdgeTime(\n media: Pick<LiveMediaSnapshot, \"duration\" | \"seekable\">,\n): number | null {\n const { seekable, duration } = media;\n try {\n if (seekable.length > 0) {\n const end = seekable.end(seekable.length - 1);\n if (Number.isFinite(end) && end >= 0) {\n return end;\n }\n }\n } catch {\n // Some browsers throw while seekable is updating mid-load.\n }\n\n if (Number.isFinite(duration) && duration > 0) {\n return duration;\n }\n\n return null;\n}\n\n/**\n * True when playback is within `toleranceSeconds` of the live edge.\n */\nexport function isAtLiveEdge(\n media: LiveMediaSnapshot,\n toleranceSeconds: number = DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS,\n): boolean {\n const edge = getLiveEdgeTime(media);\n if (edge === null) {\n return true;\n }\n const lag = edge - media.currentTime;\n return lag <= Math.max(0, toleranceSeconds);\n}\n\nexport type SeekToLiveResult =\n | { moved: true; edge: number }\n | { moved: false; reason: \"already_at_live\" | \"edge_unavailable\"; edge: number | null };\n\nexport type SeekableMediaElement = {\n currentTime: number;\n duration: number;\n seekable: SeekableLike;\n};\n\n/**\n * Seeks to the live edge. Returns whether the playhead moved.\n */\nexport function seekToLiveEdge(\n media: SeekableMediaElement,\n options?: {\n toleranceSeconds?: number;\n /** Leave a tiny buffer behind the absolute end for decoder stability. */\n edgeOffsetSeconds?: number;\n },\n): SeekToLiveResult {\n const tolerance =\n options?.toleranceSeconds ?? DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS;\n const edgeOffset = options?.edgeOffsetSeconds ?? 0.25;\n const edge = getLiveEdgeTime(media);\n\n if (edge === null) {\n return { moved: false, reason: \"edge_unavailable\", edge: null };\n }\n\n if (isAtLiveEdge(media, tolerance)) {\n return { moved: false, reason: \"already_at_live\", edge };\n }\n\n const target = Math.max(0, edge - edgeOffset);\n media.currentTime = target;\n return { moved: true, edge };\n}\n","import type Hls from \"hls.js\";\nimport { XhrLoader as BuiltinXhrLoader } from \"hls.js\";\nimport type {\n LoaderCallbacks,\n LoaderConfiguration,\n LoaderContext,\n LoaderStats,\n} from \"hls.js\";\nimport type { AuthParamsStore } from \"../auth/AuthParamsStore\";\nimport type { StreamingConfig } from \"../types\";\n\ntype HlsLoaderInstance = {\n stats: LoaderStats;\n load(\n context: LoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<LoaderContext>,\n ): void;\n destroy(): void;\n abort?: () => void;\n};\n\ntype HlsLoader = new (config: object) => HlsLoaderInstance;\n\nconst ENC_KEY_PATH_RE = /enc\\.key$/i;\nconst BUILTIN_LOADER_NAMES = new Set([\"XhrLoader\", \"FetchLoader\"]);\n\nexport type AuthParamsLoaderOptions = {\n videoId?: string;\n keyProxyUrlBuilder?: StreamingConfig[\"keyProxyUrlBuilder\"];\n getKeyAccessToken?: StreamingConfig[\"getKeyAccessToken\"];\n};\n\nexport function isEncryptionKeyUrl(\n rawUrl: string,\n baseOrigin: string = typeof location !== \"undefined\"\n ? location.origin\n : \"http://localhost\",\n): boolean {\n try {\n return ENC_KEY_PATH_RE.test(new URL(rawUrl, baseOrigin).pathname);\n } catch {\n return /enc\\.key/i.test(rawUrl);\n }\n}\n\n/**\n * Always resolve a builtin hls.js loader (XhrLoader).\n *\n * Never trust `Hls.DefaultConfig.loader` alone — if it was reassigned to a\n * custom wrapper, `extends` / nested `inner.load()` chains blow Firefox's\n * stack (`InternalError: too much recursion`).\n */\nexport function resolveBuiltinHlsLoader(HlsClass: typeof Hls): HlsLoader {\n // Module export is immune to DefaultConfig pollution.\n if (typeof BuiltinXhrLoader === \"function\") {\n return BuiltinXhrLoader as unknown as HlsLoader;\n }\n\n const start = HlsClass.DefaultConfig.loader as HlsLoader;\n let current: HlsLoader | null = start;\n const seen = new Set<HlsLoader>();\n\n while (current && !seen.has(current)) {\n seen.add(current);\n const name = typeof current.name === \"string\" ? current.name : \"\";\n if (BUILTIN_LOADER_NAMES.has(name)) {\n return current;\n }\n const parentCtor = Object.getPrototypeOf(current.prototype)\n ?.constructor as HlsLoader | undefined;\n if (\n !parentCtor ||\n parentCtor === (Object as unknown as HlsLoader) ||\n parentCtor === (Function as unknown as HlsLoader)\n ) {\n break;\n }\n current = parentCtor;\n }\n\n return start;\n}\n\n/**\n * Rewrites an HLS request URL so signed auth query params are present.\n *\n * AES `enc.key` handling (enterprise priority order):\n * 1. `keyProxyUrlBuilder` — same-origin BFF (production; server IP must pass CDN/WAF)\n * 2. Otherwise keep CDN/API URL and apply signed `token`/`expires` (and related) query\n * params — same auth model as segments on Appextech CDN hosts\n * 3. Optional `getKeyAccessToken` is applied at load-time (Bearer), not in this rewrite\n */\nexport function rewriteHlsRequestUrl(\n rawUrl: string,\n store: AuthParamsStore,\n options: AuthParamsLoaderOptions = {},\n baseOrigin: string = typeof location !== \"undefined\"\n ? location.origin\n : \"http://localhost\",\n): string {\n if (!rawUrl) return rawUrl;\n\n const parsed = new URL(rawUrl, baseOrigin);\n const isKey = ENC_KEY_PATH_RE.test(parsed.pathname);\n\n if (isKey && options.keyProxyUrlBuilder && options.videoId) {\n const snapshot = store.toRecord();\n return options.keyProxyUrlBuilder({\n videoId: options.videoId,\n keyUrl: parsed.toString(),\n token: snapshot.token,\n expires: snapshot.expires,\n username: snapshot.username,\n mobile: snapshot.mobile,\n });\n }\n\n if (!store.hasParams()) return parsed.toString();\n return store.applyToUrl(rawUrl, baseOrigin);\n}\n\nfunction createLoaderStats(): LoaderStats {\n const now = performance.now();\n return {\n aborted: false,\n loaded: 0,\n retry: 0,\n total: 0,\n chunkCount: 0,\n bwEstimate: 0,\n loading: { start: now, first: 0, end: 0 },\n parsing: { start: 0, end: 0 },\n buffering: { start: 0, first: 0, end: 0 },\n };\n}\n\n/**\n * Browser-direct enc.key fetch with optional API Bearer + signed query URL.\n * Prefer this only when the key host allows CORS + Authorization (Video API\n * origin). CDN hosts typically authenticate via query params only — use XHR.\n */\nasync function loadEncryptionKeyWithFetch(\n context: LoaderContext,\n callbacks: LoaderCallbacks<LoaderContext>,\n accessToken: string | null | undefined,\n signal: AbortSignal,\n): Promise<void> {\n const stats = createLoaderStats();\n stats.loading.first = performance.now();\n\n const headers: Record<string, string> = {\n Accept: \"*/*\",\n ...(context.headers as Record<string, string> | undefined),\n };\n if (accessToken) {\n headers.Authorization = `Bearer ${accessToken}`;\n }\n\n const response = await fetch(context.url, {\n method: \"GET\",\n headers,\n credentials: \"omit\",\n cache: \"no-store\",\n signal,\n });\n\n if (!response.ok) {\n callbacks.onError(\n {\n code: response.status,\n text: response.statusText || `enc.key HTTP ${response.status}`,\n },\n context,\n response,\n stats,\n );\n return;\n }\n\n const data = await response.arrayBuffer();\n const end = performance.now();\n stats.loading.end = end;\n stats.loaded = data.byteLength;\n stats.total = data.byteLength;\n\n // Guard against HTML challenge pages mislabeled as keys.\n const head = new TextDecoder().decode(data.slice(0, 32));\n if (/<!DOCTYPE|<html/i.test(head)) {\n callbacks.onError(\n {\n code: 403,\n text: \"enc.key returned HTML (CDN challenge/block), not an AES key\",\n },\n context,\n response,\n stats,\n );\n return;\n }\n\n callbacks.onSuccess(\n {\n url: response.url || context.url,\n data,\n code: response.status,\n },\n stats,\n context,\n response,\n );\n}\n\n/**\n * hls.js loader that:\n * - Re-applies signed auth query params on every media request\n * - Loads AES `enc.key` via BFF / optional Bearer fetch / signed-query XHR\n *\n * Uses composition (not `extends DefaultConfig.loader`) so repeated mounts,\n * HMR, or a polluted DefaultConfig cannot nest `super.load()` into recursion.\n */\nexport function createAuthParamsLoader(\n HlsClass: typeof Hls,\n store: AuthParamsStore,\n options: AuthParamsLoaderOptions = {},\n): HlsLoader {\n const BaseLoader = resolveBuiltinHlsLoader(HlsClass);\n\n return class AuthParamsLoader {\n readonly stats: LoaderStats;\n private readonly inner: HlsLoaderInstance;\n private keyAbort: AbortController | null = null;\n\n constructor(config: object) {\n this.inner = new BaseLoader(config);\n // hls.js mutates loader.stats on the instance — share the same object.\n this.stats = this.inner.stats;\n }\n\n abort(): void {\n this.keyAbort?.abort();\n this.keyAbort = null;\n this.inner.abort?.();\n }\n\n destroy(): void {\n this.keyAbort?.abort();\n this.keyAbort = null;\n this.inner.destroy();\n }\n\n load(\n context: LoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<LoaderContext>,\n ): void {\n if (!context.url) {\n this.inner.load(context, config, callbacks);\n return;\n }\n\n try {\n const originalUrl = context.url;\n const isKey = isEncryptionKeyUrl(originalUrl);\n const usingKeyProxy = Boolean(\n isKey && options.keyProxyUrlBuilder && options.videoId,\n );\n context.url = rewriteHlsRequestUrl(originalUrl, store, options);\n\n if (usingKeyProxy) {\n this.inner.load(context, config, callbacks);\n return;\n }\n\n if (isKey && typeof options.getKeyAccessToken === \"function\") {\n const accessToken = options.getKeyAccessToken() ?? null;\n if (accessToken) {\n this.keyAbort?.abort();\n this.keyAbort = new AbortController();\n const timeoutMs =\n typeof config?.timeout === \"number\" && config.timeout > 0\n ? config.timeout\n : 20_000;\n const timer = setTimeout(() => this.keyAbort?.abort(), timeoutMs);\n\n void loadEncryptionKeyWithFetch(\n context,\n callbacks,\n accessToken,\n this.keyAbort.signal,\n )\n .catch((error: unknown) => {\n const stats = createLoaderStats();\n const aborted =\n error instanceof DOMException && error.name === \"AbortError\";\n callbacks.onError(\n {\n code: 0,\n text: aborted\n ? \"enc.key fetch aborted/timeout\"\n : error instanceof Error\n ? error.message\n : \"enc.key fetch failed\",\n },\n context,\n null,\n stats,\n );\n })\n .finally(() => {\n clearTimeout(timer);\n });\n return;\n }\n }\n } catch {\n // Fall through to default loader.\n }\n\n this.inner.load(context, config, callbacks);\n }\n };\n}\n","import type { AuthParamsStore } from \"../auth/AuthParamsStore\";\nimport type { Logger } from \"../logging/Logger\";\nimport type {\n HlsQualityLevel,\n HlsSupportMode,\n PlayerAudioTrack,\n PlayerState,\n PlayerTextTrack,\n QualitySelection,\n StreamingConfig,\n TextTrackSelection,\n} from \"../types\";\nimport { createAuthParamsLoader } from \"./authParamsLoader\";\n\nexport type HlsEngineCallbacks = {\n onStateChange?: (state: PlayerState) => void;\n onSupportMode?: (mode: HlsSupportMode) => void;\n onFatalError?: (message: string) => void;\n onAuthRecoveryNeeded?: (reason: string) => void;\n onQualitiesChange?: (levels: HlsQualityLevel[]) => void;\n onQualitySelectionChange?: (selection: QualitySelection) => void;\n onTextTracksChange?: (tracks: PlayerTextTrack[]) => void;\n onTextTrackSelectionChange?: (selection: TextTrackSelection) => void;\n onAudioTracksChange?: (tracks: PlayerAudioTrack[]) => void;\n onAudioTrackSelectionChange?: (selection: number) => void;\n onEnded?: () => void;\n};\n\nexport type HlsEngineOptions = {\n videoEl: HTMLVideoElement;\n playbackUrl: string;\n authParams: AuthParamsStore;\n autoplay: boolean;\n startMuted: boolean;\n startPosition?: number;\n volume?: number;\n videoId?: string;\n keyProxyUrlBuilder?: StreamingConfig[\"keyProxyUrlBuilder\"];\n getKeyAccessToken?: StreamingConfig[\"getKeyAccessToken\"];\n hlsConfig: {\n enableWorker: boolean;\n lowLatencyMode: boolean;\n backBufferLength: number;\n fatalRecoveryLimit: number;\n };\n logger: Logger;\n callbacks: HlsEngineCallbacks;\n};\n\nfunction isAuthHttpStatus(code: unknown): boolean {\n return code === 401 || code === 403;\n}\n\n/**\n * Dual-path HLS engine: hls.js when supported, otherwise native Safari HLS.\n *\n * Signed CDN playback requires auth query params on every HLS request\n * (playlists, segments, and AES `enc.key` on CDN hosts).\n *\n * Optional `streaming.keyProxyUrlBuilder` (same-origin BFF) or\n * `streaming.getKeyAccessToken` (browser Bearer) for Video API–origin keys\n * when query-signed CDN access is insufficient.\n */\nexport class HlsEngine {\n private hls: import(\"hls.js\").default | null = null;\n private destroyed = false;\n private supportMode: HlsSupportMode = \"unsupported\";\n private networkRecoveryCount = 0;\n private mediaRecoveryCount = 0;\n private qualities: HlsQualityLevel[] = [];\n private qualitySelection: QualitySelection = \"auto\";\n private textTracks: PlayerTextTrack[] = [];\n private textTrackSelection: TextTrackSelection = \"off\";\n private audioTracks: PlayerAudioTrack[] = [];\n private audioTrackSelection = 0;\n private nativeTextTrackCleanup: (() => void) | null = null;\n\n constructor(private readonly options: HlsEngineOptions) {}\n\n async start(): Promise<void> {\n const { videoEl, playbackUrl, startMuted, volume } = this.options;\n\n videoEl.muted = startMuted;\n if (typeof volume === \"number\") {\n videoEl.volume = Math.min(1, Math.max(0, volume));\n }\n\n const Hls = (await import(\"hls.js\")).default;\n\n if (Hls.isSupported()) {\n this.supportMode = \"hls.js\";\n this.options.callbacks.onSupportMode?.(\"hls.js\");\n await this.startWithHlsJs(Hls, playbackUrl);\n return;\n }\n\n if (videoEl.canPlayType(\"application/vnd.apple.mpegurl\")) {\n this.supportMode = \"native\";\n this.options.callbacks.onSupportMode?.(\"native\");\n videoEl.src = this.options.authParams.applyToUrl(playbackUrl);\n this.bindMediaEvents();\n this.bindNativeTextTracks();\n this.options.callbacks.onStateChange?.(\"ready\");\n await this.applyStartPositionAndAutoplay();\n return;\n }\n\n this.supportMode = \"unsupported\";\n this.options.callbacks.onSupportMode?.(\"unsupported\");\n this.options.callbacks.onFatalError?.(\n \"HLS is not supported in this browser\",\n );\n }\n\n private async startWithHlsJs(\n Hls: typeof import(\"hls.js\").default,\n playbackUrl: string,\n ): Promise<void> {\n const {\n videoEl,\n authParams,\n hlsConfig,\n callbacks,\n videoId,\n keyProxyUrlBuilder,\n getKeyAccessToken,\n } = this.options;\n\n const loader = createAuthParamsLoader(Hls, authParams, {\n videoId,\n keyProxyUrlBuilder,\n getKeyAccessToken,\n });\n\n this.hls = new Hls({\n enableWorker: hlsConfig.enableWorker,\n lowLatencyMode: hlsConfig.lowLatencyMode,\n backBufferLength: hlsConfig.backBufferLength,\n loader: loader as typeof Hls.DefaultConfig.loader,\n });\n\n this.hls.attachMedia(videoEl);\n this.hls.loadSource(authParams.applyToUrl(playbackUrl));\n\n this.hls.on(Hls.Events.MANIFEST_PARSED, (_event, data) => {\n if (this.destroyed) return;\n this.qualities = (data.levels ?? []).map((level, index) => ({\n index,\n height: level.height ?? 0,\n width: level.width ?? 0,\n bitrate: level.bitrate ?? 0,\n label:\n level.height != null && level.height > 0\n ? `${level.height}p`\n : `Level ${index}`,\n }));\n callbacks.onQualitiesChange?.(this.qualities);\n this.syncHlsSubtitleTracks();\n this.syncHlsAudioTracks();\n callbacks.onStateChange?.(\"ready\");\n void this.applyStartPositionAndAutoplay();\n });\n\n this.hls.on(Hls.Events.SUBTITLE_TRACKS_UPDATED, () => {\n if (this.destroyed) return;\n this.syncHlsSubtitleTracks();\n });\n\n this.hls.on(Hls.Events.AUDIO_TRACKS_UPDATED, () => {\n if (this.destroyed) return;\n this.syncHlsAudioTracks();\n });\n\n this.hls.on(Hls.Events.ERROR, (_event, data) => {\n this.handleHlsError(Hls, data);\n });\n\n this.bindMediaEvents();\n }\n\n private handleHlsError(\n Hls: typeof import(\"hls.js\").default,\n data: {\n fatal: boolean;\n type: string;\n details: string;\n response?: { code?: number };\n },\n ): void {\n if (this.destroyed) return;\n const { callbacks, hlsConfig } = this.options;\n const status = data.response?.code;\n\n // Only treat real HTTP auth failures as credential expiry.\n // Status 0 / undefined is usually CORS/abort — renewing cannot fix that.\n const authFailure = isAuthHttpStatus(status);\n\n if (data.details === Hls.ErrorDetails.KEY_LOAD_ERROR) {\n if (authFailure) {\n callbacks.onAuthRecoveryNeeded?.(\"key_error\");\n if (!data.fatal) return;\n } else if (!data.fatal) {\n // Do not require getKeyAccessToken/keyProxy — CDN keys use signed query.\n // Surface the real failure (HTTP / network) instead of a configure gate.\n callbacks.onFatalError?.(\n status\n ? `Encryption key load failed (HTTP ${status}).`\n : \"Encryption key load failed (network/CORS). Ensure signed query params are applied, or use keyProxyUrlBuilder / getKeyAccessToken when the key host requires API Bearer.\",\n );\n return;\n }\n }\n\n if (!data.fatal) {\n if (\n authFailure &&\n data.type === Hls.ErrorTypes.NETWORK_ERROR &&\n (data.details === Hls.ErrorDetails.FRAG_LOAD_ERROR ||\n data.details === Hls.ErrorDetails.LEVEL_LOAD_ERROR)\n ) {\n callbacks.onAuthRecoveryNeeded?.(\n data.details === Hls.ErrorDetails.LEVEL_LOAD_ERROR\n ? \"level_error\"\n : \"frag_error\",\n );\n }\n return;\n }\n\n if (data.type === Hls.ErrorTypes.NETWORK_ERROR) {\n this.networkRecoveryCount += 1;\n if (this.networkRecoveryCount <= hlsConfig.fatalRecoveryLimit) {\n if (authFailure) {\n callbacks.onAuthRecoveryNeeded?.(\"fatal_network\");\n }\n this.hls?.startLoad();\n return;\n }\n }\n\n if (data.type === Hls.ErrorTypes.MEDIA_ERROR) {\n this.mediaRecoveryCount += 1;\n if (this.mediaRecoveryCount <= hlsConfig.fatalRecoveryLimit) {\n this.hls?.recoverMediaError();\n return;\n }\n }\n\n callbacks.onFatalError?.(data.details || \"Fatal HLS error\");\n }\n\n private async applyStartPositionAndAutoplay(): Promise<void> {\n if (this.destroyed) return;\n const { videoEl, autoplay, startPosition } = this.options;\n\n if (typeof startPosition === \"number\" && startPosition > 0) {\n const seek = () => {\n if (this.destroyed) return;\n try {\n videoEl.currentTime = startPosition;\n } catch {\n // Ignore seek before seekable ranges are ready.\n }\n };\n if (videoEl.seekable.length > 0) {\n seek();\n } else {\n videoEl.addEventListener(\"loadedmetadata\", seek, { once: true });\n }\n }\n\n if (!autoplay) return;\n try {\n await videoEl.play();\n } catch {\n if (!videoEl.muted) {\n videoEl.muted = true;\n try {\n await videoEl.play();\n } catch {\n this.options.logger.warn(\"Autoplay blocked\");\n }\n }\n }\n }\n\n private bindMediaEvents(): void {\n const { videoEl, callbacks } = this.options;\n videoEl.addEventListener(\"playing\", () =>\n callbacks.onStateChange?.(\"playing\"),\n );\n videoEl.addEventListener(\"pause\", () => {\n if (!videoEl.ended) callbacks.onStateChange?.(\"paused\");\n });\n videoEl.addEventListener(\"waiting\", () =>\n callbacks.onStateChange?.(\"buffering\"),\n );\n videoEl.addEventListener(\"ended\", () => {\n callbacks.onStateChange?.(\"ended\");\n callbacks.onEnded?.();\n });\n }\n\n updateAuthParams(): void {\n if (this.supportMode === \"native\" && this.options.videoEl) {\n const time = this.options.videoEl.currentTime;\n const wasPaused = this.options.videoEl.paused;\n this.options.videoEl.src = this.options.authParams.applyToUrl(\n this.options.playbackUrl,\n );\n this.options.videoEl.currentTime = time;\n if (!wasPaused) void this.options.videoEl.play();\n }\n }\n\n resumeAfterAuthRenew(): void {\n this.networkRecoveryCount = 0;\n this.hls?.startLoad();\n this.updateAuthParams();\n }\n\n setQuality(selection: QualitySelection): void {\n this.qualitySelection = selection;\n if (!this.hls) return;\n this.hls.currentLevel = selection === \"auto\" ? -1 : selection;\n this.options.callbacks.onQualitySelectionChange?.(selection);\n }\n\n getQuality(): QualitySelection {\n return this.qualitySelection;\n }\n\n getQualities(): HlsQualityLevel[] {\n return this.qualities;\n }\n\n getTextTracks(): PlayerTextTrack[] {\n return this.textTracks;\n }\n\n getTextTrackSelection(): TextTrackSelection {\n return this.textTrackSelection;\n }\n\n setTextTrack(selection: TextTrackSelection): void {\n if (this.destroyed) return;\n this.textTrackSelection = selection;\n this.options.callbacks.onTextTrackSelectionChange?.(selection);\n\n if (this.supportMode === \"hls.js\" && this.hls) {\n this.hls.subtitleDisplay = selection !== \"off\";\n this.hls.subtitleTrack = selection === \"off\" ? -1 : selection;\n return;\n }\n\n if (this.supportMode === \"native\" && this.options.videoEl) {\n const tracks = this.options.videoEl.textTracks;\n for (let i = 0; i < tracks.length; i += 1) {\n const track = tracks[i]!;\n track.mode =\n selection !== \"off\" && i === selection ? \"showing\" : \"disabled\";\n }\n }\n }\n\n getAudioTracks(): PlayerAudioTrack[] {\n return this.audioTracks;\n }\n\n getAudioTrackSelection(): number {\n return this.audioTrackSelection;\n }\n\n setAudioTrack(index: number): void {\n if (this.destroyed) return;\n if (\n !Number.isInteger(index) ||\n index < 0 ||\n (this.audioTracks.length > 0 && index >= this.audioTracks.length)\n ) {\n return;\n }\n\n this.audioTrackSelection = index;\n this.options.callbacks.onAudioTrackSelectionChange?.(index);\n\n if (this.supportMode === \"hls.js\" && this.hls) {\n this.hls.audioTrack = index;\n return;\n }\n\n if (this.supportMode === \"native\" && this.options.videoEl) {\n const audioTracks = (\n this.options.videoEl as HTMLVideoElement & {\n audioTracks?: { length: number; [i: number]: { enabled: boolean } };\n }\n ).audioTracks;\n if (audioTracks && audioTracks.length > 0) {\n for (let i = 0; i < audioTracks.length; i += 1) {\n audioTracks[i]!.enabled = i === index;\n }\n }\n }\n }\n\n getSupportMode(): HlsSupportMode {\n return this.supportMode;\n }\n\n private syncHlsSubtitleTracks(): void {\n if (!this.hls) return;\n const tracks: PlayerTextTrack[] = (this.hls.subtitleTracks ?? []).map(\n (track, index) => ({\n index,\n id: String(track.id ?? index),\n label: track.name || track.lang || `Subtitles ${index + 1}`,\n language: track.lang,\n }),\n );\n this.textTracks = tracks;\n this.options.callbacks.onTextTracksChange?.(tracks);\n }\n\n private syncHlsAudioTracks(): void {\n if (!this.hls) return;\n const tracks: PlayerAudioTrack[] = (this.hls.audioTracks ?? []).map(\n (track, index) => ({\n index,\n id: String(track.id ?? index),\n label: track.name || track.lang || `Audio ${index + 1}`,\n language: track.lang,\n }),\n );\n this.audioTracks = tracks;\n this.options.callbacks.onAudioTracksChange?.(tracks);\n if (tracks.length > 0) {\n this.audioTrackSelection = 0;\n this.options.callbacks.onAudioTrackSelectionChange?.(0);\n }\n }\n\n private bindNativeTextTracks(): void {\n const { videoEl } = this.options;\n const syncFromElement = () => {\n if (this.destroyed || this.textTracks.length > 0) return;\n const list = videoEl.textTracks;\n const tracks: PlayerTextTrack[] = [];\n for (let i = 0; i < list.length; i += 1) {\n const track = list[i]!;\n if (track.kind !== \"subtitles\" && track.kind !== \"captions\") continue;\n tracks.push({\n index: tracks.length,\n id: track.id || `native-${tracks.length}`,\n label: track.label || track.language || `Track ${tracks.length + 1}`,\n language: track.language || undefined,\n });\n }\n if (tracks.length === 0) return;\n this.textTracks = tracks;\n this.options.callbacks.onTextTracksChange?.(tracks);\n };\n\n const textTracks = videoEl.textTracks as TextTrackList & {\n addEventListener?: (\n type: string,\n listener: EventListenerOrEventListenerObject,\n ) => void;\n removeEventListener?: (\n type: string,\n listener: EventListenerOrEventListenerObject,\n ) => void;\n };\n textTracks.addEventListener?.(\"addtrack\", syncFromElement);\n syncFromElement();\n this.nativeTextTrackCleanup = () => {\n textTracks.removeEventListener?.(\"addtrack\", syncFromElement);\n };\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.nativeTextTrackCleanup?.();\n this.nativeTextTrackCleanup = null;\n this.hls?.destroy();\n this.hls = null;\n const { videoEl } = this.options;\n videoEl.removeAttribute(\"src\");\n videoEl.load();\n }\n}\n","import { AuthManager } from \"../auth/AuthManager\";\nimport {\n assertNoSecretsInConfig,\n mergePlayerConfig,\n PACKAGE_VERSION,\n} from \"../config/defaults\";\nimport {\n createPlayerError,\n PlayerErrorCode,\n type PlayerError,\n} from \"../errors/PlayerError\";\nimport { EventEmitter } from \"../events/EventEmitter\";\nimport { Logger } from \"../logging/Logger\";\nimport { PlaybackSourceManager } from \"../playback/PlaybackSourceManager\";\nimport { RefreshManager } from \"../playback/RefreshManager\";\nimport {\n isAtLiveEdge,\n seekToLiveEdge,\n type SeekToLiveResult,\n} from \"../playback/liveEdge\";\nimport { HlsEngine } from \"../streaming/HlsEngine\";\nimport type {\n BufferedRange,\n CreateVideoPlayerOptions,\n PlayerAudioTrack,\n PlayerConfig,\n PlayerDiagnostics,\n PlayerState,\n PlayerTextTrack,\n QualitySelection,\n TextTrackSelection,\n} from \"../types\";\n\nfunction expiryStatus(\n expiresAt: number | null,\n safetyMs: number,\n): PlayerDiagnostics[\"authExpiryStatus\"] {\n if (expiresAt === null || expiresAt <= 0) return \"unknown\";\n const remaining = expiresAt - Date.now();\n if (remaining <= 0) return \"expired\";\n if (remaining <= safetyMs) return \"expiring_soon\";\n return \"valid\";\n}\n\nfunction generateSessionId(): string {\n if (typeof crypto !== \"undefined\" && \"randomUUID\" in crypto) {\n return crypto.randomUUID();\n }\n return `ps_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;\n}\n\nexport type VideoPlayer = {\n play: () => Promise<void>;\n pause: () => void;\n seek: (time: number) => void;\n /** Jump to the latest live edge. No-op when already at live. */\n goToLive: () => SeekToLiveResult;\n isLive: () => boolean;\n isAtLiveEdge: () => boolean;\n getCurrentTime: () => number;\n getDuration: () => number;\n setVolume: (volume: number) => void;\n getVolume: () => number;\n mute: () => void;\n unmute: () => void;\n isMuted: () => boolean;\n setPlaybackRate: (rate: number) => void;\n getPlaybackRate: () => number;\n getState: () => PlayerState;\n getBufferedRanges: () => BufferedRange[];\n getQuality: () => QualitySelection;\n setQuality: (selection: QualitySelection | string) => void;\n getAvailableQualities: () => ReturnType<HlsEngine[\"getQualities\"]>;\n getTextTracks: () => PlayerTextTrack[];\n getSelectedTextTrack: () => TextTrackSelection;\n setTextTrack: (selection: TextTrackSelection) => void;\n getAudioTracks: () => PlayerAudioTrack[];\n getSelectedAudioTrack: () => number;\n setAudioTrack: (index: number) => void;\n enterFullscreen: () => Promise<void>;\n exitFullscreen: () => Promise<void>;\n isFullscreen: () => boolean;\n /** Attach fullscreen target container (host UI chrome). Zoom stays UI-only. */\n setFullscreenElement: (el: HTMLElement | null) => void;\n reload: () => Promise<void>;\n destroy: () => void;\n getDiagnostics: () => PlayerDiagnostics;\n getConfig: () => PlayerConfig;\n updateConfig: (partial: Parameters<typeof mergePlayerConfig>[0]) => void;\n on: EventEmitter[\"on\"];\n off: EventEmitter[\"off\"];\n};\n\n/**\n * Creates a framework-agnostic video player.\n * Never pass clientSecret — use auth.getToken / playback.getSource callbacks.\n */\nexport function createVideoPlayer(\n options: CreateVideoPlayerOptions,\n): VideoPlayer {\n // Scan only config-shaped fields — never deep-walk mount (HTMLVideoElement)\n // or credential callback objects (auth / playback).\n assertNoSecretsInConfig({\n videoId: options.videoId,\n sourceUrl: options.sourceUrl,\n player: options.player,\n controls: options.controls,\n theme: options.theme,\n watermark: options.watermark,\n streaming: options.streaming,\n logging: options.logging,\n debug: options.debug,\n accessibility: options.accessibility,\n });\n\n let config = mergePlayerConfig({\n player: options.player,\n controls: options.controls,\n theme: options.theme,\n watermark: options.watermark,\n streaming: options.streaming,\n logging: options.logging,\n debug: options.debug,\n accessibility: options.accessibility,\n });\n\n const events = new EventEmitter();\n const logger = new Logger(config.logging);\n const playbackSessionId = generateSessionId();\n\n let state: PlayerState = \"idle\";\n let destroyed = false;\n let lastError: PlayerError | null = null;\n let videoEl = options.mount ?? null;\n let engine: HlsEngine | null = null;\n let refreshManager: RefreshManager | null = null;\n let fullscreenEl: HTMLElement | null = null;\n let isLiveStream = false;\n let mediaCleanup: (() => void) | null = null;\n\n const setState = (next: PlayerState) => {\n if (destroyed && next !== \"destroyed\") return;\n state = next;\n events.emit(\"statechange\", { state: next });\n };\n\n const bindMediaProgressEvents = (el: HTMLVideoElement) => {\n mediaCleanup?.();\n const onTimeUpdate = () => {\n if (destroyed) return;\n events.emit(\"timeupdate\", {\n currentTime: el.currentTime,\n duration: Number.isFinite(el.duration) ? el.duration : 0,\n });\n };\n const onProgress = () => {\n if (destroyed) return;\n let bufferedEnd = 0;\n try {\n if (el.buffered.length > 0) {\n bufferedEnd = el.buffered.end(el.buffered.length - 1);\n }\n } catch {\n bufferedEnd = 0;\n }\n events.emit(\"progress\", { bufferedEnd });\n };\n el.addEventListener(\"timeupdate\", onTimeUpdate);\n el.addEventListener(\"progress\", onProgress);\n mediaCleanup = () => {\n el.removeEventListener(\"timeupdate\", onTimeUpdate);\n el.removeEventListener(\"progress\", onProgress);\n };\n };\n\n const authManager = new AuthManager(\n options.auth,\n options.auth?.refreshBeforeExpiryMs ?? 60_000,\n logger,\n (token) => events.emit(\"authrefresh\", { expiresAt: token.expiresAt }),\n (message, retryable) =>\n events.emit(\"autherror\", { message, retryable }),\n );\n\n const sourceManager = new PlaybackSourceManager(options.playback, logger);\n\n const ensureVideoElement = (): HTMLVideoElement => {\n if (!videoEl) {\n throw createPlayerError(\n PlayerErrorCode.INVALID_CONFIGURATION,\n \"A video element must be provided via mount before starting playback\",\n { category: \"config\", fatal: true, retryable: false },\n );\n }\n return videoEl;\n };\n\n const startPlayback = async (): Promise<void> => {\n if (destroyed) return;\n setState(\"loading\");\n lastError = null;\n\n const videoId = options.videoId ?? \"unknown\";\n\n try {\n await authManager.ensureToken({\n reason: \"initial\",\n videoId: options.videoId,\n });\n\n let playbackUrl: string;\n let expiresAt: number;\n\n if (options.sourceUrl) {\n const source = {\n url: options.sourceUrl,\n expiresAt: Date.now() + 24 * 60 * 60 * 1000,\n live: /\\/hls-web-live\\//i.test(options.sourceUrl),\n };\n sourceManager.applyDirectSource(source);\n playbackUrl = source.url;\n expiresAt = source.expiresAt;\n isLiveStream = Boolean(source.live);\n } else {\n const source = await sourceManager.load({\n videoId,\n reason: \"initial\",\n });\n playbackUrl = source.url;\n expiresAt = source.expiresAt;\n isLiveStream = Boolean(source.live);\n }\n\n const el = ensureVideoElement();\n bindMediaProgressEvents(el);\n engine?.destroy();\n engine = new HlsEngine({\n videoEl: el,\n playbackUrl,\n authParams: sourceManager.authParams,\n autoplay: config.player.autoplay,\n startMuted: config.player.startMuted,\n startPosition: config.player.startPosition,\n volume: config.player.volume,\n videoId: options.videoId,\n keyProxyUrlBuilder: config.streaming.keyProxyUrlBuilder,\n // Optional: browser Bearer for Video API–origin enc.key (CORS-dependent).\n // CDN keys use signed query via the auth loader (no Bearer) — same as\n // segments. Apps can pass getKeyAccessToken or rely on keyProxyUrlBuilder.\n // When unset, defaults to AuthManager token only if explicitly requested\n // via streaming.getKeyAccessToken; otherwise query-signed XHR.\n getKeyAccessToken: config.streaming.getKeyAccessToken,\n hlsConfig: config.streaming.hls,\n logger,\n callbacks: {\n onStateChange: (s) => {\n setState(s);\n if (s === \"ready\") events.emit(\"ready\");\n if (s === \"playing\") {\n events.emit(\"play\");\n events.emit(\"playing\");\n }\n if (s === \"paused\") events.emit(\"pause\");\n if (s === \"buffering\") events.emit(\"buffering\");\n if (s === \"ended\") events.emit(\"ended\");\n },\n onFatalError: (message) => {\n lastError = createPlayerError(\n PlayerErrorCode.PLAYBACK_ERROR,\n message,\n { category: \"playback\", fatal: true, retryable: true },\n );\n setState(\"error\");\n events.emit(\"error\", {\n code: lastError.code,\n message: lastError.message,\n fatal: true,\n });\n },\n onAuthRecoveryNeeded: (reason) => {\n refreshManager?.requestRenew(\n reason as \"frag_error\" | \"level_error\" | \"key_error\" | \"fatal_network\",\n );\n },\n onQualitiesChange: () => {\n /* consumers poll getAvailableQualities */\n },\n onQualitySelectionChange: (selection) => {\n const level = engine\n ?.getQualities()\n .find((q) => q.index === selection);\n events.emit(\"qualitychange\", {\n selection,\n label: typeof selection === \"number\" ? level?.label : \"auto\",\n });\n },\n onTextTracksChange: (tracks) => {\n events.emit(\"texttrackchange\", {\n tracks,\n selection: engine?.getTextTrackSelection() ?? \"off\",\n });\n },\n onTextTrackSelectionChange: (selection) => {\n events.emit(\"texttrackchange\", {\n tracks: engine?.getTextTracks() ?? [],\n selection,\n });\n },\n onAudioTracksChange: (tracks) => {\n events.emit(\"audiotrackchange\", {\n tracks,\n selection: engine?.getAudioTrackSelection() ?? 0,\n });\n },\n onAudioTrackSelectionChange: (selection) => {\n events.emit(\"audiotrackchange\", {\n tracks: engine?.getAudioTracks() ?? [],\n selection,\n });\n },\n onEnded: () => events.emit(\"ended\"),\n },\n });\n\n await engine.start();\n\n if (!options.sourceUrl && options.playback) {\n refreshManager?.stop();\n refreshManager = new RefreshManager({\n videoId,\n authManager,\n sourceManager,\n refreshBeforeExpiryMs:\n options.playback.refreshBeforeExpiryMs ?? 30_000,\n renewMaxRetries: options.playback.renewMaxRetries ?? 3,\n renewBackoffMs: options.playback.renewBackoffMs ?? 2_000,\n coalesceMs: options.playback.authRecoveryCoalesceMs ?? 1_000,\n logger,\n isDestroyed: () => destroyed,\n onRenewing: () => setState(\"renewing\"),\n onRenewed: (nextExpiresAt) => {\n engine?.resumeAfterAuthRenew();\n if (!destroyed) {\n const el = videoEl;\n if (el && !el.paused && !el.ended) {\n setState(\"playing\");\n } else {\n setState(\"ready\");\n }\n }\n events.emit(\"tokenrefresh\", { expiresAt: nextExpiresAt });\n events.emit(\"sourcechange\", { expiresAt: nextExpiresAt });\n },\n onFatal: (message) => {\n lastError = createPlayerError(\n PlayerErrorCode.TOKEN_REFRESH_FAILED,\n message,\n { category: \"auth\", fatal: true, retryable: true },\n );\n setState(\"error\");\n events.emit(\"error\", {\n code: lastError.code,\n message: lastError.message,\n fatal: true,\n });\n },\n });\n refreshManager.start(expiresAt);\n }\n\n options.analytics?.onEvent?.({\n type: \"PLAYER_INITIALIZED\",\n payload: { videoId, playbackSessionId },\n });\n } catch (error) {\n const playerError =\n error && typeof error === \"object\" && \"code\" in error\n ? (error as PlayerError)\n : createPlayerError(\n PlayerErrorCode.UNKNOWN,\n error instanceof Error ? error.message : \"Failed to start player\",\n { category: \"unknown\", fatal: true, retryable: true, cause: error },\n );\n lastError = playerError;\n setState(\"error\");\n events.emit(\"error\", {\n code: playerError.code,\n message: playerError.message,\n fatal: playerError.fatal,\n });\n throw playerError;\n }\n };\n\n // Auto-start when mount is provided\n if (options.mount) {\n void startPlayback().catch(() => {\n /* error already emitted */\n });\n }\n\n const api: VideoPlayer = {\n async play() {\n await ensureVideoElement().play();\n },\n pause() {\n ensureVideoElement().pause();\n },\n seek(time: number) {\n const el = ensureVideoElement();\n const duration = Number.isFinite(el.duration) ? el.duration : time;\n el.currentTime = Math.min(Math.max(0, time), duration);\n },\n goToLive() {\n const el = ensureVideoElement();\n return seekToLiveEdge(el);\n },\n isLive() {\n return isLiveStream;\n },\n isAtLiveEdge() {\n if (!isLiveStream || !videoEl) {\n return true;\n }\n return isAtLiveEdge(videoEl);\n },\n getCurrentTime() {\n return videoEl?.currentTime ?? 0;\n },\n getDuration() {\n return videoEl?.duration ?? 0;\n },\n setVolume(volume: number) {\n const el = ensureVideoElement();\n el.volume = Math.min(1, Math.max(0, volume));\n events.emit(\"volumechange\", { volume: el.volume, muted: el.muted });\n },\n getVolume() {\n return videoEl?.volume ?? 0;\n },\n mute() {\n const el = ensureVideoElement();\n el.muted = true;\n events.emit(\"volumechange\", { volume: el.volume, muted: true });\n },\n unmute() {\n const el = ensureVideoElement();\n el.muted = false;\n events.emit(\"volumechange\", { volume: el.volume, muted: false });\n },\n isMuted() {\n return videoEl?.muted ?? false;\n },\n setPlaybackRate(rate: number) {\n ensureVideoElement().playbackRate = rate;\n },\n getPlaybackRate() {\n return videoEl?.playbackRate ?? 1;\n },\n getState() {\n return state;\n },\n getBufferedRanges() {\n const el = videoEl;\n if (!el) return [];\n const ranges: BufferedRange[] = [];\n for (let i = 0; i < el.buffered.length; i += 1) {\n ranges.push({ start: el.buffered.start(i), end: el.buffered.end(i) });\n }\n return ranges;\n },\n getQuality() {\n return engine?.getQuality() ?? \"auto\";\n },\n setQuality(selection: QualitySelection | string) {\n if (selection === \"auto\") {\n engine?.setQuality(\"auto\");\n return;\n }\n if (typeof selection === \"number\") {\n engine?.setQuality(selection);\n return;\n }\n const match = engine\n ?.getQualities()\n .find((q) => q.label === selection || `${q.height}p` === selection);\n if (match) engine?.setQuality(match.index);\n },\n getAvailableQualities() {\n return engine?.getQualities() ?? [];\n },\n getTextTracks() {\n return engine?.getTextTracks() ?? [];\n },\n getSelectedTextTrack() {\n return engine?.getTextTrackSelection() ?? \"off\";\n },\n setTextTrack(selection: TextTrackSelection) {\n engine?.setTextTrack(selection);\n },\n getAudioTracks() {\n return engine?.getAudioTracks() ?? [];\n },\n getSelectedAudioTrack() {\n return engine?.getAudioTrackSelection() ?? 0;\n },\n setAudioTrack(index: number) {\n engine?.setAudioTrack(index);\n },\n async enterFullscreen() {\n const target = fullscreenEl ?? videoEl?.parentElement ?? videoEl;\n if (target && \"requestFullscreen\" in target) {\n await target.requestFullscreen();\n events.emit(\"fullscreenchange\", { isFullscreen: true });\n }\n },\n async exitFullscreen() {\n if (document.fullscreenElement) {\n await document.exitFullscreen();\n events.emit(\"fullscreenchange\", { isFullscreen: false });\n }\n },\n isFullscreen() {\n return Boolean(document.fullscreenElement);\n },\n setFullscreenElement(el: HTMLElement | null) {\n fullscreenEl = el;\n },\n async reload() {\n refreshManager?.stop();\n engine?.destroy();\n await startPlayback();\n },\n destroy() {\n if (destroyed) return;\n destroyed = true;\n mediaCleanup?.();\n mediaCleanup = null;\n refreshManager?.stop();\n refreshManager = null;\n engine?.destroy();\n engine = null;\n authManager.destroy();\n sourceManager.destroy();\n setState(\"destroyed\");\n events.emit(\"destroy\");\n events.removeAll();\n options.analytics?.onEvent?.({ type: \"PLAYER_DESTROYED\" });\n },\n getDiagnostics() {\n const buffered = api.getBufferedRanges();\n return {\n playerVersion: PACKAGE_VERSION,\n currentState: state,\n hlsSupport: engine?.getSupportMode() ?? \"unsupported\",\n videoId: options.videoId ?? null,\n currentTime: api.getCurrentTime(),\n duration: api.getDuration(),\n bufferedEnd: buffered.length ? buffered[buffered.length - 1]!.end : 0,\n currentQuality:\n api.getQuality() === \"auto\"\n ? \"auto\"\n : engine?.getQualities().find((q) => q.index === api.getQuality())\n ?.label ?? null,\n playbackSessionId,\n authExpiryStatus: expiryStatus(\n authManager.getExpiresAt(),\n options.auth?.refreshBeforeExpiryMs ?? 60_000,\n ),\n sourceExpiryStatus: expiryStatus(\n sourceManager.getExpiresAt(),\n options.playback?.refreshBeforeExpiryMs ?? 30_000,\n ),\n lastError: lastError?.message ?? null,\n };\n },\n getConfig() {\n return config;\n },\n updateConfig(partial) {\n config = mergePlayerConfig({\n player: { ...config.player, ...partial?.player },\n controls: { ...config.controls, ...partial?.controls },\n theme: { ...config.theme, ...partial?.theme },\n watermark: { ...config.watermark, ...partial?.watermark },\n streaming: {\n engine: \"hls\",\n hls: { ...config.streaming.hls, ...partial?.streaming?.hls },\n keyProxyUrlBuilder:\n partial?.streaming?.keyProxyUrlBuilder ??\n config.streaming.keyProxyUrlBuilder,\n getKeyAccessToken:\n partial?.streaming?.getKeyAccessToken ??\n config.streaming.getKeyAccessToken,\n },\n logging: { ...config.logging, ...partial?.logging },\n debug: { ...config.debug, ...partial?.debug },\n accessibility: {\n ...config.accessibility,\n ...partial?.accessibility,\n },\n });\n logger.update(config.logging);\n },\n on: events.on.bind(events),\n off: events.off.bind(events),\n };\n\n // Allow attaching mount after create\n (api as VideoPlayer & { attach: (el: HTMLVideoElement, container?: HTMLElement) => Promise<void> }).attach =\n async (el: HTMLVideoElement, container?: HTMLElement) => {\n videoEl = el;\n fullscreenEl = container ?? null;\n await startPlayback();\n };\n\n return api;\n}\n\nexport type { CreateVideoPlayerOptions };\n"],"mappings":"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","names":["PlayerErrorCode","isPlainObject","BuiltinXhrLoader","el"]}