@codenkay/video-nsgplayer-core 0.1.0 → 0.1.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.2
4
+
5
+ - Fix `InternalError: too much recursion` / stack overflow in `assertNoSecretsInConfig` when `createVideoPlayer` options include an `HTMLVideoElement` mount or credential callbacks.
6
+ - Secret scanning is now plain-object only, iterative, depth-capped, and does not deep-walk `mount` / `auth` / `playback`.
7
+ - Harden `redactObject` against circular graphs.
8
+
9
+ ## 0.1.1
10
+
11
+ - Live-edge and config scan hardening.
12
+
3
13
  ## 0.1.0
4
14
 
5
15
  - Initial release
package/dist/index.cjs CHANGED
@@ -44,11 +44,13 @@ __export(index_exports, {
44
44
  PlaybackSourceManager: () => PlaybackSourceManager,
45
45
  PlayerErrorCode: () => PlayerErrorCode,
46
46
  RefreshManager: () => RefreshManager,
47
+ SECRET_SCAN_MAX_DEPTH: () => SECRET_SCAN_MAX_DEPTH,
47
48
  assertNoSecretsInConfig: () => assertNoSecretsInConfig,
48
49
  createPlayerError: () => createPlayerError,
49
50
  createVideoPlayer: () => createVideoPlayer,
50
51
  getLiveEdgeTime: () => getLiveEdgeTime,
51
52
  isAtLiveEdge: () => isAtLiveEdge,
53
+ isPlainObject: () => isPlainObject,
52
54
  mergePlayerConfig: () => mergePlayerConfig,
53
55
  redactObject: () => redactObject,
54
56
  redactSensitive: () => redactSensitive,
@@ -206,7 +208,7 @@ var AuthManager = class {
206
208
 
207
209
  // src/config/defaults.ts
208
210
  var PLAYBACK_RATES = [0.5, 0.75, 1, 1.25, 1.5, 2];
209
- var PACKAGE_VERSION = "0.1.0";
211
+ var PACKAGE_VERSION = "0.1.2";
210
212
  var DEFAULT_PLAYER_BEHAVIOR = {
211
213
  autoplay: true,
212
214
  startMuted: true,
@@ -292,22 +294,83 @@ var FORBIDDEN_SECRET_KEYS = [
292
294
  "basicauthpassword",
293
295
  "password"
294
296
  ];
297
+ var SKIP_DEEP_SCAN_KEYS = /* @__PURE__ */ new Set([
298
+ "mount",
299
+ "auth",
300
+ "playback",
301
+ "gettoken",
302
+ "getsource",
303
+ "refreshsource",
304
+ "keyproxyurlbuilder"
305
+ ]);
306
+ var SECRET_SCAN_MAX_DEPTH = 32;
307
+ function isPlainObject(value) {
308
+ if (value === null || typeof value !== "object") return false;
309
+ if (Array.isArray(value)) return false;
310
+ const proto = Object.getPrototypeOf(value);
311
+ return proto === Object.prototype || proto === null;
312
+ }
313
+ function normalizeConfigKey(key) {
314
+ return key.toLowerCase().replace(/[^a-z0-9]/g, "");
315
+ }
316
+ function isForbiddenSecretKey(key) {
317
+ const lower = normalizeConfigKey(key);
318
+ return FORBIDDEN_SECRET_KEYS.some((k) => lower.includes(k));
319
+ }
320
+ function throwForbidden(path, key) {
321
+ throw new Error(
322
+ `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().`
323
+ );
324
+ }
295
325
  function assertNoSecretsInConfig(raw) {
296
- if (!raw || typeof raw !== "object") return;
297
- const walk = (obj, path) => {
298
- for (const [key, value] of Object.entries(obj)) {
299
- const lower = key.toLowerCase().replace(/[^a-z0-9]/g, "");
300
- if (FORBIDDEN_SECRET_KEYS.some((k) => lower.includes(k))) {
301
- throw new Error(
302
- `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().`
303
- );
326
+ if (!isPlainObject(raw) && !Array.isArray(raw)) return;
327
+ const seen = /* @__PURE__ */ new WeakSet();
328
+ const stack = [
329
+ { value: raw, path: "", depth: 0 }
330
+ ];
331
+ while (stack.length > 0) {
332
+ const current = stack.pop();
333
+ if (current.depth > SECRET_SCAN_MAX_DEPTH) continue;
334
+ const { value, path, depth } = current;
335
+ if (Array.isArray(value)) {
336
+ if (seen.has(value)) continue;
337
+ seen.add(value);
338
+ for (let i = 0; i < value.length; i += 1) {
339
+ const item = value[i];
340
+ if (isPlainObject(item) || Array.isArray(item)) {
341
+ stack.push({ value: item, path: `${path}[${i}]`, depth: depth + 1 });
342
+ }
304
343
  }
305
- if (value && typeof value === "object" && !Array.isArray(value)) {
306
- walk(value, `${path}${key}.`);
344
+ continue;
345
+ }
346
+ if (!isPlainObject(value)) continue;
347
+ if (seen.has(value)) continue;
348
+ seen.add(value);
349
+ for (const [key, child] of Object.entries(value)) {
350
+ const normalized = normalizeConfigKey(key);
351
+ if (isForbiddenSecretKey(key)) {
352
+ throwForbidden(path, key);
353
+ }
354
+ if (normalized === "mount") continue;
355
+ if (SKIP_DEEP_SCAN_KEYS.has(normalized)) {
356
+ if (isPlainObject(child)) {
357
+ for (const nestedKey of Object.keys(child)) {
358
+ if (isForbiddenSecretKey(nestedKey)) {
359
+ throwForbidden(`${path}${key}.`, nestedKey);
360
+ }
361
+ }
362
+ }
363
+ continue;
364
+ }
365
+ if (isPlainObject(child) || Array.isArray(child)) {
366
+ stack.push({
367
+ value: child,
368
+ path: path ? `${path}${key}.` : `${key}.`,
369
+ depth: depth + 1
370
+ });
307
371
  }
308
372
  }
309
- };
310
- walk(raw, "");
373
+ }
311
374
  }
312
375
  function mergePlayerConfig(partial) {
313
376
  assertNoSecretsInConfig(partial);
@@ -395,7 +458,14 @@ var EventEmitter = class {
395
458
 
396
459
  // src/security/redaction.ts
397
460
  var SENSITIVE_KEYS = /^(authorization|cookie|set-cookie|x-api-key|token|accessToken|access_token|clientSecret|password)$/i;
398
- function redactValue(key, value) {
461
+ var REDACT_MAX_DEPTH = 32;
462
+ function isPlainObject2(value) {
463
+ if (value === null || typeof value !== "object") return false;
464
+ if (Array.isArray(value)) return false;
465
+ const proto = Object.getPrototypeOf(value);
466
+ return proto === Object.prototype || proto === null;
467
+ }
468
+ function redactValue(key, value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
399
469
  if (SENSITIVE_KEYS.test(key)) return "[REDACTED]";
400
470
  if (typeof value === "string") {
401
471
  if (/^https?:\/\//i.test(value) && /[?&](token|expires)=/i.test(value)) {
@@ -412,15 +482,25 @@ function redactValue(key, value) {
412
482
  }
413
483
  }
414
484
  }
415
- if (value && typeof value === "object" && !Array.isArray(value)) {
416
- return redactObject(value);
485
+ if (Array.isArray(value)) {
486
+ if (depth >= REDACT_MAX_DEPTH || seen.has(value)) return "[REDACTED_CYCLE]";
487
+ seen.add(value);
488
+ return value.map(
489
+ (item, index) => redactValue(String(index), item, seen, depth + 1)
490
+ );
491
+ }
492
+ if (isPlainObject2(value)) {
493
+ return redactObject(value, seen, depth + 1);
417
494
  }
418
495
  return value;
419
496
  }
420
- function redactObject(obj) {
497
+ function redactObject(obj, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
498
+ if (depth > REDACT_MAX_DEPTH) return { "[REDACTED]": "max_depth" };
499
+ if (seen.has(obj)) return { "[REDACTED]": "cycle" };
500
+ seen.add(obj);
421
501
  const out = {};
422
502
  for (const [key, value] of Object.entries(obj)) {
423
- out[key] = redactValue(key, value);
503
+ out[key] = redactValue(key, value, seen, depth);
424
504
  }
425
505
  return out;
426
506
  }
@@ -890,7 +970,18 @@ function generateSessionId() {
890
970
  return `ps_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
891
971
  }
892
972
  function createVideoPlayer(options) {
893
- assertNoSecretsInConfig(options);
973
+ assertNoSecretsInConfig({
974
+ videoId: options.videoId,
975
+ sourceUrl: options.sourceUrl,
976
+ player: options.player,
977
+ controls: options.controls,
978
+ theme: options.theme,
979
+ watermark: options.watermark,
980
+ streaming: options.streaming,
981
+ logging: options.logging,
982
+ debug: options.debug,
983
+ accessibility: options.accessibility
984
+ });
894
985
  let config = mergePlayerConfig({
895
986
  player: options.player,
896
987
  controls: options.controls,
@@ -1273,11 +1364,13 @@ function createVideoPlayer(options) {
1273
1364
  PlaybackSourceManager,
1274
1365
  PlayerErrorCode,
1275
1366
  RefreshManager,
1367
+ SECRET_SCAN_MAX_DEPTH,
1276
1368
  assertNoSecretsInConfig,
1277
1369
  createPlayerError,
1278
1370
  createVideoPlayer,
1279
1371
  getLiveEdgeTime,
1280
1372
  isAtLiveEdge,
1373
+ isPlainObject,
1281
1374
  mergePlayerConfig,
1282
1375
  redactObject,
1283
1376
  redactSensitive,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors/PlayerError.ts","../src/auth/AuthManager.ts","../src/config/defaults.ts","../src/events/EventEmitter.ts","../src/security/redaction.ts","../src/logging/Logger.ts","../src/auth/AuthParamsStore.ts","../src/playback/PlaybackSourceManager.ts","../src/playback/RefreshManager.ts","../src/playback/liveEdge.ts","../src/streaming/HlsEngine.ts","../src/player/createVideoPlayer.ts"],"sourcesContent":["export { createVideoPlayer, type VideoPlayer } from \"./player/createVideoPlayer\";\nexport {\n DEFAULT_PLAYER_CONFIG,\n DEFAULT_PLAYER_BEHAVIOR,\n DEFAULT_CONTROLS,\n DEFAULT_THEME,\n DEFAULT_WATERMARK,\n PLAYBACK_RATES,\n PACKAGE_VERSION,\n mergePlayerConfig,\n themeToCssVars,\n assertNoSecretsInConfig,\n} from \"./config/defaults\";\nexport {\n PlayerErrorCode,\n createPlayerError,\n redactSensitive,\n type PlayerError,\n} from \"./errors/PlayerError\";\nexport { AuthParamsStore } from \"./auth/AuthParamsStore\";\nexport { AuthManager } from \"./auth/AuthManager\";\nexport { PlaybackSourceManager } from \"./playback/PlaybackSourceManager\";\nexport { RefreshManager } from \"./playback/RefreshManager\";\nexport {\n DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS,\n getLiveEdgeTime,\n isAtLiveEdge,\n seekToLiveEdge,\n type LiveMediaSnapshot,\n type SeekToLiveResult,\n} from \"./playback/liveEdge\";\nexport { EventEmitter } from \"./events/EventEmitter\";\nexport { redactObject, redactValue } from \"./security/redaction\";\nexport type * from \"./types\";\n","export enum PlayerErrorCode {\n INVALID_CONFIGURATION = \"INVALID_CONFIGURATION\",\n AUTHENTICATION_FAILED = \"AUTHENTICATION_FAILED\",\n AUTH_TOKEN_REFRESH_FAILED = \"AUTH_TOKEN_REFRESH_FAILED\",\n TOKEN_EXPIRED = \"TOKEN_EXPIRED\",\n TOKEN_REFRESH_FAILED = \"TOKEN_REFRESH_FAILED\",\n SOURCE_RESOLUTION_FAILED = \"SOURCE_RESOLUTION_FAILED\",\n MANIFEST_LOAD_FAILED = \"MANIFEST_LOAD_FAILED\",\n SEGMENT_LOAD_FAILED = \"SEGMENT_LOAD_FAILED\",\n NETWORK_ERROR = \"NETWORK_ERROR\",\n PLAYBACK_ERROR = \"PLAYBACK_ERROR\",\n UNSUPPORTED_BROWSER = \"UNSUPPORTED_BROWSER\",\n AUTOPLAY_BLOCKED = \"AUTOPLAY_BLOCKED\",\n UNKNOWN = \"UNKNOWN\",\n}\n\nexport type PlayerError = {\n code: PlayerErrorCode;\n message: string;\n category: \"config\" | \"auth\" | \"network\" | \"playback\" | \"unknown\";\n fatal: boolean;\n retryable: boolean;\n timestamp: number;\n cause?: unknown;\n};\n\nexport function createPlayerError(\n code: PlayerErrorCode,\n message: string,\n options?: Partial<Omit<PlayerError, \"code\" | \"message\" | \"timestamp\">>,\n): PlayerError {\n return {\n code,\n message: redactSensitive(message),\n category: options?.category ?? \"unknown\",\n fatal: options?.fatal ?? true,\n retryable: options?.retryable ?? false,\n timestamp: Date.now(),\n cause: options?.cause,\n };\n}\n\nexport function redactSensitive(input: string): string {\n return input\n .replace(/(Bearer\\s+)[^\\s]+/gi, \"$1[REDACTED]\")\n .replace(/([?&](token|expires|signature|sig)=)[^&]+/gi, \"$1[REDACTED]\")\n .replace(/(Authorization:\\s*)[^\\s]+/gi, \"$1[REDACTED]\");\n}\n","import {\n createPlayerError,\n PlayerErrorCode,\n} from \"../errors/PlayerError\";\nimport type { Logger } from \"../logging/Logger\";\nimport type {\n AuthConfig,\n AuthToken,\n AuthTokenProviderContext,\n} from \"../types\";\n\n/**\n * Manages provider auth-token lifecycle (independent from signed playback URL).\n * Single-flight refresh; never stores clientSecret.\n * Unauthorized recoveries are bounded to prevent infinite 401 → refresh loops.\n */\nexport class AuthManager {\n private token: AuthToken | null = null;\n private inFlight: Promise<AuthToken> | null = null;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private destroyed = false;\n /** Consecutive unauthorized refresh attempts (reset on success). */\n private unauthorizedAttempts = 0;\n private readonly maxUnauthorizedRetries: number;\n\n constructor(\n private readonly auth: AuthConfig | undefined,\n private readonly refreshBeforeExpiryMs: number,\n private readonly logger: Logger,\n private readonly onRefreshed?: (token: AuthToken) => void,\n private readonly onError?: (message: string, retryable: boolean) => void,\n maxUnauthorizedRetries = 1,\n ) {\n this.maxUnauthorizedRetries = Math.max(0, maxUnauthorizedRetries);\n }\n\n getAccessToken(): string | null {\n return this.token?.accessToken ?? null;\n }\n\n getExpiresAt(): number | null {\n return this.token?.expiresAt ?? null;\n }\n\n async ensureToken(\n context: AuthTokenProviderContext,\n ): Promise<AuthToken | null> {\n if (!this.auth?.getToken) return null;\n if (this.destroyed) return null;\n\n if (\n this.token &&\n context.reason !== \"unauthorized\" &&\n context.reason !== \"manual\" &&\n this.token.expiresAt - Date.now() > this.refreshBeforeExpiryMs\n ) {\n return this.token;\n }\n\n return this.refresh(context);\n }\n\n async refresh(context: AuthTokenProviderContext): Promise<AuthToken> {\n if (!this.auth?.getToken) {\n throw createPlayerError(\n PlayerErrorCode.INVALID_CONFIGURATION,\n \"auth.getToken is required for authenticated playback\",\n { category: \"config\", fatal: true, retryable: false },\n );\n }\n\n if (context.reason === \"unauthorized\") {\n if (this.unauthorizedAttempts >= this.maxUnauthorizedRetries) {\n const message =\n \"Auth token refresh aborted: exceeded bounded unauthorized retry limit\";\n this.onError?.(message, false);\n throw createPlayerError(\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED,\n message,\n { category: \"auth\", fatal: true, retryable: false },\n );\n }\n this.unauthorizedAttempts += 1;\n }\n\n if (this.inFlight) return this.inFlight;\n\n this.inFlight = (async () => {\n try {\n const next = await this.auth!.getToken(context);\n if (\n !next?.accessToken ||\n typeof next.expiresAt !== \"number\" ||\n next.expiresAt <= 0\n ) {\n throw createPlayerError(\n PlayerErrorCode.AUTHENTICATION_FAILED,\n \"auth.getToken returned an invalid token payload\",\n { category: \"auth\", fatal: true, retryable: true },\n );\n }\n this.token = next;\n if (context.reason !== \"unauthorized\") {\n this.unauthorizedAttempts = 0;\n }\n this.scheduleProactiveRefresh();\n this.onRefreshed?.(next);\n this.logger.debug(\"Auth token refreshed\", {\n reason: context.reason,\n expiresAt: next.expiresAt,\n });\n return next;\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n (error as { code: string }).code ===\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED\n ) {\n throw error;\n }\n const message =\n error instanceof Error ? error.message : \"Auth token refresh failed\";\n const retryable = this.unauthorizedAttempts <= this.maxUnauthorizedRetries;\n this.onError?.(message, retryable);\n throw createPlayerError(\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED,\n message,\n { category: \"auth\", fatal: !retryable, retryable, cause: error },\n );\n } finally {\n this.inFlight = null;\n }\n })();\n\n return this.inFlight;\n }\n\n private scheduleProactiveRefresh(): void {\n if (this.timer) clearTimeout(this.timer);\n if (!this.token || this.destroyed) return;\n const delay = Math.max(\n 5_000,\n this.token.expiresAt - Date.now() - this.refreshBeforeExpiryMs,\n );\n this.timer = setTimeout(() => {\n void this.refresh({\n reason: \"expiring\",\n videoId: undefined,\n }).catch(() => {\n /* onError already notified */\n });\n }, delay);\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n this.token = null;\n this.inFlight = null;\n }\n}\n","import type {\n ControlsConfig,\n PlayerBehaviorConfig,\n PlayerConfig,\n ThemeConfig,\n WatermarkConfig,\n} from \"../types\";\n\nexport const PLAYBACK_RATES = [0.5, 0.75, 1, 1.25, 1.5, 2] as const;\n\nexport const PACKAGE_VERSION = \"0.1.0\";\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\nexport function assertNoSecretsInConfig(raw: unknown): void {\n if (!raw || typeof raw !== \"object\") return;\n const walk = (obj: Record<string, unknown>, path: string) => {\n for (const [key, value] of Object.entries(obj)) {\n const lower = key.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n if (FORBIDDEN_SECRET_KEYS.some((k) => lower.includes(k))) {\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 if (value && typeof value === \"object\" && !Array.isArray(value)) {\n walk(value as Record<string, unknown>, `${path}${key}.`);\n }\n }\n };\n walk(raw as Record<string, unknown>, \"\");\n}\n\nexport function mergePlayerConfig(\n partial?: 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): 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\nexport function redactValue(key: string, value: unknown): 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 (value && typeof value === \"object\" && !Array.isArray(value)) {\n return redactObject(value as Record<string, unknown>);\n }\n return value;\n}\n\nexport function redactObject(\n obj: Record<string, unknown>,\n): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n out[key] = redactValue(key, value);\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 assertNoSecretsInConfig(options);\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"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors/PlayerError.ts","../src/auth/AuthManager.ts","../src/config/defaults.ts","../src/events/EventEmitter.ts","../src/security/redaction.ts","../src/logging/Logger.ts","../src/auth/AuthParamsStore.ts","../src/playback/PlaybackSourceManager.ts","../src/playback/RefreshManager.ts","../src/playback/liveEdge.ts","../src/streaming/HlsEngine.ts","../src/player/createVideoPlayer.ts"],"sourcesContent":["export { createVideoPlayer, type VideoPlayer } from \"./player/createVideoPlayer\";\nexport {\n DEFAULT_PLAYER_CONFIG,\n DEFAULT_PLAYER_BEHAVIOR,\n DEFAULT_CONTROLS,\n DEFAULT_THEME,\n DEFAULT_WATERMARK,\n PLAYBACK_RATES,\n PACKAGE_VERSION,\n mergePlayerConfig,\n themeToCssVars,\n assertNoSecretsInConfig,\n isPlainObject,\n SECRET_SCAN_MAX_DEPTH,\n} from \"./config/defaults\";\nexport {\n PlayerErrorCode,\n createPlayerError,\n redactSensitive,\n type PlayerError,\n} from \"./errors/PlayerError\";\nexport { AuthParamsStore } from \"./auth/AuthParamsStore\";\nexport { AuthManager } from \"./auth/AuthManager\";\nexport { PlaybackSourceManager } from \"./playback/PlaybackSourceManager\";\nexport { RefreshManager } from \"./playback/RefreshManager\";\nexport {\n DEFAULT_LIVE_EDGE_TOLERANCE_SECONDS,\n getLiveEdgeTime,\n isAtLiveEdge,\n seekToLiveEdge,\n type LiveMediaSnapshot,\n type SeekToLiveResult,\n} from \"./playback/liveEdge\";\nexport { EventEmitter } from \"./events/EventEmitter\";\nexport { redactObject, redactValue } from \"./security/redaction\";\nexport type * from \"./types\";\n","export enum PlayerErrorCode {\n INVALID_CONFIGURATION = \"INVALID_CONFIGURATION\",\n AUTHENTICATION_FAILED = \"AUTHENTICATION_FAILED\",\n AUTH_TOKEN_REFRESH_FAILED = \"AUTH_TOKEN_REFRESH_FAILED\",\n TOKEN_EXPIRED = \"TOKEN_EXPIRED\",\n TOKEN_REFRESH_FAILED = \"TOKEN_REFRESH_FAILED\",\n SOURCE_RESOLUTION_FAILED = \"SOURCE_RESOLUTION_FAILED\",\n MANIFEST_LOAD_FAILED = \"MANIFEST_LOAD_FAILED\",\n SEGMENT_LOAD_FAILED = \"SEGMENT_LOAD_FAILED\",\n NETWORK_ERROR = \"NETWORK_ERROR\",\n PLAYBACK_ERROR = \"PLAYBACK_ERROR\",\n UNSUPPORTED_BROWSER = \"UNSUPPORTED_BROWSER\",\n AUTOPLAY_BLOCKED = \"AUTOPLAY_BLOCKED\",\n UNKNOWN = \"UNKNOWN\",\n}\n\nexport type PlayerError = {\n code: PlayerErrorCode;\n message: string;\n category: \"config\" | \"auth\" | \"network\" | \"playback\" | \"unknown\";\n fatal: boolean;\n retryable: boolean;\n timestamp: number;\n cause?: unknown;\n};\n\nexport function createPlayerError(\n code: PlayerErrorCode,\n message: string,\n options?: Partial<Omit<PlayerError, \"code\" | \"message\" | \"timestamp\">>,\n): PlayerError {\n return {\n code,\n message: redactSensitive(message),\n category: options?.category ?? \"unknown\",\n fatal: options?.fatal ?? true,\n retryable: options?.retryable ?? false,\n timestamp: Date.now(),\n cause: options?.cause,\n };\n}\n\nexport function redactSensitive(input: string): string {\n return input\n .replace(/(Bearer\\s+)[^\\s]+/gi, \"$1[REDACTED]\")\n .replace(/([?&](token|expires|signature|sig)=)[^&]+/gi, \"$1[REDACTED]\")\n .replace(/(Authorization:\\s*)[^\\s]+/gi, \"$1[REDACTED]\");\n}\n","import {\n createPlayerError,\n PlayerErrorCode,\n} from \"../errors/PlayerError\";\nimport type { Logger } from \"../logging/Logger\";\nimport type {\n AuthConfig,\n AuthToken,\n AuthTokenProviderContext,\n} from \"../types\";\n\n/**\n * Manages provider auth-token lifecycle (independent from signed playback URL).\n * Single-flight refresh; never stores clientSecret.\n * Unauthorized recoveries are bounded to prevent infinite 401 → refresh loops.\n */\nexport class AuthManager {\n private token: AuthToken | null = null;\n private inFlight: Promise<AuthToken> | null = null;\n private timer: ReturnType<typeof setTimeout> | null = null;\n private destroyed = false;\n /** Consecutive unauthorized refresh attempts (reset on success). */\n private unauthorizedAttempts = 0;\n private readonly maxUnauthorizedRetries: number;\n\n constructor(\n private readonly auth: AuthConfig | undefined,\n private readonly refreshBeforeExpiryMs: number,\n private readonly logger: Logger,\n private readonly onRefreshed?: (token: AuthToken) => void,\n private readonly onError?: (message: string, retryable: boolean) => void,\n maxUnauthorizedRetries = 1,\n ) {\n this.maxUnauthorizedRetries = Math.max(0, maxUnauthorizedRetries);\n }\n\n getAccessToken(): string | null {\n return this.token?.accessToken ?? null;\n }\n\n getExpiresAt(): number | null {\n return this.token?.expiresAt ?? null;\n }\n\n async ensureToken(\n context: AuthTokenProviderContext,\n ): Promise<AuthToken | null> {\n if (!this.auth?.getToken) return null;\n if (this.destroyed) return null;\n\n if (\n this.token &&\n context.reason !== \"unauthorized\" &&\n context.reason !== \"manual\" &&\n this.token.expiresAt - Date.now() > this.refreshBeforeExpiryMs\n ) {\n return this.token;\n }\n\n return this.refresh(context);\n }\n\n async refresh(context: AuthTokenProviderContext): Promise<AuthToken> {\n if (!this.auth?.getToken) {\n throw createPlayerError(\n PlayerErrorCode.INVALID_CONFIGURATION,\n \"auth.getToken is required for authenticated playback\",\n { category: \"config\", fatal: true, retryable: false },\n );\n }\n\n if (context.reason === \"unauthorized\") {\n if (this.unauthorizedAttempts >= this.maxUnauthorizedRetries) {\n const message =\n \"Auth token refresh aborted: exceeded bounded unauthorized retry limit\";\n this.onError?.(message, false);\n throw createPlayerError(\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED,\n message,\n { category: \"auth\", fatal: true, retryable: false },\n );\n }\n this.unauthorizedAttempts += 1;\n }\n\n if (this.inFlight) return this.inFlight;\n\n this.inFlight = (async () => {\n try {\n const next = await this.auth!.getToken(context);\n if (\n !next?.accessToken ||\n typeof next.expiresAt !== \"number\" ||\n next.expiresAt <= 0\n ) {\n throw createPlayerError(\n PlayerErrorCode.AUTHENTICATION_FAILED,\n \"auth.getToken returned an invalid token payload\",\n { category: \"auth\", fatal: true, retryable: true },\n );\n }\n this.token = next;\n if (context.reason !== \"unauthorized\") {\n this.unauthorizedAttempts = 0;\n }\n this.scheduleProactiveRefresh();\n this.onRefreshed?.(next);\n this.logger.debug(\"Auth token refreshed\", {\n reason: context.reason,\n expiresAt: next.expiresAt,\n });\n return next;\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n (error as { code: string }).code ===\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED\n ) {\n throw error;\n }\n const message =\n error instanceof Error ? error.message : \"Auth token refresh failed\";\n const retryable = this.unauthorizedAttempts <= this.maxUnauthorizedRetries;\n this.onError?.(message, retryable);\n throw createPlayerError(\n PlayerErrorCode.AUTH_TOKEN_REFRESH_FAILED,\n message,\n { category: \"auth\", fatal: !retryable, retryable, cause: error },\n );\n } finally {\n this.inFlight = null;\n }\n })();\n\n return this.inFlight;\n }\n\n private scheduleProactiveRefresh(): void {\n if (this.timer) clearTimeout(this.timer);\n if (!this.token || this.destroyed) return;\n const delay = Math.max(\n 5_000,\n this.token.expiresAt - Date.now() - this.refreshBeforeExpiryMs,\n );\n this.timer = setTimeout(() => {\n void this.refresh({\n reason: \"expiring\",\n videoId: undefined,\n }).catch(() => {\n /* onError already notified */\n });\n }, delay);\n }\n\n destroy(): void {\n this.destroyed = true;\n if (this.timer) clearTimeout(this.timer);\n this.timer = null;\n this.token = null;\n this.inFlight = null;\n }\n}\n","import type {\n ControlsConfig,\n PlayerBehaviorConfig,\n PlayerConfig,\n ThemeConfig,\n WatermarkConfig,\n} from \"../types\";\n\nexport const PLAYBACK_RATES = [0.5, 0.75, 1, 1.25, 1.5, 2] as const;\n\nexport const PACKAGE_VERSION = \"0.1.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"]}