@codenkay/video-nsgplayer-core 0.1.2 → 0.1.3

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../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/HlsEngine.ts","../src/player/createVideoPlayer.ts"],"sourcesContent":["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.2\";\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]);\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?: unknown;\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 },\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\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\") {\n if (/^https?:\\/\\//i.test(value) && /[?&](token|expires)=/i.test(value)) {\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 }\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\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 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 applyToUrl(rawUrl: string, baseOrigin?: string): string {\n const target = new URL(rawUrl, baseOrigin ?? (typeof location !== \"undefined\" ? location.origin : \"http://localhost\"));\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 =\n error instanceof Error ? error.message : \"Playback refresh failed\";\n this.options.logger.warn(\"Playback refresh failed\", {\n reason,\n failure: this.consecutiveFailures,\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","/**\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 { AuthParamsStore } from \"../auth/AuthParamsStore\";\nimport type { Logger } from \"../logging/Logger\";\nimport type {\n HlsQualityLevel,\n HlsSupportMode,\n PlayerState,\n QualitySelection,\n} from \"../types\";\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 hlsConfig: {\n enableWorker: boolean;\n lowLatencyMode: boolean;\n backBufferLength: number;\n fatalRecoveryLimit: number;\n };\n logger: Logger;\n callbacks: HlsEngineCallbacks;\n};\n\n/**\n * Dual-path HLS engine: hls.js when supported, otherwise native Safari HLS.\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, autoplay, startMuted, volume, startPosition } =\n this.options;\n\n videoEl.muted = startMuted;\n if (typeof volume === \"number\") videoEl.volume = Math.min(1, Math.max(0, volume));\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 } else 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 } else {\n this.supportMode = \"unsupported\";\n this.options.callbacks.onSupportMode?.(\"unsupported\");\n this.options.callbacks.onFatalError?.(\"HLS is not supported in this browser\");\n return;\n }\n\n if (typeof startPosition === \"number\" && startPosition > 0) {\n videoEl.currentTime = startPosition;\n }\n\n if (autoplay) {\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\n private async startWithHlsJs(\n Hls: typeof import(\"hls.js\").default,\n playbackUrl: string,\n ): Promise<void> {\n const { videoEl, authParams, hlsConfig, callbacks } = this.options;\n\n this.hls = new Hls({\n enableWorker: hlsConfig.enableWorker,\n lowLatencyMode: hlsConfig.lowLatencyMode,\n backBufferLength: hlsConfig.backBufferLength,\n xhrSetup: (xhr, url) => {\n // Auth params are applied via loader URL rewriting below when possible.\n void xhr;\n void url;\n },\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 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 });\n\n this.hls.on(Hls.Events.ERROR, (_event, data) => {\n if (!data.fatal) {\n if (\n data.type === Hls.ErrorTypes.NETWORK_ERROR &&\n (data.details === Hls.ErrorDetails.FRAG_LOAD_ERROR ||\n data.details === Hls.ErrorDetails.LEVEL_LOAD_ERROR ||\n data.details === Hls.ErrorDetails.KEY_LOAD_ERROR)\n ) {\n callbacks.onAuthRecoveryNeeded?.(\n data.details === Hls.ErrorDetails.KEY_LOAD_ERROR\n ? \"key_error\"\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 callbacks.onAuthRecoveryNeeded?.(\"fatal_network\");\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 this.bindMediaEvents();\n }\n\n private bindMediaEvents(): void {\n const { videoEl, callbacks } = this.options;\n videoEl.addEventListener(\"playing\", () => callbacks.onStateChange?.(\"playing\"));\n videoEl.addEventListener(\"pause\", () => {\n if (!videoEl.ended) callbacks.onStateChange?.(\"paused\");\n });\n videoEl.addEventListener(\"waiting\", () => callbacks.onStateChange?.(\"buffering\"));\n videoEl.addEventListener(\"ended\", () => {\n callbacks.onStateChange?.(\"ended\");\n callbacks.onEnded?.();\n });\n }\n\n updateAuthParams(): void {\n // AuthParamsStore is live; next segment/manifest requests should use updated params.\n // For hls.js we kick startLoad after reactive renew.\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.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 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 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 },\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"]}
1
+ {"version":3,"sources":["../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 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.3\";\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]);\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 };\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 },\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\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\") {\n if (/^https?:\\/\\//i.test(value) && /[?&](token|expires)=/i.test(value)) {\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 }\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\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 =\n error instanceof Error ? error.message : \"Playback refresh failed\";\n this.options.logger.warn(\"Playback refresh failed\", {\n reason,\n failure: this.consecutiveFailures,\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","/**\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 type {\n LoaderCallbacks,\n LoaderConfiguration,\n LoaderContext,\n} from \"hls.js\";\nimport type { AuthParamsStore } from \"../auth/AuthParamsStore\";\nimport type { StreamingConfig } from \"../types\";\n\ntype HlsLoader = new (config: object) => {\n load(\n context: LoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<LoaderContext>,\n ): void;\n destroy(): void;\n};\n\nconst ENC_KEY_PATH_RE = /\\/enc\\.key$/i;\n\nexport type AuthParamsLoaderOptions = {\n videoId?: string;\n keyProxyUrlBuilder?: StreamingConfig[\"keyProxyUrlBuilder\"];\n};\n\n/**\n * Rewrites an HLS request URL so signed auth query params are present.\n * Master playlists are signed on loadSource; child playlists / segments / keys\n * are relative and would otherwise be fetched unsigned → CDN 403.\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 });\n }\n\n if (!store.hasParams()) return parsed.toString();\n return store.applyToUrl(rawUrl, baseOrigin);\n}\n\n/**\n * hls.js loader that re-applies live AuthParamsStore credentials on every\n * manifest / level / fragment / key request.\n */\nexport function createAuthParamsLoader(\n HlsClass: typeof Hls,\n store: AuthParamsStore,\n options: AuthParamsLoaderOptions = {},\n): HlsLoader {\n const BaseLoader = HlsClass.DefaultConfig.loader as HlsLoader;\n\n return class AuthParamsLoader extends BaseLoader {\n load(\n context: LoaderContext,\n config: LoaderConfiguration,\n callbacks: LoaderCallbacks<LoaderContext>,\n ): void {\n if (context.url) {\n try {\n context.url = rewriteHlsRequestUrl(context.url, store, options);\n } catch {\n // Leave context.url unchanged if parsing fails.\n }\n }\n super.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 hlsConfig: {\n enableWorker: boolean;\n lowLatencyMode: boolean;\n backBufferLength: number;\n fatalRecoveryLimit: number;\n };\n logger: Logger;\n callbacks: HlsEngineCallbacks;\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 * (master, media playlist, segments, keys). hls.js only receives the signed\n * master URL via loadSource; child URIs are relative and unsigned unless a\n * custom loader re-applies AuthParamsStore on each request.\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, autoplay, startMuted, volume, startPosition } =\n this.options;\n\n videoEl.muted = startMuted;\n if (typeof volume === \"number\") videoEl.volume = Math.min(1, Math.max(0, volume));\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 } else 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 } else {\n this.supportMode = \"unsupported\";\n this.options.callbacks.onSupportMode?.(\"unsupported\");\n this.options.callbacks.onFatalError?.(\"HLS is not supported in this browser\");\n return;\n }\n\n if (typeof startPosition === \"number\" && startPosition > 0) {\n videoEl.currentTime = startPosition;\n }\n\n if (autoplay) {\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\n private async startWithHlsJs(\n Hls: typeof import(\"hls.js\").default,\n playbackUrl: string,\n ): Promise<void> {\n const { videoEl, authParams, hlsConfig, callbacks, videoId, keyProxyUrlBuilder } =\n this.options;\n\n const loader = createAuthParamsLoader(Hls, authParams, {\n videoId,\n keyProxyUrlBuilder,\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 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 });\n\n this.hls.on(Hls.Events.ERROR, (_event, data) => {\n if (!data.fatal) {\n if (\n data.type === Hls.ErrorTypes.NETWORK_ERROR &&\n (data.details === Hls.ErrorDetails.FRAG_LOAD_ERROR ||\n data.details === Hls.ErrorDetails.LEVEL_LOAD_ERROR ||\n data.details === Hls.ErrorDetails.KEY_LOAD_ERROR)\n ) {\n callbacks.onAuthRecoveryNeeded?.(\n data.details === Hls.ErrorDetails.KEY_LOAD_ERROR\n ? \"key_error\"\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 callbacks.onAuthRecoveryNeeded?.(\"fatal_network\");\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 this.bindMediaEvents();\n }\n\n private bindMediaEvents(): void {\n const { videoEl, callbacks } = this.options;\n videoEl.addEventListener(\"playing\", () => callbacks.onStateChange?.(\"playing\"));\n videoEl.addEventListener(\"pause\", () => {\n if (!videoEl.ended) callbacks.onStateChange?.(\"paused\");\n });\n videoEl.addEventListener(\"waiting\", () => callbacks.onStateChange?.(\"buffering\"));\n videoEl.addEventListener(\"ended\", () => {\n callbacks.onStateChange?.(\"ended\");\n callbacks.onEnded?.();\n });\n }\n\n updateAuthParams(): void {\n // AuthParamsStore is live; the custom loader reads it on each request.\n // For native HLS we must reload the signed master URL.\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.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: options.streaming?.keyProxyUrlBuilder,\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 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 },\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codenkay/video-nsgplayer-core",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Framework-agnostic NSG HLS video player engine",
5
5
  "license": "MIT",
6
6
  "author": "NSG Player",