{"version":3,"sources":["../../../src/components/features/captions-url.ts"],"names":[],"mappings":";;;AAgBO,SAAS,cAAA,CACd,UAAA,EACA,QAAA,EACA,UAAA,EACA,OAAA,EAQoB;AACpB,EAAA,IAAI,CAAC,YAAY,OAAO,MAAA;AACxB,EAAA,MAAM,IAAA,GAAO,CAAA,EAAG,UAAA,CAAW,MAAM,CAAA,CAAA,EAAI,UAAA,CAAW,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,CAAA;AAC9E,EAAA,MAAM,UAAU,OAAA,EAAS,OAAA,GAAU,CAAA,SAAA,EAAY,OAAA,CAAQ,OAAO,CAAA,CAAA,GAAK,EAAA;AACnE,EAAA,OAAO,CAAA,EAAG,qBAAqB,CAAA,CAAA,EAAI,UAAU,IAAI,QAAQ,CAAA,GAAA,EAAM,IAAI,CAAA,EAAG,OAAO,CAAA,CAAA;AAC/E;AAaA,IAAM,qBAAA,GAAwB,eAAA;AAE9B,SAAS,oBAAoB,SAAA,EAA8C;AACzE,EAAA,OAAO,WAAW,iBAAA,IAAqB,qBAAA;AACzC;AAKO,SAAS,iBAAA,CACd,WACA,GAAA,EACY;AACZ,EAAA,IAAI,CAAC,OAAO,CAAC,GAAA,CAAI,WAAW,CAAA,EAAG,qBAAqB,CAAA,CAAA,CAAG,CAAA,EAAG,OAAO,GAAA;AACjE,EAAA,MAAM,IAAA,GAAO,oBAAoB,SAAS,CAAA;AAC1C,EAAA,IAAI,IAAA,KAAS,uBAAuB,OAAO,GAAA;AAC3C,EAAA,OAAO,GAAG,IAAI,CAAA,EAAG,IAAI,KAAA,CAAM,qBAAA,CAAsB,MAAM,CAAC,CAAA,CAAA;AAC1D;AAQO,SAAS,gBAAA,CACd,SAAA,EACA,UAAA,EACA,QAAA,EACA,YACA,OAAA,EACoB;AACpB,EAAA,MAAM,GAAA,GAAM,cAAA,CAAe,UAAA,EAAY,QAAA,EAAU,YAAY,OAAO,CAAA;AACpE,EAAA,OAAO,GAAA,GAAO,iBAAA,CAAkB,SAAA,EAAW,GAAG,CAAA,GAAe,MAAA;AAC/D;AAwBO,SAAS,oBAAA,CACd,SAAA,EACA,UAAA,EACA,MAAA,EACmB;AACnB,EAAA,IAAI,CAAC,MAAA,EAAQ,OAAO,EAAC;AACrB,EAAA,OAAO;AAAA,IACL,aAAa,gBAAA,CAAiB,SAAA,EAAW,YAAY,MAAA,CAAO,EAAA,EAAI,OAAO,WAAW,CAAA;AAAA,IAClF,sBAAsB,gBAAA,CAAiB,SAAA,EAAW,YAAY,MAAA,CAAO,EAAA,EAAI,OAAO,qBAAA,EAAuB;AAAA,MACrG,OAAA,EAAS;AAAA,KACV;AAAA,GACH;AACF;AAWO,SAAS,wBAAA,CACd,SAAA,EACA,UAAA,EACA,QAAA,EAC6B;AAC7B,EAAA,MAAM,IAAA,GAAO,oBAAoB,SAAS,CAAA;AAC1C,EAAA,OAAO;AAAA,IACL,aAAa,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,UAAU,IAAI,QAAQ,CAAA,CAAA;AAAA,IAC9C,sBAAsB,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,UAAU,IAAI,QAAQ,CAAA,kBAAA;AAAA,GACzD;AACF;AAQO,SAAS,6BAA6B,OAAA,EAAyB;AACpE,EAAA,OAAO,OAAA,KAAY,YAAY,iBAAA,GAAoB,OAAA;AACrD","file":"captions-url.cjs","sourcesContent":["/**\n * Build the captions API URL for a video entity.\n *\n * Returns the HTTPS URL to the `/api/captions/[entityType]/[entityId]` endpoint\n * which serves VTT content for iOS native fullscreen subtitles.\n * Returns undefined if entity has no srt_content.\n *\n * Cache-busting hash derived from the srt_content length so iOS Safari\n * fetches fresh VTT when subtitles are regenerated (Safari aggressively caches\n * <track> src URLs even with short Cache-Control max-age).\n *\n * Lifted from hub `lib/utils/captions-url.ts`. The hub's hard-coded\n * `VideoEnabledEntityType` enum is widened to `string` here — embedders\n * pass whatever entity-type discriminator their reverse-proxied\n * `/api/captions/...` route expects.\n */\nexport function getCaptionsUrl(\n  entityType: string,\n  entityId: string | number,\n  srtContent?: string | null,\n  options?: {\n    /**\n     * Which SRT column the endpoint should serve. `'highlight'` targets the\n     * entity's highlight_srt_content (AI highlight reel captions); omitted\n     * means the main video's srt_content.\n     */\n    variant?: 'highlight'\n  },\n): string | undefined {\n  if (!srtContent) return undefined\n  const hash = `${srtContent.length}-${srtContent.slice(0, 8).replace(/\\s/g, '')}`\n  const variant = options?.variant ? `&variant=${options.variant}` : ''\n  return `${DEFAULT_CAPTIONS_PATH}/${entityType}/${entityId}?v=${hash}${variant}`\n}\n\n/** The slice of `ChatRuntime.endpoints` this module needs. */\nexport interface CaptionsEndpoints {\n  /** Base URL prefix for the captions route (plain path base, no query\n   *  params) — e.g. `/content/api/captions` in a proxied embedder. Unset ⇒\n   *  the same-origin relative default `/api/captions` (the hub). Wired by\n   *  hosts exactly like every other endpoint on `ChatRuntime.endpoints`. */\n  captionsUrlPrefix?: string\n}\n\n/** Same-origin default — for hosts that serve the route themselves (the hub).\n *  Cross-origin embedders set `endpoints.captionsUrlPrefix` instead. */\nconst DEFAULT_CAPTIONS_PATH = '/api/captions'\n\nfunction resolveCaptionsBase(endpoints?: CaptionsEndpoints | null): string {\n  return endpoints?.captionsUrlPrefix || DEFAULT_CAPTIONS_PATH\n}\n\n/** Rebase an already-built relative `/api/captions/...` URL (e.g. one the hub\n *  API computed server-side) onto the host's captions base. Same-origin hosts\n *  (base = default) get the URL back untouched. Non-captions URLs pass through. */\nexport function rebaseCaptionsUrl<T extends string | null | undefined>(\n  endpoints: CaptionsEndpoints | null | undefined,\n  url: T,\n): T | string {\n  if (!url || !url.startsWith(`${DEFAULT_CAPTIONS_PATH}/`)) return url\n  const base = resolveCaptionsBase(endpoints)\n  if (base === DEFAULT_CAPTIONS_PATH) return url\n  return `${base}${url.slice(DEFAULT_CAPTIONS_PATH.length)}`\n}\n\n/**\n * The endpoints-aware entry point — `getCaptionsUrl` based on\n * `endpoints.captionsUrlPrefix` (consumers hand over `runtime?.endpoints` and\n * nothing else). Hub/same-origin hosts leave the prefix unset and resolve to\n * the relative default.\n */\nexport function buildCaptionsUrl(\n  endpoints: CaptionsEndpoints | null | undefined,\n  entityType: string,\n  entityId: string | number,\n  srtContent?: string | null,\n  options?: { variant?: 'highlight' },\n): string | undefined {\n  const rel = getCaptionsUrl(entityType, entityId, srtContent, options)\n  return rel ? (rebaseCaptionsUrl(endpoints, rel) as string) : undefined\n}\n\n/** The two SRT columns every video entity carries — main video + highlight\n *  reel. The caption URL shape is fully generic over these\n *  (`?variant=highlight` is the only difference), so consumers never derive\n *  the two URLs by hand. */\nexport interface CaptionSrtFields {\n  id: string | number\n  srt_content?: string | null\n  highlight_srt_content?: string | null\n}\n\nexport interface EntityCaptionUrls {\n  captionsUrl?: string\n  highlightCaptionsUrl?: string\n}\n\n/**\n * THE one-stop caption derivation for a video entity: hand over the runtime\n * `endpoints` + the entity row and get both `<track>` URLs back, base-resolved\n * for the host (relative on the hub, proxied in embedders). Every view\n * (release, onboarding guide, webinar, podcast, …) calls this once instead of\n * hand-building main + highlight URLs separately.\n */\nexport function getEntityCaptionUrls(\n  endpoints: CaptionsEndpoints | null | undefined,\n  entityType: string,\n  entity: CaptionSrtFields | null | undefined,\n): EntityCaptionUrls {\n  if (!entity) return {}\n  return {\n    captionsUrl: buildCaptionsUrl(endpoints, entityType, entity.id, entity.srt_content),\n    highlightCaptionsUrl: buildCaptionsUrl(endpoints, entityType, entity.id, entity.highlight_srt_content, {\n      variant: 'highlight',\n    }),\n  }\n}\n\n/**\n * Identity-only variant of `getEntityCaptionUrls` — for surfaces that know the\n * entity's type + id but NOT its SRT columns (chat cards, whose hydration rows\n * deliberately exclude the heavy SRT content). The `/api/captions` route is\n * addressed purely by `<entityType>/<entityId>`, so the URLs derive from\n * identity alone; a video without subtitles costs one silent 404 `<track>`\n * fetch. No `?v=` cache-buster (no content to hash) — the route's own\n * Cache-Control governs freshness.\n */\nexport function getEntityCaptionUrlsById(\n  endpoints: CaptionsEndpoints | null | undefined,\n  entityType: string,\n  entityId: string | number,\n): Required<EntityCaptionUrls> {\n  const base = resolveCaptionsBase(endpoints)\n  return {\n    captionsUrl: `${base}/${entityType}/${entityId}`,\n    highlightCaptionsUrl: `${base}/${entityType}/${entityId}?variant=highlight`,\n  }\n}\n\n/**\n * Chat docType → captions-route entity type. Chat documentTypes equal the\n * captions entity types for every video-bearing type except podcast\n * (`podcast` vs `podcast_episode`). Kept here (not per-card) so the alias\n * exists exactly once.\n */\nexport function captionsEntityTypeForDocType(docType: string): string {\n  return docType === 'podcast' ? 'podcast_episode' : docType\n}\n"]}