prismcast 1.10.3 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (674) hide show
  1. package/dist/app.d.ts +1 -0
  2. package/dist/app.d.ts.map +1 -0
  3. package/dist/app.js +103 -50
  4. package/dist/app.js.map +1 -1
  5. package/dist/browser/blockedPage.d.ts +80 -0
  6. package/dist/browser/blockedPage.d.ts.map +1 -0
  7. package/dist/browser/blockedPage.js +209 -0
  8. package/dist/browser/blockedPage.js.map +1 -0
  9. package/dist/browser/browserSupervisor.d.ts +80 -0
  10. package/dist/browser/browserSupervisor.d.ts.map +1 -0
  11. package/dist/browser/browserSupervisor.js +186 -0
  12. package/dist/browser/browserSupervisor.js.map +1 -0
  13. package/dist/browser/cdp.d.ts +1 -0
  14. package/dist/browser/cdp.d.ts.map +1 -0
  15. package/dist/browser/cdp.js +6 -5
  16. package/dist/browser/cdp.js.map +1 -1
  17. package/dist/browser/channelSelection.d.ts +45 -14
  18. package/dist/browser/channelSelection.d.ts.map +1 -0
  19. package/dist/browser/channelSelection.js +81 -18
  20. package/dist/browser/channelSelection.js.map +1 -1
  21. package/dist/browser/consent.d.ts +152 -0
  22. package/dist/browser/consent.d.ts.map +1 -0
  23. package/dist/browser/consent.js +418 -0
  24. package/dist/browser/consent.js.map +1 -0
  25. package/dist/browser/display.d.ts +1 -0
  26. package/dist/browser/display.d.ts.map +1 -0
  27. package/dist/browser/hlsPlaylistObserver.d.ts +23 -6
  28. package/dist/browser/hlsPlaylistObserver.d.ts.map +1 -0
  29. package/dist/browser/hlsPlaylistObserver.js +27 -8
  30. package/dist/browser/hlsPlaylistObserver.js.map +1 -1
  31. package/dist/browser/index.d.ts +44 -27
  32. package/dist/browser/index.d.ts.map +1 -0
  33. package/dist/browser/index.js +427 -244
  34. package/dist/browser/index.js.map +1 -1
  35. package/dist/browser/launchGovernor.d.ts +89 -0
  36. package/dist/browser/launchGovernor.d.ts.map +1 -0
  37. package/dist/browser/launchGovernor.js +96 -0
  38. package/dist/browser/launchGovernor.js.map +1 -0
  39. package/dist/browser/login.d.ts +10 -2
  40. package/dist/browser/login.d.ts.map +1 -0
  41. package/dist/browser/login.js +36 -5
  42. package/dist/browser/login.js.map +1 -1
  43. package/dist/browser/manifestInterceptor.d.ts +88 -35
  44. package/dist/browser/manifestInterceptor.d.ts.map +1 -0
  45. package/dist/browser/manifestInterceptor.js +165 -77
  46. package/dist/browser/manifestInterceptor.js.map +1 -1
  47. package/dist/browser/pageStaleness.d.ts +30 -0
  48. package/dist/browser/pageStaleness.d.ts.map +1 -0
  49. package/dist/browser/pageStaleness.js +76 -0
  50. package/dist/browser/pageStaleness.js.map +1 -0
  51. package/dist/browser/precaching.d.ts +95 -3
  52. package/dist/browser/precaching.d.ts.map +1 -0
  53. package/dist/browser/precaching.js +499 -65
  54. package/dist/browser/precaching.js.map +1 -1
  55. package/dist/browser/tabNetworkObserver.d.ts +2 -1
  56. package/dist/browser/tabNetworkObserver.d.ts.map +1 -0
  57. package/dist/browser/tabNetworkObserver.js +7 -3
  58. package/dist/browser/tabNetworkObserver.js.map +1 -1
  59. package/dist/browser/tuning/cache.d.ts +61 -0
  60. package/dist/browser/tuning/cache.d.ts.map +1 -0
  61. package/dist/browser/tuning/cache.js +62 -0
  62. package/dist/browser/tuning/cache.js.map +1 -0
  63. package/dist/browser/tuning/comcastPolymer.d.ts +3 -2
  64. package/dist/browser/tuning/comcastPolymer.d.ts.map +1 -0
  65. package/dist/browser/tuning/comcastPolymer.js +79 -102
  66. package/dist/browser/tuning/comcastPolymer.js.map +1 -1
  67. package/dist/browser/tuning/cox.d.ts +1 -0
  68. package/dist/browser/tuning/cox.d.ts.map +1 -0
  69. package/dist/browser/tuning/directv.d.ts +1 -0
  70. package/dist/browser/tuning/directv.d.ts.map +1 -0
  71. package/dist/browser/tuning/directv.js +52 -46
  72. package/dist/browser/tuning/directv.js.map +1 -1
  73. package/dist/browser/tuning/fox.d.ts +1 -0
  74. package/dist/browser/tuning/fox.d.ts.map +1 -0
  75. package/dist/browser/tuning/fox.js +13 -12
  76. package/dist/browser/tuning/fox.js.map +1 -1
  77. package/dist/browser/tuning/gridSearch.d.ts +68 -0
  78. package/dist/browser/tuning/gridSearch.d.ts.map +1 -0
  79. package/dist/browser/tuning/gridSearch.js +85 -0
  80. package/dist/browser/tuning/gridSearch.js.map +1 -0
  81. package/dist/browser/tuning/hbo.d.ts +1 -0
  82. package/dist/browser/tuning/hbo.d.ts.map +1 -0
  83. package/dist/browser/tuning/hbo.js +73 -45
  84. package/dist/browser/tuning/hbo.js.map +1 -1
  85. package/dist/browser/tuning/hulu.d.ts +1 -0
  86. package/dist/browser/tuning/hulu.d.ts.map +1 -0
  87. package/dist/browser/tuning/hulu.js +128 -173
  88. package/dist/browser/tuning/hulu.js.map +1 -1
  89. package/dist/browser/tuning/shared.d.ts +75 -5
  90. package/dist/browser/tuning/shared.d.ts.map +1 -0
  91. package/dist/browser/tuning/shared.js +216 -6
  92. package/dist/browser/tuning/shared.js.map +1 -1
  93. package/dist/browser/tuning/sling.d.ts +1 -0
  94. package/dist/browser/tuning/sling.d.ts.map +1 -0
  95. package/dist/browser/tuning/sling.js +105 -126
  96. package/dist/browser/tuning/sling.js.map +1 -1
  97. package/dist/browser/tuning/spectrum.d.ts +1 -0
  98. package/dist/browser/tuning/spectrum.d.ts.map +1 -0
  99. package/dist/browser/tuning/spectrum.js +80 -125
  100. package/dist/browser/tuning/spectrum.js.map +1 -1
  101. package/dist/browser/tuning/thumbnailRow.d.ts +1 -0
  102. package/dist/browser/tuning/thumbnailRow.d.ts.map +1 -0
  103. package/dist/browser/tuning/thumbnailRow.js +8 -2
  104. package/dist/browser/tuning/thumbnailRow.js.map +1 -1
  105. package/dist/browser/tuning/tileClick.d.ts +1 -0
  106. package/dist/browser/tuning/tileClick.d.ts.map +1 -0
  107. package/dist/browser/tuning/tileClick.js +3 -2
  108. package/dist/browser/tuning/tileClick.js.map +1 -1
  109. package/dist/browser/tuning/xfinity.d.ts +1 -0
  110. package/dist/browser/tuning/xfinity.d.ts.map +1 -0
  111. package/dist/browser/tuning/youtubeTv.d.ts +1 -0
  112. package/dist/browser/tuning/youtubeTv.d.ts.map +1 -0
  113. package/dist/browser/tuning/youtubeTv.js +74 -127
  114. package/dist/browser/tuning/youtubeTv.js.map +1 -1
  115. package/dist/browser/video.d.ts +54 -14
  116. package/dist/browser/video.d.ts.map +1 -0
  117. package/dist/browser/video.js +296 -138
  118. package/dist/browser/video.js.map +1 -1
  119. package/dist/channels/index.d.ts +1 -0
  120. package/dist/channels/index.d.ts.map +1 -0
  121. package/dist/channels/index.js +12 -9
  122. package/dist/channels/index.js.map +1 -1
  123. package/dist/config/channelForm.d.ts +15 -1
  124. package/dist/config/channelForm.d.ts.map +1 -0
  125. package/dist/config/channelForm.js +28 -12
  126. package/dist/config/channelForm.js.map +1 -1
  127. package/dist/config/consistencyProbe.d.ts +1 -0
  128. package/dist/config/consistencyProbe.d.ts.map +1 -0
  129. package/dist/config/consistencyProbe.js +15 -11
  130. package/dist/config/consistencyProbe.js.map +1 -1
  131. package/dist/config/health.d.ts +41 -8
  132. package/dist/config/health.d.ts.map +1 -0
  133. package/dist/config/health.js +189 -38
  134. package/dist/config/health.js.map +1 -1
  135. package/dist/config/index.d.ts +55 -3
  136. package/dist/config/index.d.ts.map +1 -0
  137. package/dist/config/index.js +320 -69
  138. package/dist/config/index.js.map +1 -1
  139. package/dist/config/paths.d.ts +7 -1
  140. package/dist/config/paths.d.ts.map +1 -0
  141. package/dist/config/paths.js +8 -1
  142. package/dist/config/paths.js.map +1 -1
  143. package/dist/config/persistence.context.d.ts +1 -0
  144. package/dist/config/persistence.context.d.ts.map +1 -0
  145. package/dist/config/persistence.d.ts +13 -10
  146. package/dist/config/persistence.d.ts.map +1 -0
  147. package/dist/config/persistence.js +40 -21
  148. package/dist/config/persistence.js.map +1 -1
  149. package/dist/config/presets.d.ts +1 -0
  150. package/dist/config/presets.d.ts.map +1 -0
  151. package/dist/config/profiles.d.ts +21 -14
  152. package/dist/config/profiles.d.ts.map +1 -0
  153. package/dist/config/profiles.js +77 -43
  154. package/dist/config/profiles.js.map +1 -1
  155. package/dist/config/providerLineups.d.ts +47 -0
  156. package/dist/config/providerLineups.d.ts.map +1 -0
  157. package/dist/config/providerLineups.js +137 -0
  158. package/dist/config/providerLineups.js.map +1 -0
  159. package/dist/config/reactivity.d.ts +84 -0
  160. package/dist/config/reactivity.d.ts.map +1 -0
  161. package/dist/config/reactivity.js +226 -0
  162. package/dist/config/reactivity.js.map +1 -0
  163. package/dist/config/servicePacks.d.ts +18 -2
  164. package/dist/config/servicePacks.d.ts.map +1 -0
  165. package/dist/config/servicePacks.js +53 -11
  166. package/dist/config/servicePacks.js.map +1 -1
  167. package/dist/config/services.d.ts +16 -10
  168. package/dist/config/services.d.ts.map +1 -0
  169. package/dist/config/services.js +27 -16
  170. package/dist/config/services.js.map +1 -1
  171. package/dist/config/sites.d.ts +4 -2
  172. package/dist/config/sites.d.ts.map +1 -0
  173. package/dist/config/sites.js +9 -5
  174. package/dist/config/sites.js.map +1 -1
  175. package/dist/config/userChannels.d.ts +23 -18
  176. package/dist/config/userChannels.d.ts.map +1 -0
  177. package/dist/config/userChannels.js +45 -34
  178. package/dist/config/userChannels.js.map +1 -1
  179. package/dist/config/userConfig.d.ts +14 -9
  180. package/dist/config/userConfig.d.ts.map +1 -0
  181. package/dist/config/userConfig.js +87 -25
  182. package/dist/config/userConfig.js.map +1 -1
  183. package/dist/config/userProfiles.d.ts +8 -4
  184. package/dist/config/userProfiles.d.ts.map +1 -0
  185. package/dist/config/userProfiles.js +48 -23
  186. package/dist/config/userProfiles.js.map +1 -1
  187. package/dist/hdhr/channelMap.d.ts +1 -0
  188. package/dist/hdhr/channelMap.d.ts.map +1 -0
  189. package/dist/hdhr/deviceId.d.ts +1 -0
  190. package/dist/hdhr/deviceId.d.ts.map +1 -0
  191. package/dist/hdhr/discover.d.ts +1 -0
  192. package/dist/hdhr/discover.d.ts.map +1 -0
  193. package/dist/hdhr/discover.js +48 -47
  194. package/dist/hdhr/discover.js.map +1 -1
  195. package/dist/hdhr/getHandlers.d.ts +29 -0
  196. package/dist/hdhr/getHandlers.d.ts.map +1 -0
  197. package/dist/hdhr/getHandlers.js +196 -0
  198. package/dist/hdhr/getHandlers.js.map +1 -0
  199. package/dist/hdhr/identity.d.ts +36 -0
  200. package/dist/hdhr/identity.d.ts.map +1 -0
  201. package/dist/hdhr/identity.js +51 -0
  202. package/dist/hdhr/identity.js.map +1 -0
  203. package/dist/hdhr/index.d.ts +22 -4
  204. package/dist/hdhr/index.d.ts.map +1 -0
  205. package/dist/hdhr/index.js +229 -54
  206. package/dist/hdhr/index.js.map +1 -1
  207. package/dist/hdhr/protocol.d.ts +75 -0
  208. package/dist/hdhr/protocol.d.ts.map +1 -0
  209. package/dist/hdhr/protocol.js +264 -0
  210. package/dist/hdhr/protocol.js.map +1 -0
  211. package/dist/hdhr/tunerState.d.ts +24 -0
  212. package/dist/hdhr/tunerState.d.ts.map +1 -0
  213. package/dist/hdhr/tunerState.js +67 -0
  214. package/dist/hdhr/tunerState.js.map +1 -0
  215. package/dist/hdhr/udp.d.ts +43 -0
  216. package/dist/hdhr/udp.d.ts.map +1 -0
  217. package/dist/hdhr/udp.js +277 -0
  218. package/dist/hdhr/udp.js.map +1 -0
  219. package/dist/identity.d.ts +1 -0
  220. package/dist/identity.d.ts.map +1 -0
  221. package/dist/identity.js +13 -11
  222. package/dist/identity.js.map +1 -1
  223. package/dist/index.d.ts +1 -0
  224. package/dist/index.d.ts.map +1 -0
  225. package/dist/index.js +4 -3
  226. package/dist/index.js.map +1 -1
  227. package/dist/native/codecInference.d.ts +1 -0
  228. package/dist/native/codecInference.d.ts.map +1 -0
  229. package/dist/native/codecInference.js +50 -5
  230. package/dist/native/codecInference.js.map +1 -1
  231. package/dist/native/decrypt.d.ts +6 -2
  232. package/dist/native/decrypt.d.ts.map +1 -0
  233. package/dist/native/decrypt.js +15 -8
  234. package/dist/native/decrypt.js.map +1 -1
  235. package/dist/native/index.d.ts +39 -16
  236. package/dist/native/index.d.ts.map +1 -0
  237. package/dist/native/index.js +273 -103
  238. package/dist/native/index.js.map +1 -1
  239. package/dist/native/probe.d.ts +114 -18
  240. package/dist/native/probe.d.ts.map +1 -0
  241. package/dist/native/probe.js +452 -115
  242. package/dist/native/probe.js.map +1 -1
  243. package/dist/native/proxy.d.ts +56 -1
  244. package/dist/native/proxy.d.ts.map +1 -0
  245. package/dist/native/proxy.js +604 -161
  246. package/dist/native/proxy.js.map +1 -1
  247. package/dist/native/tokenExpiry.d.ts +1 -0
  248. package/dist/native/tokenExpiry.d.ts.map +1 -0
  249. package/dist/native/tokenExpiry.js +1 -1
  250. package/dist/routes/assets.d.ts +1 -0
  251. package/dist/routes/assets.d.ts.map +1 -0
  252. package/dist/routes/assets.js +4 -2
  253. package/dist/routes/assets.js.map +1 -1
  254. package/dist/routes/auth.d.ts +1 -0
  255. package/dist/routes/auth.d.ts.map +1 -0
  256. package/dist/routes/auth.js +0 -1
  257. package/dist/routes/auth.js.map +1 -1
  258. package/dist/routes/cdp.d.ts +5 -5
  259. package/dist/routes/cdp.d.ts.map +1 -0
  260. package/dist/routes/cdp.js +59 -20
  261. package/dist/routes/cdp.js.map +1 -1
  262. package/dist/routes/channels.d.ts +1 -0
  263. package/dist/routes/channels.d.ts.map +1 -0
  264. package/dist/routes/channels.js +2 -1
  265. package/dist/routes/channels.js.map +1 -1
  266. package/dist/routes/clientActions.d.ts +4 -3
  267. package/dist/routes/clientActions.d.ts.map +1 -0
  268. package/dist/routes/components.d.ts +1 -0
  269. package/dist/routes/components.d.ts.map +1 -0
  270. package/dist/routes/components.js +2 -2
  271. package/dist/routes/components.js.map +1 -1
  272. package/dist/routes/config/channels/endpoints/browse.d.ts +1 -0
  273. package/dist/routes/config/channels/endpoints/browse.d.ts.map +1 -0
  274. package/dist/routes/config/channels/endpoints/browse.js +23 -10
  275. package/dist/routes/config/channels/endpoints/browse.js.map +1 -1
  276. package/dist/routes/config/channels/endpoints/bulk.d.ts +1 -0
  277. package/dist/routes/config/channels/endpoints/bulk.d.ts.map +1 -0
  278. package/dist/routes/config/channels/endpoints/bulk.js +5 -3
  279. package/dist/routes/config/channels/endpoints/bulk.js.map +1 -1
  280. package/dist/routes/config/channels/endpoints/crud.d.ts +1 -0
  281. package/dist/routes/config/channels/endpoints/crud.d.ts.map +1 -0
  282. package/dist/routes/config/channels/endpoints/crud.js +49 -22
  283. package/dist/routes/config/channels/endpoints/crud.js.map +1 -1
  284. package/dist/routes/config/channels/endpoints/importExport.d.ts +1 -0
  285. package/dist/routes/config/channels/endpoints/importExport.d.ts.map +1 -0
  286. package/dist/routes/config/channels/endpoints/importExport.js +6 -3
  287. package/dist/routes/config/channels/endpoints/importExport.js.map +1 -1
  288. package/dist/routes/config/channels/endpoints/predefined.d.ts +1 -0
  289. package/dist/routes/config/channels/endpoints/predefined.d.ts.map +1 -0
  290. package/dist/routes/config/channels/endpoints/prefs.d.ts +1 -0
  291. package/dist/routes/config/channels/endpoints/prefs.d.ts.map +1 -0
  292. package/dist/routes/config/channels/endpoints/prefs.js +2 -1
  293. package/dist/routes/config/channels/endpoints/prefs.js.map +1 -1
  294. package/dist/routes/config/channels/endpoints/service.d.ts +2 -1
  295. package/dist/routes/config/channels/endpoints/service.d.ts.map +1 -0
  296. package/dist/routes/config/channels/endpoints/service.js +3 -1
  297. package/dist/routes/config/channels/endpoints/service.js.map +1 -1
  298. package/dist/routes/config/channels/endpoints/tags.d.ts +1 -0
  299. package/dist/routes/config/channels/endpoints/tags.d.ts.map +1 -0
  300. package/dist/routes/config/channels/endpoints/tags.js +13 -7
  301. package/dist/routes/config/channels/endpoints/tags.js.map +1 -1
  302. package/dist/routes/config/channels/healthBridge.d.ts +1 -0
  303. package/dist/routes/config/channels/healthBridge.d.ts.map +1 -0
  304. package/dist/routes/config/channels/healthBridge.js +2 -2
  305. package/dist/routes/config/channels/http/handler.d.ts +1 -0
  306. package/dist/routes/config/channels/http/handler.d.ts.map +1 -0
  307. package/dist/routes/config/channels/http/playlistHint.d.ts +2 -1
  308. package/dist/routes/config/channels/http/playlistHint.d.ts.map +1 -0
  309. package/dist/routes/config/channels/http/playlistHint.js +16 -2
  310. package/dist/routes/config/channels/http/playlistHint.js.map +1 -1
  311. package/dist/routes/config/channels/http/serviceWarning.d.ts +4 -2
  312. package/dist/routes/config/channels/http/serviceWarning.d.ts.map +1 -0
  313. package/dist/routes/config/channels/http/serviceWarning.js +3 -2
  314. package/dist/routes/config/channels/http/serviceWarning.js.map +1 -1
  315. package/dist/routes/config/channels/index.d.ts +1 -0
  316. package/dist/routes/config/channels/index.d.ts.map +1 -0
  317. package/dist/routes/config/channels/setup.d.ts +1 -0
  318. package/dist/routes/config/channels/setup.d.ts.map +1 -0
  319. package/dist/routes/config/channels/table.d.ts +3 -3
  320. package/dist/routes/config/channels/table.d.ts.map +1 -0
  321. package/dist/routes/config/channels/table.js +55 -27
  322. package/dist/routes/config/channels/table.js.map +1 -1
  323. package/dist/routes/config/http/envelope.d.ts +1 -0
  324. package/dist/routes/config/http/envelope.d.ts.map +1 -0
  325. package/dist/routes/config/index.d.ts +35 -3
  326. package/dist/routes/config/index.d.ts.map +1 -0
  327. package/dist/routes/config/index.js +51 -2
  328. package/dist/routes/config/index.js.map +1 -1
  329. package/dist/routes/config/services.d.ts +5 -4
  330. package/dist/routes/config/services.d.ts.map +1 -0
  331. package/dist/routes/config/services.js +35 -24
  332. package/dist/routes/config/services.js.map +1 -1
  333. package/dist/routes/config/settings.d.ts +1 -0
  334. package/dist/routes/config/settings.d.ts.map +1 -0
  335. package/dist/routes/config/settings.js +89 -43
  336. package/dist/routes/config/settings.js.map +1 -1
  337. package/dist/routes/debug.d.ts +1 -0
  338. package/dist/routes/debug.d.ts.map +1 -0
  339. package/dist/routes/debug.js +2 -2
  340. package/dist/routes/debug.js.map +1 -1
  341. package/dist/routes/health.d.ts +39 -1
  342. package/dist/routes/health.d.ts.map +1 -0
  343. package/dist/routes/health.js +33 -27
  344. package/dist/routes/health.js.map +1 -1
  345. package/dist/routes/hls.d.ts +1 -0
  346. package/dist/routes/hls.d.ts.map +1 -0
  347. package/dist/routes/icons.d.ts +1 -0
  348. package/dist/routes/icons.d.ts.map +1 -0
  349. package/dist/routes/icons.js +1 -1
  350. package/dist/routes/index.d.ts +1 -0
  351. package/dist/routes/index.d.ts.map +1 -0
  352. package/dist/routes/logs.d.ts +1 -0
  353. package/dist/routes/logs.d.ts.map +1 -0
  354. package/dist/routes/logs.js +13 -3
  355. package/dist/routes/logs.js.map +1 -1
  356. package/dist/routes/mpegts.d.ts +1 -0
  357. package/dist/routes/mpegts.d.ts.map +1 -0
  358. package/dist/routes/play.d.ts +1 -0
  359. package/dist/routes/play.d.ts.map +1 -0
  360. package/dist/routes/playlist.d.ts +1 -0
  361. package/dist/routes/playlist.d.ts.map +1 -0
  362. package/dist/routes/playlist.js +7 -2
  363. package/dist/routes/playlist.js.map +1 -1
  364. package/dist/routes/root/content.d.ts +8 -5
  365. package/dist/routes/root/content.d.ts.map +1 -0
  366. package/dist/routes/root/content.js +11 -12
  367. package/dist/routes/root/content.js.map +1 -1
  368. package/dist/routes/root/index.d.ts +2 -1
  369. package/dist/routes/root/index.d.ts.map +1 -0
  370. package/dist/routes/root/index.js +10 -8
  371. package/dist/routes/root/index.js.map +1 -1
  372. package/dist/routes/root/scripts/channels.d.ts +6 -0
  373. package/dist/routes/root/scripts/channels.d.ts.map +1 -0
  374. package/dist/routes/root/scripts/channels.js +147 -97
  375. package/dist/routes/root/scripts/channels.js.map +1 -1
  376. package/dist/routes/root/scripts/clientEscape.d.ts +22 -0
  377. package/dist/routes/root/scripts/clientEscape.d.ts.map +1 -0
  378. package/dist/routes/root/scripts/clientEscape.js +41 -0
  379. package/dist/routes/root/scripts/clientEscape.js.map +1 -0
  380. package/dist/routes/root/scripts/clientUrl.d.ts +23 -0
  381. package/dist/routes/root/scripts/clientUrl.d.ts.map +1 -0
  382. package/dist/routes/root/scripts/clientUrl.js +44 -0
  383. package/dist/routes/root/scripts/clientUrl.js.map +1 -0
  384. package/dist/routes/root/scripts/config.d.ts +6 -0
  385. package/dist/routes/root/scripts/config.d.ts.map +1 -0
  386. package/dist/routes/root/scripts/config.js +39 -22
  387. package/dist/routes/root/scripts/config.js.map +1 -1
  388. package/dist/routes/root/scripts/index.d.ts +1 -0
  389. package/dist/routes/root/scripts/index.d.ts.map +1 -0
  390. package/dist/routes/root/scripts/shared.d.ts +1 -0
  391. package/dist/routes/root/scripts/shared.d.ts.map +1 -0
  392. package/dist/routes/root/scripts/shared.js +52 -26
  393. package/dist/routes/root/scripts/shared.js.map +1 -1
  394. package/dist/routes/root/scripts/status.d.ts +1 -0
  395. package/dist/routes/root/scripts/status.d.ts.map +1 -0
  396. package/dist/routes/root/scripts/status.handlers.d.ts +18 -6
  397. package/dist/routes/root/scripts/status.handlers.d.ts.map +1 -0
  398. package/dist/routes/root/scripts/status.handlers.js +38 -32
  399. package/dist/routes/root/scripts/status.handlers.js.map +1 -1
  400. package/dist/routes/root/scripts/status.js +15 -7
  401. package/dist/routes/root/scripts/status.js.map +1 -1
  402. package/dist/routes/root/styles.d.ts +1 -0
  403. package/dist/routes/root/styles.d.ts.map +1 -0
  404. package/dist/routes/root/styles.js +7 -4
  405. package/dist/routes/root/styles.js.map +1 -1
  406. package/dist/routes/services.d.ts +13 -1
  407. package/dist/routes/services.d.ts.map +1 -0
  408. package/dist/routes/services.js +81 -68
  409. package/dist/routes/services.js.map +1 -1
  410. package/dist/routes/sse.d.ts +1 -0
  411. package/dist/routes/sse.d.ts.map +1 -0
  412. package/dist/routes/sse.js +1 -1
  413. package/dist/routes/sse.js.map +1 -1
  414. package/dist/routes/streams.d.ts +2 -1
  415. package/dist/routes/streams.d.ts.map +1 -0
  416. package/dist/routes/streams.js +1 -1
  417. package/dist/routes/theme.d.ts +3 -2
  418. package/dist/routes/theme.d.ts.map +1 -0
  419. package/dist/routes/theme.js +6 -5
  420. package/dist/routes/theme.js.map +1 -1
  421. package/dist/routes/ui.d.ts +3 -1
  422. package/dist/routes/ui.d.ts.map +1 -0
  423. package/dist/routes/ui.js +16 -4
  424. package/dist/routes/ui.js.map +1 -1
  425. package/dist/routes/upgrade.d.ts +1 -0
  426. package/dist/routes/upgrade.d.ts.map +1 -0
  427. package/dist/routes/upgrade.js +6 -2
  428. package/dist/routes/upgrade.js.map +1 -1
  429. package/dist/service/commands.context.d.ts +1 -0
  430. package/dist/service/commands.context.d.ts.map +1 -0
  431. package/dist/service/commands.context.js +3 -2
  432. package/dist/service/commands.context.js.map +1 -1
  433. package/dist/service/commands.d.ts +1 -0
  434. package/dist/service/commands.d.ts.map +1 -0
  435. package/dist/service/commands.js +10 -13
  436. package/dist/service/commands.js.map +1 -1
  437. package/dist/service/generators.context.d.ts +1 -0
  438. package/dist/service/generators.context.d.ts.map +1 -0
  439. package/dist/service/generators.d.ts +3 -2
  440. package/dist/service/generators.d.ts.map +1 -0
  441. package/dist/service/generators.js +108 -20
  442. package/dist/service/generators.js.map +1 -1
  443. package/dist/service/index.d.ts +1 -0
  444. package/dist/service/index.d.ts.map +1 -0
  445. package/dist/streaming/captureLock.d.ts +44 -0
  446. package/dist/streaming/captureLock.d.ts.map +1 -0
  447. package/dist/streaming/captureLock.js +95 -0
  448. package/dist/streaming/captureLock.js.map +1 -0
  449. package/dist/streaming/captureSession.d.ts +31 -0
  450. package/dist/streaming/captureSession.d.ts.map +1 -0
  451. package/dist/streaming/captureSession.js +54 -0
  452. package/dist/streaming/captureSession.js.map +1 -0
  453. package/dist/streaming/clients.d.ts +1 -0
  454. package/dist/streaming/clients.d.ts.map +1 -0
  455. package/dist/streaming/codec.d.ts +1 -0
  456. package/dist/streaming/codec.d.ts.map +1 -0
  457. package/dist/streaming/fmp4Segmenter.d.ts +29 -2
  458. package/dist/streaming/fmp4Segmenter.d.ts.map +1 -0
  459. package/dist/streaming/fmp4Segmenter.js +79 -26
  460. package/dist/streaming/fmp4Segmenter.js.map +1 -1
  461. package/dist/streaming/hls.d.ts +18 -7
  462. package/dist/streaming/hls.d.ts.map +1 -0
  463. package/dist/streaming/hls.js +219 -115
  464. package/dist/streaming/hls.js.map +1 -1
  465. package/dist/streaming/hlsResume.d.ts +1 -0
  466. package/dist/streaming/hlsResume.d.ts.map +1 -0
  467. package/dist/streaming/hlsResume.js +1 -1
  468. package/dist/streaming/hlsResume.js.map +1 -1
  469. package/dist/streaming/hlsSegments.d.ts +58 -1
  470. package/dist/streaming/hlsSegments.d.ts.map +1 -0
  471. package/dist/streaming/hlsSegments.js +147 -17
  472. package/dist/streaming/hlsSegments.js.map +1 -1
  473. package/dist/streaming/lifecycle.d.ts +4 -1
  474. package/dist/streaming/lifecycle.d.ts.map +1 -0
  475. package/dist/streaming/lifecycle.js +65 -85
  476. package/dist/streaming/lifecycle.js.map +1 -1
  477. package/dist/streaming/monitor.d.ts +6 -4
  478. package/dist/streaming/monitor.d.ts.map +1 -0
  479. package/dist/streaming/monitor.js +343 -145
  480. package/dist/streaming/monitor.js.map +1 -1
  481. package/dist/streaming/mp4Parser.d.ts +5 -4
  482. package/dist/streaming/mp4Parser.d.ts.map +1 -0
  483. package/dist/streaming/mp4Parser.js +36 -13
  484. package/dist/streaming/mp4Parser.js.map +1 -1
  485. package/dist/streaming/mpegts.d.ts +16 -0
  486. package/dist/streaming/mpegts.d.ts.map +1 -0
  487. package/dist/streaming/mpegts.js +61 -17
  488. package/dist/streaming/mpegts.js.map +1 -1
  489. package/dist/streaming/playlistBuilder.d.ts +1 -0
  490. package/dist/streaming/playlistBuilder.d.ts.map +1 -0
  491. package/dist/streaming/preroll.d.ts +31 -4
  492. package/dist/streaming/preroll.d.ts.map +1 -0
  493. package/dist/streaming/preroll.js +69 -27
  494. package/dist/streaming/preroll.js.map +1 -1
  495. package/dist/streaming/pretune.d.ts +26 -1
  496. package/dist/streaming/pretune.d.ts.map +1 -0
  497. package/dist/streaming/pretune.js +22 -24
  498. package/dist/streaming/pretune.js.map +1 -1
  499. package/dist/streaming/pretuneTimers.d.ts +24 -0
  500. package/dist/streaming/pretuneTimers.d.ts.map +1 -0
  501. package/dist/streaming/pretuneTimers.js +56 -0
  502. package/dist/streaming/pretuneTimers.js.map +1 -0
  503. package/dist/streaming/recovery.d.ts +139 -5
  504. package/dist/streaming/recovery.d.ts.map +1 -0
  505. package/dist/streaming/recovery.js +160 -16
  506. package/dist/streaming/recovery.js.map +1 -1
  507. package/dist/streaming/registry.d.ts +27 -9
  508. package/dist/streaming/registry.d.ts.map +1 -0
  509. package/dist/streaming/registry.js +21 -3
  510. package/dist/streaming/registry.js.map +1 -1
  511. package/dist/streaming/setup.d.ts +157 -29
  512. package/dist/streaming/setup.d.ts.map +1 -0
  513. package/dist/streaming/setup.js +1034 -458
  514. package/dist/streaming/setup.js.map +1 -1
  515. package/dist/streaming/showInfo.d.ts +21 -1
  516. package/dist/streaming/showInfo.d.ts.map +1 -0
  517. package/dist/streaming/showInfo.js +31 -16
  518. package/dist/streaming/showInfo.js.map +1 -1
  519. package/dist/streaming/statusEmitter.d.ts +5 -2
  520. package/dist/streaming/statusEmitter.d.ts.map +1 -0
  521. package/dist/streaming/statusEmitter.js +5 -3
  522. package/dist/streaming/statusEmitter.js.map +1 -1
  523. package/dist/types/channels.d.ts +15 -12
  524. package/dist/types/channels.d.ts.map +1 -0
  525. package/dist/types/channels.js +4 -2
  526. package/dist/types/channels.js.map +1 -1
  527. package/dist/types/config.d.ts +16 -5
  528. package/dist/types/config.d.ts.map +1 -0
  529. package/dist/types/index.d.ts +3 -2
  530. package/dist/types/index.d.ts.map +1 -0
  531. package/dist/types/profiles.d.ts +4 -2
  532. package/dist/types/profiles.d.ts.map +1 -0
  533. package/dist/types/selection.d.ts +31 -3
  534. package/dist/types/selection.d.ts.map +1 -0
  535. package/dist/types/selection.js +4 -2
  536. package/dist/types/selection.js.map +1 -1
  537. package/dist/types/shared.d.ts +1 -0
  538. package/dist/types/shared.d.ts.map +1 -0
  539. package/dist/types/streaming.d.ts +8 -0
  540. package/dist/types/streaming.d.ts.map +1 -0
  541. package/dist/upgrade/commands.context.d.ts +1 -0
  542. package/dist/upgrade/commands.context.d.ts.map +1 -0
  543. package/dist/upgrade/commands.d.ts +1 -0
  544. package/dist/upgrade/commands.d.ts.map +1 -0
  545. package/dist/upgrade/commands.js +1 -1
  546. package/dist/upgrade/commands.js.map +1 -1
  547. package/dist/upgrade/detection.context.d.ts +1 -0
  548. package/dist/upgrade/detection.context.d.ts.map +1 -0
  549. package/dist/upgrade/detection.context.js +2 -0
  550. package/dist/upgrade/detection.context.js.map +1 -1
  551. package/dist/upgrade/detection.d.ts +7 -6
  552. package/dist/upgrade/detection.d.ts.map +1 -0
  553. package/dist/upgrade/detection.js +4 -4
  554. package/dist/upgrade/index.d.ts +1 -0
  555. package/dist/upgrade/index.d.ts.map +1 -0
  556. package/dist/upgrade/lifecycle.context.d.ts +1 -0
  557. package/dist/upgrade/lifecycle.context.d.ts.map +1 -0
  558. package/dist/upgrade/lifecycle.d.ts +7 -7
  559. package/dist/upgrade/lifecycle.d.ts.map +1 -0
  560. package/dist/upgrade/lifecycle.js +9 -10
  561. package/dist/upgrade/lifecycle.js.map +1 -1
  562. package/dist/upgrade/pathHandle.d.ts +5 -3
  563. package/dist/upgrade/pathHandle.d.ts.map +1 -0
  564. package/dist/upgrade/pathHandle.js +3 -2
  565. package/dist/upgrade/pathHandle.js.map +1 -1
  566. package/dist/utils/bootSession.context.d.ts +1 -0
  567. package/dist/utils/bootSession.context.d.ts.map +1 -0
  568. package/dist/utils/bootSession.context.js +6 -5
  569. package/dist/utils/bootSession.context.js.map +1 -1
  570. package/dist/utils/bootSession.d.ts +1 -0
  571. package/dist/utils/bootSession.d.ts.map +1 -0
  572. package/dist/utils/bootSession.js.map +1 -1
  573. package/dist/utils/chromeFetch.d.ts +1 -0
  574. package/dist/utils/chromeFetch.d.ts.map +1 -0
  575. package/dist/utils/cliOutput.d.ts +1 -0
  576. package/dist/utils/cliOutput.d.ts.map +1 -0
  577. package/dist/utils/clock.d.ts +5 -4
  578. package/dist/utils/clock.d.ts.map +1 -0
  579. package/dist/utils/clock.js +19 -16
  580. package/dist/utils/clock.js.map +1 -1
  581. package/dist/utils/debugFilter.d.ts +9 -1
  582. package/dist/utils/debugFilter.d.ts.map +1 -0
  583. package/dist/utils/debugFilter.js +60 -33
  584. package/dist/utils/debugFilter.js.map +1 -1
  585. package/dist/utils/delay.d.ts +48 -15
  586. package/dist/utils/delay.d.ts.map +1 -0
  587. package/dist/utils/delay.js +73 -20
  588. package/dist/utils/delay.js.map +1 -1
  589. package/dist/utils/errors.d.ts +32 -0
  590. package/dist/utils/errors.d.ts.map +1 -0
  591. package/dist/utils/errors.js +45 -4
  592. package/dist/utils/errors.js.map +1 -1
  593. package/dist/utils/evaluate.d.ts +1 -0
  594. package/dist/utils/evaluate.d.ts.map +1 -0
  595. package/dist/utils/evaluate.js +29 -23
  596. package/dist/utils/evaluate.js.map +1 -1
  597. package/dist/utils/ffmpeg.context.d.ts +1 -0
  598. package/dist/utils/ffmpeg.context.d.ts.map +1 -0
  599. package/dist/utils/ffmpeg.context.js.map +1 -1
  600. package/dist/utils/ffmpeg.d.ts +29 -7
  601. package/dist/utils/ffmpeg.d.ts.map +1 -0
  602. package/dist/utils/ffmpeg.js +31 -13
  603. package/dist/utils/ffmpeg.js.map +1 -1
  604. package/dist/utils/fileLogger.d.ts +3 -1
  605. package/dist/utils/fileLogger.d.ts.map +1 -0
  606. package/dist/utils/fileLogger.js +64 -29
  607. package/dist/utils/fileLogger.js.map +1 -1
  608. package/dist/utils/format.d.ts +14 -1
  609. package/dist/utils/format.d.ts.map +1 -0
  610. package/dist/utils/format.js +19 -5
  611. package/dist/utils/format.js.map +1 -1
  612. package/dist/utils/index.d.ts +1 -0
  613. package/dist/utils/index.d.ts.map +1 -0
  614. package/dist/utils/logEmitter.d.ts +1 -0
  615. package/dist/utils/logEmitter.d.ts.map +1 -0
  616. package/dist/utils/logger.d.ts +1 -0
  617. package/dist/utils/logger.d.ts.map +1 -0
  618. package/dist/utils/logger.js +10 -6
  619. package/dist/utils/logger.js.map +1 -1
  620. package/dist/utils/m3u.d.ts +3 -2
  621. package/dist/utils/m3u.d.ts.map +1 -0
  622. package/dist/utils/m3u.js +4 -3
  623. package/dist/utils/m3u.js.map +1 -1
  624. package/dist/utils/markup.d.ts +4 -2
  625. package/dist/utils/markup.d.ts.map +1 -0
  626. package/dist/utils/markup.js +6 -5
  627. package/dist/utils/markup.js.map +1 -1
  628. package/dist/utils/memo.d.ts +3 -2
  629. package/dist/utils/memo.d.ts.map +1 -0
  630. package/dist/utils/memo.js +3 -3
  631. package/dist/utils/morganStream.d.ts +1 -0
  632. package/dist/utils/morganStream.d.ts.map +1 -0
  633. package/dist/utils/network.d.ts +1 -0
  634. package/dist/utils/network.d.ts.map +1 -0
  635. package/dist/utils/network.js +2 -2
  636. package/dist/utils/pid.d.ts +1 -0
  637. package/dist/utils/pid.d.ts.map +1 -0
  638. package/dist/utils/pid.js +3 -3
  639. package/dist/utils/platform.d.ts +3 -1
  640. package/dist/utils/platform.d.ts.map +1 -0
  641. package/dist/utils/platform.js +2 -1
  642. package/dist/utils/platform.js.map +1 -1
  643. package/dist/utils/processInspector.context.d.ts +1 -0
  644. package/dist/utils/processInspector.context.d.ts.map +1 -0
  645. package/dist/utils/processInspector.context.js +3 -1
  646. package/dist/utils/processInspector.context.js.map +1 -1
  647. package/dist/utils/processInspector.d.ts +4 -3
  648. package/dist/utils/processInspector.d.ts.map +1 -0
  649. package/dist/utils/processInspector.js +2 -0
  650. package/dist/utils/processInspector.js.map +1 -1
  651. package/dist/utils/retry.d.ts +24 -1
  652. package/dist/utils/retry.d.ts.map +1 -0
  653. package/dist/utils/retry.js +32 -5
  654. package/dist/utils/retry.js.map +1 -1
  655. package/dist/utils/runtimeIdentity.context.d.ts +1 -0
  656. package/dist/utils/runtimeIdentity.context.d.ts.map +1 -0
  657. package/dist/utils/runtimeIdentity.context.js +30 -0
  658. package/dist/utils/runtimeIdentity.context.js.map +1 -1
  659. package/dist/utils/runtimeIdentity.d.ts +6 -4
  660. package/dist/utils/runtimeIdentity.d.ts.map +1 -0
  661. package/dist/utils/runtimeIdentity.js +15 -5
  662. package/dist/utils/runtimeIdentity.js.map +1 -1
  663. package/dist/utils/sanitize.d.ts +1 -0
  664. package/dist/utils/sanitize.d.ts.map +1 -0
  665. package/dist/utils/streamContext.d.ts +2 -1
  666. package/dist/utils/streamContext.d.ts.map +1 -0
  667. package/dist/utils/streamContext.js +1 -1
  668. package/dist/utils/timing.d.ts +1 -0
  669. package/dist/utils/timing.d.ts.map +1 -0
  670. package/dist/utils/version.d.ts +1 -0
  671. package/dist/utils/version.d.ts.map +1 -0
  672. package/dist/utils/version.js +7 -3
  673. package/dist/utils/version.js.map +1 -1
  674. package/package.json +26 -20
@@ -1,66 +1,117 @@
1
1
  import type { Nullable } from "../types/index.ts";
2
2
  import type { Page } from "puppeteer-core";
3
+ import type { RecognizedHlsPlaylistKind } from "../native/probe.ts";
4
+ import { observeHlsPlaylists } from "./hlsPlaylistObserver.ts";
5
+ export declare const FINALIZE_SETTLE_DELAY = 1500;
3
6
  /**
4
- * Captured-URL state used by selectInterceptedManifest() to choose the playlist URL appropriate for a given resolution mode. Modeled as a plain record so the
5
- * selection logic is testable in isolation from the network plumbing that maintains the underlying state.
7
+ * A master playlist observation reduced to the facts selection needs: the declared child playlist URLs (for membership judgment), the wire-arrival ordinal, and
8
+ * the URL. Modeled as a record so a URL can never exist without its ordinal - the null-consistency question separate parallel locals would raise is
9
+ * unrepresentable.
10
+ */
11
+ export interface InterceptedMasterFact {
12
+ readonly childUrls: readonly string[];
13
+ readonly ordinal: number;
14
+ readonly url: string;
15
+ }
16
+ /**
17
+ * A media playlist observation reduced to the facts selection needs: its liveness, the wire-arrival ordinal, and the URL. Modeled as a record so a URL can never
18
+ * exist without its ordinal.
19
+ */
20
+ export interface InterceptedMediaFact {
21
+ readonly live: boolean;
22
+ readonly ordinal: number;
23
+ readonly url: string;
24
+ }
25
+ /**
26
+ * Captured state used by selectInterceptedManifest() to choose the playlist appropriate for a given resolution mode. Modeled as a plain record so the selection
27
+ * logic is testable in isolation from the network plumbing that maintains the underlying state. Every judgment - including the pathname normalization membership
28
+ * relies on - lives in the selection function; this record carries only facts.
6
29
  */
7
30
  export interface InterceptedManifestState {
8
- directTune: boolean;
9
- firstMasterUrl: Nullable<string>;
10
- firstMediaUrl: Nullable<string>;
11
- latestMasterUrl: Nullable<string>;
12
- latestMediaUrl: Nullable<string>;
31
+ readonly directTune: boolean;
32
+ readonly firstMasterUrl: Nullable<string>;
33
+ readonly firstMediaUrl: Nullable<string>;
34
+ readonly latestMaster: Nullable<InterceptedMasterFact>;
35
+ readonly latestMedia: Nullable<InterceptedMediaFact>;
36
+ readonly markOrdinal: Nullable<number>;
13
37
  }
14
38
  /**
15
- * Selects the playlist URL appropriate for a given resolution mode from the per-kind first/latest state captured by the manifest observer. Master URLs always
16
- * outrank media URLs when both kinds were observed because masters declare richer metadata (variant bandwidth, resolution, separate audio renditions). Within
17
- * the chosen kind, direct tunes pick the first URL and guide tunes pick the latest URL. Returns null when no qualifying URL is available.
39
+ * The outcome of selectInterceptedManifest(): the chosen URL and the kind selection decided it is. The kind is reported alongside the URL so no caller re-derives
40
+ * it by comparing URLs, which would be fragile when the same URL could sit in both the master and media records.
41
+ */
42
+ export interface SelectedManifest {
43
+ readonly kind: RecognizedHlsPlaylistKind;
44
+ readonly url: string;
45
+ }
46
+ /**
47
+ * Selects the playlist appropriate for a given resolution mode from the captured state, reporting the URL together with the kind selection decided.
48
+ *
49
+ * Direct tunes take the earliest qualifying capture (firstMasterUrl before firstMediaUrl), master preferred, with the kind tagged by the slot that supplied the
50
+ * URL. The epoch never participates on the direct branch: a direct tune navigates by URL and its first capture answers.
51
+ *
52
+ * Guide tunes apply a three-signal rule over the latest captures:
53
+ *
54
+ * 1. No master captured: the media fallback (latestMedia's URL) or null. Liveness gates only the override of a master, never the sole available feed, so a VOD
55
+ * media playlist still answers when it is all that arrived.
56
+ * 2. Epoch declared and the master post-epoch (latestMaster.ordinal > markOrdinal): the master, categorically. A master observed after channel selection began
57
+ * answers the click. An absent epoch (mark never called) also leaves the master the winner, because without a click there is no fresher truth to prefer.
58
+ * 3. Override to the media only when every clause holds: an epoch exists (rule 2 falling through means the master is pre-epoch), latestMedia is live, the media
59
+ * is post-epoch (latestMedia.ordinal > markOrdinal - which structurally postdates the pre-epoch master, so no separate ordering clause is needed), and the
60
+ * media is a verified non-member of the master's children. Otherwise the master wins.
18
61
  *
19
- * Pure selection policy exported so the rule is testable in isolation from the network plumbing; the closure inside installManifestInterceptor() consumes it
20
- * through the same shape.
62
+ * Membership is member-conservative (see isVerifiedNonMemberOfMaster): anything short of a proven foreign pathname keeps the master, so the override engages only
63
+ * where a media playlist is demonstrably not one of the master's own children. Pure selection policy exported so the rule is testable in isolation from the
64
+ * network plumbing; the closure inside installManifestInterceptor() consumes it through the same shape.
21
65
  *
22
- * @param state - The captured-URL state at resolution time.
23
- * @returns The selected URL, or null when no URL matches the resolution mode.
66
+ * @param state - The captured state at resolution time.
67
+ * @returns The selected playlist, or null when no URL matches the resolution mode.
24
68
  */
25
- export declare function selectInterceptedManifest(state: InterceptedManifestState): Nullable<string>;
69
+ export declare function selectInterceptedManifest(state: InterceptedManifestState): Nullable<SelectedManifest>;
26
70
  /**
27
- * Result of manifest interception. The URL may be either a master or a media playlist; the probe normalizes both kinds into a MediaFeed so downstream code does
28
- * not branch on which kind originally arrived. The underlying observer and its CDP sessions are owned and disposed internally - callers do not hold session
29
- * references.
71
+ * Result of manifest interception. The URL may be either a master or a media playlist; selectedKind reports which selection chose, and the probe normalizes both
72
+ * kinds into a MediaFeed so downstream code does not branch on which kind originally arrived. The underlying observer and its CDP sessions are owned and disposed
73
+ * internally - callers do not hold session references.
30
74
  */
31
75
  export interface ManifestInterceptionResult {
32
- masterManifestUrl: string;
76
+ readonly manifestUrl: string;
77
+ readonly selectedKind: RecognizedHlsPlaylistKind;
33
78
  }
34
79
  /**
35
- * Handle returned by installManifestInterceptor. Provides the interception promise, a finalize function to signal that channel selection is complete, and an
36
- * explicit dispose path. Implements TC39 Symbol.dispose so callers may use the "using" keyword for scope-bound cleanup, including on thrown errors.
80
+ * Handle returned by installManifestInterceptor. Provides the interception promise, a finalize function to signal that channel selection is complete, an epoch
81
+ * stamp marking when channel selection begins, and an explicit dispose path. Implements TC39 Symbol.dispose so callers may use the "using" keyword for
82
+ * scope-bound cleanup, including on thrown errors.
37
83
  */
38
84
  export interface ManifestInterceptorHandle extends Disposable {
39
85
  readonly dispose: () => void;
40
86
  readonly finalize: (directTune: boolean) => void;
87
+ readonly markChannelSelectionStart: () => void;
41
88
  readonly promise: Promise<Nullable<ManifestInterceptionResult>>;
42
89
  readonly [Symbol.dispose]: () => void;
43
90
  }
44
91
  /**
45
- * Installs a long-lived HLS playlist observer that tracks observed playlist URLs on the given page. Both master and media playlists are accepted; first/latest
46
- * URLs are tracked separately per kind so master-based and media-only sites both work without separate code paths. Master playlists take precedence over media
47
- * playlists when both have arrived during the interception window because masters carry richer metadata (variant bandwidth, resolution, separate audio
48
- * renditions) that improves the resulting MediaFeed. The returned handle provides a finalize(directTune) callback - when called, the observer resolves with
49
- * whichever URL is appropriate for the tune type:
92
+ * Installs a long-lived HLS playlist observer that tracks observed playlists on the given page. Both master and media playlists are accepted; the first and latest
93
+ * URL per kind are tracked separately, guarded by wire-arrival order, so master-based and media-only sites both work without separate code paths. The returned
94
+ * handle provides a finalize(directTune) callback and a markChannelSelectionStart() epoch stamp; when finalize is called the observer resolves through
95
+ * selectInterceptedManifest with the playlist appropriate for the tune type:
50
96
  *
51
- * - directTune=true: resolves immediately (or after the settle delay if no manifest has arrived yet) with the first manifest captured. Used by sites where the
52
- * navigated URL itself selects the channel and the player loads its manifest before the click handler returns. Master-first URL preferred over media-first.
53
- * - directTune=false: resolves after the settle delay with the latest manifest captured. Used by guide-based sites where the channel-switch click triggers a
54
- * new manifest fetch that may arrive milliseconds after the click handler returns. Master-latest URL preferred over media-latest.
97
+ * - directTune=true: resolves immediately if a master manifest has already arrived (or after the settle delay when only a media-only manifest, or nothing, has
98
+ * arrived so far) with the first manifest captured. Used by sites where the navigated URL itself selects the channel and the player loads its manifest before
99
+ * the click handler returns. Master-first URL preferred over media-first.
100
+ * - directTune=false: resolves after the settle delay through the guide-tune rule (channel-selection epoch, playlist membership, liveness), so the tuned
101
+ * channel's playlist wins over a page-load default channel captured first. Used by guide-based sites where the channel-switch click triggers a new manifest
102
+ * fetch that may arrive milliseconds after the click handler returns.
55
103
  *
56
- * On timeout (finalize never called), the observer resolves with the latest captured URL using the same master-priority rule, or null if none arrived. The
57
- * underlying HLS observer is disposed automatically on resolution; callers do not hold CDP session references.
104
+ * On timeout (finalize never called), the observer resolves epoch-free through the same guide-tune rule with no epoch declared, so the categorical
105
+ * master-preferred outcome holds and a direct tune the timeout may be guarding is never exposed to the epoch rule. The underlying HLS observer is disposed
106
+ * automatically on resolution; callers do not hold CDP session references.
58
107
  *
59
108
  * @param page - The puppeteer page to monitor.
60
- * @param timeout - Maximum time in milliseconds to wait for a manifest. Acts as a safety net if finalize() is never called.
109
+ * @param timeout - Maximum time in milliseconds to wait for a manifest. Required: every caller sizes its interception window consciously to outlive the phases it
110
+ * observes, so no production caller relies on a shared default. Acts as a safety net if finalize() is never called.
111
+ * @param observeFactory - The HLS playlist observer factory (default observeHlsPlaylists); injectable so the selection state machine can run without a live browser.
61
112
  * @returns The interceptor handle, or null if the observer could not be installed.
62
113
  */
63
- export declare function installManifestInterceptor(page: Page, timeout?: number): Promise<Nullable<ManifestInterceptorHandle>>;
114
+ export declare function installManifestInterceptor(page: Page, timeout: number, observeFactory?: typeof observeHlsPlaylists): Promise<Nullable<ManifestInterceptorHandle>>;
64
115
  /**
65
116
  * Awaits the first master HLS manifest whose URL satisfies the supplied predicate. Used by tune-verification paths where the caller has just clicked or
66
117
  * navigated to a target channel and wants to confirm the resulting stream belongs to that channel rather than to whatever default the page was previously
@@ -72,6 +123,8 @@ export declare function installManifestInterceptor(page: Page, timeout?: number)
72
123
  * @param page - The puppeteer page to monitor.
73
124
  * @param predicate - Test applied to each verified master manifest URL. Return true to accept the URL and resolve.
74
125
  * @param timeout - Maximum time in milliseconds to wait for a matching manifest.
126
+ * @param observeFactory - The HLS playlist observer factory (default observeHlsPlaylists); injectable so the verification state machine can run without a live browser.
75
127
  * @returns The matching URL, or null on timeout.
76
128
  */
77
- export declare function awaitMatchingManifest(page: Page, predicate: (url: string) => boolean, timeout?: number): Promise<Nullable<string>>;
129
+ export declare function awaitMatchingManifest(page: Page, predicate: (url: string) => boolean, timeout?: number, observeFactory?: typeof observeHlsPlaylists): Promise<Nullable<string>>;
130
+ //# sourceMappingURL=manifestInterceptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifestInterceptor.d.ts","sourceRoot":"","sources":["../../src/browser/manifestInterceptor.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AA6B/D,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAK1C;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IAIpC,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAGtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAGzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IAGnC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAGvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAGzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IAGvC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAG7B,QAAQ,CAAC,cAAc,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAG1C,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAGzC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,qBAAqB,CAAC,CAAC;IAGvD,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IAIrD,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CACxC;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAG/B,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;IAGzC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAmCD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,wBAAwB,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAuCrG;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IAIzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAG7B,QAAQ,CAAC,YAAY,EAAE,yBAAyB,CAAC;CAClD;AAED;;;;GAIG;AACH,MAAM,WAAW,yBAA0B,SAAQ,UAAU;IAI3D,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAM7B,QAAQ,CAAC,QAAQ,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC;IAKjD,QAAQ,CAAC,yBAAyB,EAAE,MAAM,IAAI,CAAC;IAI/C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAC,CAAC,CAAC;IAGhE,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACvC;AA6BD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAC1E,cAAc,GAAE,OAAO,mBAAyC,GAAG,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,CAoKhH;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,EACzF,OAAO,GAAE,MAA6B,EAAE,cAAc,GAAE,OAAO,mBAAyC,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CA8DrI"}
@@ -1,120 +1,196 @@
1
- import { LOG, startTimer } from "../utils/index.js";
1
+ import { LOG, extractPathname, startTimer } from "../utils/index.js";
2
2
  import { observeHlsPlaylists } from "./hlsPlaylistObserver.js";
3
3
  /* This module hosts two consumer-facing state machines built on top of the HLS playlist observer (hlsPlaylistObserver.ts), which in turn rides on the tab-wide
4
4
  * network observer (tabNetworkObserver.ts). The layering:
5
5
  *
6
6
  * tabNetworkObserver -> tab-wide CDP transport (OOPIF-aware via auto-attach + flatten)
7
- * hlsPlaylistObserver -> HLS filter + body fetch + classify + per-URL dedup
8
- * manifestInterceptor -> selection: first-vs-latest, master priority, finalize semantics, predicate match
7
+ * hlsPlaylistObserver -> HLS filter + body fetch + classify + per-URL dedup + wire-arrival sequencing
8
+ * manifestInterceptor -> selection: the channel-selection epoch, playlist membership, the liveness override, finalize semantics, predicate match
9
9
  *
10
- * Two state machines live here:
10
+ * This module hosts the following consumer-facing state machines built on top of the HLS playlist observer:
11
11
  *
12
- * - installManifestInterceptor(): the long-lived capture used by native HLS setup. Accepts both master and media playlists, tracks first and latest URLs per
13
- * kind, and resolves with the URL appropriate for the tune type when finalize() is called. Master playlists take precedence over media playlists when both
14
- * arrive during the interception window because masters carry richer metadata (variant bandwidth, resolution, separate audio renditions).
12
+ * - installManifestInterceptor(): the long-lived capture used by native HLS setup. Accepts both master and media playlists, tracks the first and latest URL per
13
+ * kind, and resolves with the playlist appropriate for the tune type when finalize() is called. A direct tune (single-channel site navigated by URL) takes the
14
+ * first qualifying capture, master preferred. A guide tune (multi-channel site) judges the captures through three signals - a channel-selection epoch stamped
15
+ * when selection begins, playlist membership of a media playlist within the latest master's declared children, and media liveness - so the tuned channel's
16
+ * playlist is chosen even when a page-load default channel was captured first. See selectInterceptedManifest for the full rule.
15
17
  * - awaitMatchingManifest(): the short-lived verification used after a guide-click tune. Accepts master playlists only and resolves with the first URL whose
16
18
  * path satisfies a caller-supplied predicate. Media playlists are skipped at the consumer level because tune verification is a multi-channel concept that
17
19
  * does not apply to direct-tune media-only sources.
18
20
  *
19
- * Race safety, URL filtering, body fetching, and classification all live below this module - we receive a stream of recognized HLS playlists with their kind
20
- * and apply selection policy. Public callers do not hold CDP session references; the underlying HLS observer disposes its tab network observer deterministically
21
- * when finalize, timeout, predicate match, or explicit dispose fires.
21
+ * Race safety, URL filtering, body fetching, classification, and wire-arrival sequencing all live below this module - we receive a stream of recognized HLS
22
+ * playlists with their kind, per-kind facts, and arrival ordinal, and apply selection policy. Public callers do not hold CDP session references; the underlying
23
+ * HLS observer disposes its tab network observer deterministically when finalize, timeout, predicate match, or explicit dispose fires.
22
24
  */
23
- // Default timeout for the long-lived interception used by native HLS.
24
- const INTERCEPTION_TIMEOUT = 15000;
25
- // Brief delay after finalize() is called to allow any in-flight manifest response to arrive. Applied only for guide-based tunes (directTune=false) where the
26
- // channel switch may trigger a manifest fetch that arrives milliseconds after the click handler returns. Direct tunes skip this delay and resolve immediately.
27
- const FINALIZE_SETTLE_DELAY = 1500;
25
+ // Brief delay after finalize() is called to allow any in-flight manifest response to arrive. Applied for guide-based tunes (directTune=false), where the channel
26
+ // switch may trigger a manifest fetch that arrives milliseconds after the click handler returns, and for direct tunes that have not yet captured a master
27
+ // manifest. A direct tune skips this delay and resolves immediately only once a master manifest has already arrived. Exported so a caller sizing its own
28
+ // interception window (streaming/setup.ts) can include the settle window the window must outlive.
29
+ export const FINALIZE_SETTLE_DELAY = 1500;
28
30
  // Default timeout for awaitMatchingManifest. Tune verification is a short-lived check after a click, so the budget is tighter than the native interception path.
29
31
  const VERIFICATION_TIMEOUT = 8000;
30
32
  /**
31
- * Selects the playlist URL appropriate for a given resolution mode from the per-kind first/latest state captured by the manifest observer. Master URLs always
32
- * outrank media URLs when both kinds were observed because masters declare richer metadata (variant bandwidth, resolution, separate audio renditions). Within
33
- * the chosen kind, direct tunes pick the first URL and guide tunes pick the latest URL. Returns null when no qualifying URL is available.
33
+ * Reports whether a media playlist is a verified NON-member of a master's declared children, comparing by pathname only. Membership is URL-identity policy, not
34
+ * manifest-format knowledge, which is why it lives here rather than in probe. Pathname-only because post-redirect response URLs diverge from a master's declared
35
+ * child URIs at the host far more often than at the path. The judgment is member-conservative: a media URL that cannot be parsed, an empty declared child list, or
36
+ * an empty effective set after dropping unparseable children all read as MEMBER (the master wins, degrading to the categorical rule, never a new failure). Only a
37
+ * parseable media pathname absent from a non-empty set of parseable child pathnames is a verified non-member.
34
38
  *
35
- * Pure selection policy exported so the rule is testable in isolation from the network plumbing; the closure inside installManifestInterceptor() consumes it
36
- * through the same shape.
39
+ * @param mediaUrl - The candidate media playlist URL.
40
+ * @param childUrls - The master's declared child playlist URLs.
41
+ * @returns True only when the media pathname is proven absent from a non-empty effective set of child pathnames.
42
+ */
43
+ function isVerifiedNonMemberOfMaster(mediaUrl, childUrls) {
44
+ const mediaPathname = extractPathname(mediaUrl);
45
+ // A media URL we cannot parse cannot be proven foreign, so it reads as a member and the master wins.
46
+ if (mediaPathname === null) {
47
+ return false;
48
+ }
49
+ // Normalize the declared children to pathnames, dropping any that cannot be parsed. An empty declared list or a list that parses to nothing yields an empty
50
+ // effective set: with no children to compare against, membership cannot be disproven, so the master wins.
51
+ const childPathnames = childUrls.map((child) => extractPathname(child)).filter((pathname) => pathname !== null);
52
+ if (childPathnames.length === 0) {
53
+ return false;
54
+ }
55
+ return !childPathnames.includes(mediaPathname);
56
+ }
57
+ /**
58
+ * Selects the playlist appropriate for a given resolution mode from the captured state, reporting the URL together with the kind selection decided.
37
59
  *
38
- * @param state - The captured-URL state at resolution time.
39
- * @returns The selected URL, or null when no URL matches the resolution mode.
60
+ * Direct tunes take the earliest qualifying capture (firstMasterUrl before firstMediaUrl), master preferred, with the kind tagged by the slot that supplied the
61
+ * URL. The epoch never participates on the direct branch: a direct tune navigates by URL and its first capture answers.
62
+ *
63
+ * Guide tunes apply a three-signal rule over the latest captures:
64
+ *
65
+ * 1. No master captured: the media fallback (latestMedia's URL) or null. Liveness gates only the override of a master, never the sole available feed, so a VOD
66
+ * media playlist still answers when it is all that arrived.
67
+ * 2. Epoch declared and the master post-epoch (latestMaster.ordinal > markOrdinal): the master, categorically. A master observed after channel selection began
68
+ * answers the click. An absent epoch (mark never called) also leaves the master the winner, because without a click there is no fresher truth to prefer.
69
+ * 3. Override to the media only when every clause holds: an epoch exists (rule 2 falling through means the master is pre-epoch), latestMedia is live, the media
70
+ * is post-epoch (latestMedia.ordinal > markOrdinal - which structurally postdates the pre-epoch master, so no separate ordering clause is needed), and the
71
+ * media is a verified non-member of the master's children. Otherwise the master wins.
72
+ *
73
+ * Membership is member-conservative (see isVerifiedNonMemberOfMaster): anything short of a proven foreign pathname keeps the master, so the override engages only
74
+ * where a media playlist is demonstrably not one of the master's own children. Pure selection policy exported so the rule is testable in isolation from the
75
+ * network plumbing; the closure inside installManifestInterceptor() consumes it through the same shape.
76
+ *
77
+ * @param state - The captured state at resolution time.
78
+ * @returns The selected playlist, or null when no URL matches the resolution mode.
40
79
  */
41
80
  export function selectInterceptedManifest(state) {
42
81
  if (state.directTune) {
43
- return state.firstMasterUrl ?? state.firstMediaUrl;
82
+ if (state.firstMasterUrl !== null) {
83
+ return { kind: "master", url: state.firstMasterUrl };
84
+ }
85
+ if (state.firstMediaUrl !== null) {
86
+ return { kind: "media", url: state.firstMediaUrl };
87
+ }
88
+ return null;
89
+ }
90
+ const { latestMaster, latestMedia, markOrdinal } = state;
91
+ // Rule 1: no master captured. The media fallback answers regardless of liveness.
92
+ if (latestMaster === null) {
93
+ return (latestMedia === null) ? null : { kind: "media", url: latestMedia.url };
94
+ }
95
+ // Rule 2: a master observed after channel selection began answers the click categorically; an absent epoch keeps the master too.
96
+ if ((markOrdinal !== null) && (latestMaster.ordinal > markOrdinal)) {
97
+ return { kind: "master", url: latestMaster.url };
98
+ }
99
+ // Rule 3: override to a live, post-epoch, verified non-member media; otherwise the master wins.
100
+ if ((markOrdinal !== null) && (latestMedia !== null) && latestMedia.live && (latestMedia.ordinal > markOrdinal) &&
101
+ isVerifiedNonMemberOfMaster(latestMedia.url, latestMaster.childUrls)) {
102
+ return { kind: "media", url: latestMedia.url };
44
103
  }
45
- return state.latestMasterUrl ?? state.latestMediaUrl;
104
+ return { kind: "master", url: latestMaster.url };
46
105
  }
47
106
  /**
48
- * Installs a long-lived HLS playlist observer that tracks observed playlist URLs on the given page. Both master and media playlists are accepted; first/latest
49
- * URLs are tracked separately per kind so master-based and media-only sites both work without separate code paths. Master playlists take precedence over media
50
- * playlists when both have arrived during the interception window because masters carry richer metadata (variant bandwidth, resolution, separate audio
51
- * renditions) that improves the resulting MediaFeed. The returned handle provides a finalize(directTune) callback - when called, the observer resolves with
52
- * whichever URL is appropriate for the tune type:
107
+ * Installs a long-lived HLS playlist observer that tracks observed playlists on the given page. Both master and media playlists are accepted; the first and latest
108
+ * URL per kind are tracked separately, guarded by wire-arrival order, so master-based and media-only sites both work without separate code paths. The returned
109
+ * handle provides a finalize(directTune) callback and a markChannelSelectionStart() epoch stamp; when finalize is called the observer resolves through
110
+ * selectInterceptedManifest with the playlist appropriate for the tune type:
53
111
  *
54
- * - directTune=true: resolves immediately (or after the settle delay if no manifest has arrived yet) with the first manifest captured. Used by sites where the
55
- * navigated URL itself selects the channel and the player loads its manifest before the click handler returns. Master-first URL preferred over media-first.
56
- * - directTune=false: resolves after the settle delay with the latest manifest captured. Used by guide-based sites where the channel-switch click triggers a
57
- * new manifest fetch that may arrive milliseconds after the click handler returns. Master-latest URL preferred over media-latest.
112
+ * - directTune=true: resolves immediately if a master manifest has already arrived (or after the settle delay when only a media-only manifest, or nothing, has
113
+ * arrived so far) with the first manifest captured. Used by sites where the navigated URL itself selects the channel and the player loads its manifest before
114
+ * the click handler returns. Master-first URL preferred over media-first.
115
+ * - directTune=false: resolves after the settle delay through the guide-tune rule (channel-selection epoch, playlist membership, liveness), so the tuned
116
+ * channel's playlist wins over a page-load default channel captured first. Used by guide-based sites where the channel-switch click triggers a new manifest
117
+ * fetch that may arrive milliseconds after the click handler returns.
58
118
  *
59
- * On timeout (finalize never called), the observer resolves with the latest captured URL using the same master-priority rule, or null if none arrived. The
60
- * underlying HLS observer is disposed automatically on resolution; callers do not hold CDP session references.
119
+ * On timeout (finalize never called), the observer resolves epoch-free through the same guide-tune rule with no epoch declared, so the categorical
120
+ * master-preferred outcome holds and a direct tune the timeout may be guarding is never exposed to the epoch rule. The underlying HLS observer is disposed
121
+ * automatically on resolution; callers do not hold CDP session references.
61
122
  *
62
123
  * @param page - The puppeteer page to monitor.
63
- * @param timeout - Maximum time in milliseconds to wait for a manifest. Acts as a safety net if finalize() is never called.
124
+ * @param timeout - Maximum time in milliseconds to wait for a manifest. Required: every caller sizes its interception window consciously to outlive the phases it
125
+ * observes, so no production caller relies on a shared default. Acts as a safety net if finalize() is never called.
126
+ * @param observeFactory - The HLS playlist observer factory (default observeHlsPlaylists); injectable so the selection state machine can run without a live browser.
64
127
  * @returns The interceptor handle, or null if the observer could not be installed.
65
128
  */
66
- export async function installManifestInterceptor(page, timeout = INTERCEPTION_TIMEOUT) {
129
+ export async function installManifestInterceptor(page, timeout, observeFactory = observeHlsPlaylists) {
67
130
  const elapsed = startTimer();
68
- // Track first/latest URLs separately per playlist kind. Master URLs take precedence at selection time because masters carry richer metadata. For direct tunes,
69
- // the first URL of the higher-priority kind wins; for guide tunes, the latest URL of the higher-priority kind wins. Without separate per-kind tracking, a
70
- // master-based site whose player happens to also load a media playlist for a different channel would risk picking the wrong one.
71
- let firstMasterUrl = null;
72
- let latestMasterUrl = null;
73
- let firstMediaUrl = null;
74
- let latestMediaUrl = null;
131
+ // Track the first and latest observation per kind, plus the epoch fence. Slot updates are guarded by wire-arrival order, not delivery order: the first slot
132
+ // holds the lowest-ordinal arrival and the latest facts hold the highest, so a body fetch that resolves out of order still records arrival truth. Under
133
+ // in-order delivery this is byte-for-byte the earliest/most-recent behavior. manifestCount stays purely diagnostic for the log lines.
134
+ let firstMaster = null;
135
+ let firstMedia = null;
136
+ let latestMaster = null;
137
+ let latestMedia = null;
138
+ let markOrdinal = null;
75
139
  let resolved = false;
76
140
  let manifestCount = 0;
77
141
  const { promise, resolve } = Promise.withResolvers();
78
- const observer = await observeHlsPlaylists(page, {
142
+ const observer = await observeFactory(page, {
79
143
  logCategory: "native:intercept",
80
144
  onPlaylist: (playlist) => {
81
145
  manifestCount++;
82
146
  if (playlist.kind === "master") {
83
- firstMasterUrl ??= playlist.url;
84
- latestMasterUrl = playlist.url;
147
+ // First slot: the lowest ordinal wins, so a late delivery of an even-earlier arrival corrects it.
148
+ if ((firstMaster === null) || (playlist.sequence < firstMaster.ordinal)) {
149
+ firstMaster = { ordinal: playlist.sequence, url: playlist.url };
150
+ }
151
+ // Latest slot: the highest ordinal wins, so a late delivery of a lower arrival never displaces it.
152
+ if ((latestMaster === null) || (playlist.sequence > latestMaster.ordinal)) {
153
+ latestMaster = { childUrls: playlist.childUrls, ordinal: playlist.sequence, url: playlist.url };
154
+ }
85
155
  }
86
- else if (playlist.kind === "media") {
87
- firstMediaUrl ??= playlist.url;
88
- latestMediaUrl = playlist.url;
156
+ else {
157
+ if ((firstMedia === null) || (playlist.sequence < firstMedia.ordinal)) {
158
+ firstMedia = { ordinal: playlist.sequence, url: playlist.url };
159
+ }
160
+ if ((latestMedia === null) || (playlist.sequence > latestMedia.ordinal)) {
161
+ latestMedia = { live: playlist.live, ordinal: playlist.sequence, url: playlist.url };
162
+ }
89
163
  }
90
- LOG.debug("native:intercept", "%s playlist captured (#%s) in %sms: %s.", playlist.kind, manifestCount, elapsed(), playlist.url.slice(0, 120));
164
+ LOG.debug("native:intercept", "%s playlist captured (#%s, seq %s) in %sms: %s.", playlist.kind, manifestCount, playlist.sequence, elapsed(), playlist.url.slice(0, 120));
91
165
  }
92
166
  });
93
167
  if (!observer) {
94
168
  return null;
95
169
  }
96
- // Selects the URL appropriate for the resolution mode by delegating to the pure selectInterceptedManifest() helper. Closure variables are passed by value so
97
- // the helper does not depend on shared mutable state.
98
- const selectUrl = (directTune) => selectInterceptedManifest({
170
+ // Builds the selection state from the closure locals. epochFree forces markOrdinal to null so the timeout path resolves without the epoch rule, which must
171
+ // never engage on a path a direct tune can reach.
172
+ const buildState = (directTune, epochFree) => ({
99
173
  directTune,
100
- firstMasterUrl,
101
- firstMediaUrl,
102
- latestMasterUrl,
103
- latestMediaUrl
174
+ firstMasterUrl: firstMaster?.url ?? null,
175
+ firstMediaUrl: firstMedia?.url ?? null,
176
+ latestMaster,
177
+ latestMedia,
178
+ markOrdinal: epochFree ? null : markOrdinal
104
179
  });
105
180
  // Centralized resolution helper. Used by the timeout, finalize, and dispose paths to settle the promise exactly once and tear down the observer regardless of
106
- // which path won. The selectedUrl computation honors both the master-priority rule and the directTune first/latest semantics via selectInterceptedManifest.
107
- const settle = (directTune, reason) => {
181
+ // which path won. The selection honors the direct-vs-guide semantics and, for guide tunes, the epoch/membership/liveness rule via selectInterceptedManifest.
182
+ const settle = (options) => {
183
+ const { directTune, epochFree = false, reason } = options;
108
184
  if (resolved) {
109
185
  return;
110
186
  }
111
187
  resolved = true;
112
188
  clearTimeout(timer);
113
- const selectedUrl = selectUrl(directTune);
114
- if (selectedUrl) {
115
- LOG.debug("native:intercept", "Interception %s in %sms with %s capture(s). Using %s: %s.", reason, elapsed(), manifestCount, directTune ? "first" : "latest", selectedUrl.slice(0, 120));
189
+ const selection = selectInterceptedManifest(buildState(directTune, epochFree));
190
+ if (selection) {
191
+ LOG.debug("native:intercept", "Interception %s in %sms with %s capture(s). Using %s %s: %s.", reason, elapsed(), manifestCount, directTune ? "first" : "latest", selection.kind, selection.url.slice(0, 120));
116
192
  observer.dispose();
117
- resolve({ masterManifestUrl: selectedUrl });
193
+ resolve({ manifestUrl: selection.url, selectedKind: selection.kind });
118
194
  }
119
195
  else {
120
196
  LOG.debug("native:intercept", "Interception %s in %sms but no HLS playlist was captured.", reason, elapsed());
@@ -122,13 +198,14 @@ export async function installManifestInterceptor(page, timeout = INTERCEPTION_TI
122
198
  resolve(null);
123
199
  }
124
200
  };
125
- // Timeout guard. If finalize() is never called (defensive), settle with whatever we have after the timeout. The timeout path mirrors the latest-URL semantics
126
- // of a guide tune; if no finalize() ever arrived we err on the side of the most recent capture.
127
- const timer = setTimeout(() => { settle(false, "timed out"); }, timeout);
201
+ // Timeout guard. If finalize() is never called (defensive), settle epoch-free after the timeout: the timeout cannot know the tune kind, and the epoch rule must
202
+ // never engage on a path a direct tune can reach, so it resolves with the categorical master-preferred outcome. With the interception budget sized by the
203
+ // caller to outlive the tune (streaming/setup.ts), this path is last-resort defense rather than a routine finish.
204
+ const timer = setTimeout(() => { settle({ directTune: false, epochFree: true, reason: "timed out" }); }, timeout);
128
205
  // Finalize function exposed on the returned handle. Called by the stream setup code after channel selection is complete. The resolution strategy depends on
129
206
  // two factors: whether a qualifying manifest has already been captured, and whether the tune is direct or guide-based.
130
207
  //
131
- // - Manifest captured + direct tune: settle immediately (A&E, most TVE sites - manifest arrived during page load).
208
+ // - Master manifest captured + direct tune: settle immediately (A&E, most TVE sites - manifest arrived during page load).
132
209
  // - Manifest captured + guide tune: wait FINALIZE_SETTLE_DELAY (Fox guide, Hulu - a newer manifest from the channel switch may still arrive).
133
210
  // - No manifest captured + either: wait FINALIZE_SETTLE_DELAY (Fox Sports - manifest fetch starts after video element appears, hasn't arrived yet).
134
211
  const finalize = (directTune) => {
@@ -136,16 +213,26 @@ export async function installManifestInterceptor(page, timeout = INTERCEPTION_TI
136
213
  return;
137
214
  }
138
215
  // For direct tunes, settle immediately if a master URL has already arrived. We do not short-circuit on a media-only first URL because a master may still
139
- // be in flight - waiting the settle delay gives master priority a chance to take effect.
140
- if (directTune && firstMasterUrl) {
141
- settle(true, "finalized");
216
+ // be in flight - waiting the settle delay gives the master-first preference a chance to take effect.
217
+ if (directTune && (firstMaster !== null)) {
218
+ settle({ directTune: true, reason: "finalized" });
142
219
  }
143
220
  else {
144
- setTimeout(() => { settle(directTune, "finalized"); }, FINALIZE_SETTLE_DELAY);
221
+ setTimeout(() => { settle({ directTune, reason: "finalized" }); }, FINALIZE_SETTLE_DELAY);
222
+ }
223
+ };
224
+ // Stamps the observation epoch at which channel selection begins by fencing the observer's current wire sequence. Observations after the stamp answer the
225
+ // click; guide-tune selection prefers a master observed after this point. Callable again - the latest stamp wins - and a no-op once the interception has
226
+ // resolved, matching the finalize and dispose guard idiom.
227
+ const markChannelSelectionStart = () => {
228
+ if (resolved) {
229
+ return;
145
230
  }
231
+ markOrdinal = observer.currentSequence();
232
+ LOG.debug("native:intercept", "Channel selection epoch stamped at wire sequence %s.", markOrdinal);
146
233
  };
147
- // Explicit dispose path for "using" syntax or caller-driven cancellation. Idempotent. Resolves the promise with null if it has not already settled, so
148
- // callers awaiting the promise are never left hanging on a disposed observer.
234
+ // Explicit dispose path for "using" syntax or caller-driven cancellation. Safe to call more than once. Resolves the promise with null if it has not already
235
+ // settled, so callers awaiting the promise are never left hanging on a disposed observer.
149
236
  const dispose = () => {
150
237
  if (resolved) {
151
238
  return;
@@ -156,7 +243,7 @@ export async function installManifestInterceptor(page, timeout = INTERCEPTION_TI
156
243
  observer.dispose();
157
244
  resolve(null);
158
245
  };
159
- return { dispose, finalize, promise, [Symbol.dispose]: dispose };
246
+ return { dispose, finalize, markChannelSelectionStart, promise, [Symbol.dispose]: dispose };
160
247
  }
161
248
  /**
162
249
  * Awaits the first master HLS manifest whose URL satisfies the supplied predicate. Used by tune-verification paths where the caller has just clicked or
@@ -169,16 +256,17 @@ export async function installManifestInterceptor(page, timeout = INTERCEPTION_TI
169
256
  * @param page - The puppeteer page to monitor.
170
257
  * @param predicate - Test applied to each verified master manifest URL. Return true to accept the URL and resolve.
171
258
  * @param timeout - Maximum time in milliseconds to wait for a matching manifest.
259
+ * @param observeFactory - The HLS playlist observer factory (default observeHlsPlaylists); injectable so the verification state machine can run without a live browser.
172
260
  * @returns The matching URL, or null on timeout.
173
261
  */
174
- export async function awaitMatchingManifest(page, predicate, timeout = VERIFICATION_TIMEOUT) {
262
+ export async function awaitMatchingManifest(page, predicate, timeout = VERIFICATION_TIMEOUT, observeFactory = observeHlsPlaylists) {
175
263
  const elapsed = startTimer();
176
264
  let resolved = false;
177
265
  const { promise, resolve } = Promise.withResolvers();
178
266
  // Tune verification is a multi-channel concept that only applies to master playlists - direct-tune media-only sources do not run a guide-click verification
179
267
  // step because the page navigation itself selects the channel. We reject media playlists at the consumer level rather than asking the observer to filter so
180
268
  // the observer keeps a single canonical contract (forward all recognized HLS playlists with their kind).
181
- const observer = await observeHlsPlaylists(page, {
269
+ const observer = await observeFactory(page, {
182
270
  logCategory: "native:intercept",
183
271
  onPlaylist: (playlist) => {
184
272
  if (resolved) {
@@ -1 +1 @@
1
- {"version":3,"file":"manifestInterceptor.js","sourceRoot":"","sources":["../../src/browser/manifestInterceptor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifestInterceptor.js","sourceRoot":"","sources":["../../src/browser/manifestInterceptor.ts"],"names":[],"mappings":"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"}