@bnhf/prismcast 1.3.4-2026.2.19

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 (234) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +347 -0
  3. package/bin/prismcast +6 -0
  4. package/dist/app.d.ts +6 -0
  5. package/dist/app.js +315 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/browser/cdp.d.ts +38 -0
  8. package/dist/browser/cdp.js +155 -0
  9. package/dist/browser/cdp.js.map +1 -0
  10. package/dist/browser/channelSelection.d.ts +65 -0
  11. package/dist/browser/channelSelection.js +202 -0
  12. package/dist/browser/channelSelection.js.map +1 -0
  13. package/dist/browser/display.d.ts +34 -0
  14. package/dist/browser/display.js +54 -0
  15. package/dist/browser/display.js.map +1 -0
  16. package/dist/browser/index.d.ts +205 -0
  17. package/dist/browser/index.js +1205 -0
  18. package/dist/browser/index.js.map +1 -0
  19. package/dist/browser/tuning/fox.d.ts +2 -0
  20. package/dist/browser/tuning/fox.js +83 -0
  21. package/dist/browser/tuning/fox.js.map +1 -0
  22. package/dist/browser/tuning/hbo.d.ts +2 -0
  23. package/dist/browser/tuning/hbo.js +237 -0
  24. package/dist/browser/tuning/hbo.js.map +1 -0
  25. package/dist/browser/tuning/hulu.d.ts +2 -0
  26. package/dist/browser/tuning/hulu.js +550 -0
  27. package/dist/browser/tuning/hulu.js.map +1 -0
  28. package/dist/browser/tuning/sling.d.ts +2 -0
  29. package/dist/browser/tuning/sling.js +518 -0
  30. package/dist/browser/tuning/sling.js.map +1 -0
  31. package/dist/browser/tuning/thumbnailRow.d.ts +2 -0
  32. package/dist/browser/tuning/thumbnailRow.js +108 -0
  33. package/dist/browser/tuning/thumbnailRow.js.map +1 -0
  34. package/dist/browser/tuning/tileClick.d.ts +2 -0
  35. package/dist/browser/tuning/tileClick.js +103 -0
  36. package/dist/browser/tuning/tileClick.js.map +1 -0
  37. package/dist/browser/tuning/youtubeTv.d.ts +2 -0
  38. package/dist/browser/tuning/youtubeTv.js +182 -0
  39. package/dist/browser/tuning/youtubeTv.js.map +1 -0
  40. package/dist/browser/video.d.ts +289 -0
  41. package/dist/browser/video.js +996 -0
  42. package/dist/browser/video.js.map +1 -0
  43. package/dist/channels/index.d.ts +3 -0
  44. package/dist/channels/index.js +392 -0
  45. package/dist/channels/index.js.map +1 -0
  46. package/dist/config/index.d.ts +53 -0
  47. package/dist/config/index.js +233 -0
  48. package/dist/config/index.js.map +1 -0
  49. package/dist/config/presets.d.ts +98 -0
  50. package/dist/config/presets.js +241 -0
  51. package/dist/config/presets.js.map +1 -0
  52. package/dist/config/profiles.d.ts +79 -0
  53. package/dist/config/profiles.js +245 -0
  54. package/dist/config/profiles.js.map +1 -0
  55. package/dist/config/providers.d.ts +120 -0
  56. package/dist/config/providers.js +450 -0
  57. package/dist/config/providers.js.map +1 -0
  58. package/dist/config/sites.d.ts +22 -0
  59. package/dist/config/sites.js +377 -0
  60. package/dist/config/sites.js.map +1 -0
  61. package/dist/config/userChannels.d.ts +178 -0
  62. package/dist/config/userChannels.js +543 -0
  63. package/dist/config/userChannels.js.map +1 -0
  64. package/dist/config/userConfig.d.ts +235 -0
  65. package/dist/config/userConfig.js +913 -0
  66. package/dist/config/userConfig.js.map +1 -0
  67. package/dist/hdhr/channelMap.d.ts +21 -0
  68. package/dist/hdhr/channelMap.js +82 -0
  69. package/dist/hdhr/channelMap.js.map +1 -0
  70. package/dist/hdhr/deviceId.d.ts +11 -0
  71. package/dist/hdhr/deviceId.js +84 -0
  72. package/dist/hdhr/deviceId.js.map +1 -0
  73. package/dist/hdhr/discover.d.ts +6 -0
  74. package/dist/hdhr/discover.js +155 -0
  75. package/dist/hdhr/discover.js.map +1 -0
  76. package/dist/hdhr/index.d.ts +9 -0
  77. package/dist/hdhr/index.js +87 -0
  78. package/dist/hdhr/index.js.map +1 -0
  79. package/dist/index.d.ts +1 -0
  80. package/dist/index.js +144 -0
  81. package/dist/index.js.map +1 -0
  82. package/dist/routes/assets.d.ts +6 -0
  83. package/dist/routes/assets.js +79 -0
  84. package/dist/routes/assets.js.map +1 -0
  85. package/dist/routes/auth.d.ts +6 -0
  86. package/dist/routes/auth.js +77 -0
  87. package/dist/routes/auth.js.map +1 -0
  88. package/dist/routes/channels.d.ts +6 -0
  89. package/dist/routes/channels.js +40 -0
  90. package/dist/routes/channels.js.map +1 -0
  91. package/dist/routes/components.d.ts +138 -0
  92. package/dist/routes/components.js +210 -0
  93. package/dist/routes/components.js.map +1 -0
  94. package/dist/routes/config.d.ts +72 -0
  95. package/dist/routes/config.js +1977 -0
  96. package/dist/routes/config.js.map +1 -0
  97. package/dist/routes/debug.d.ts +6 -0
  98. package/dist/routes/debug.js +274 -0
  99. package/dist/routes/debug.js.map +1 -0
  100. package/dist/routes/health.d.ts +6 -0
  101. package/dist/routes/health.js +85 -0
  102. package/dist/routes/health.js.map +1 -0
  103. package/dist/routes/hls.d.ts +6 -0
  104. package/dist/routes/hls.js +25 -0
  105. package/dist/routes/hls.js.map +1 -0
  106. package/dist/routes/index.d.ts +19 -0
  107. package/dist/routes/index.js +49 -0
  108. package/dist/routes/index.js.map +1 -0
  109. package/dist/routes/logs.d.ts +6 -0
  110. package/dist/routes/logs.js +164 -0
  111. package/dist/routes/logs.js.map +1 -0
  112. package/dist/routes/mpegts.d.ts +6 -0
  113. package/dist/routes/mpegts.js +19 -0
  114. package/dist/routes/mpegts.js.map +1 -0
  115. package/dist/routes/play.d.ts +6 -0
  116. package/dist/routes/play.js +18 -0
  117. package/dist/routes/play.js.map +1 -0
  118. package/dist/routes/playlist.d.ts +36 -0
  119. package/dist/routes/playlist.js +134 -0
  120. package/dist/routes/playlist.js.map +1 -0
  121. package/dist/routes/root.d.ts +6 -0
  122. package/dist/routes/root.js +2920 -0
  123. package/dist/routes/root.js.map +1 -0
  124. package/dist/routes/streams.d.ts +6 -0
  125. package/dist/routes/streams.js +88 -0
  126. package/dist/routes/streams.js.map +1 -0
  127. package/dist/routes/theme.d.ts +15 -0
  128. package/dist/routes/theme.js +275 -0
  129. package/dist/routes/theme.js.map +1 -0
  130. package/dist/routes/ui.d.ts +56 -0
  131. package/dist/routes/ui.js +354 -0
  132. package/dist/routes/ui.js.map +1 -0
  133. package/dist/service/commands.d.ts +41 -0
  134. package/dist/service/commands.js +391 -0
  135. package/dist/service/commands.js.map +1 -0
  136. package/dist/service/generators.d.ts +33 -0
  137. package/dist/service/generators.js +432 -0
  138. package/dist/service/generators.js.map +1 -0
  139. package/dist/service/index.d.ts +2 -0
  140. package/dist/service/index.js +7 -0
  141. package/dist/service/index.js.map +1 -0
  142. package/dist/streaming/clients.d.ts +48 -0
  143. package/dist/streaming/clients.js +114 -0
  144. package/dist/streaming/clients.js.map +1 -0
  145. package/dist/streaming/fmp4Segmenter.d.ts +61 -0
  146. package/dist/streaming/fmp4Segmenter.js +461 -0
  147. package/dist/streaming/fmp4Segmenter.js.map +1 -0
  148. package/dist/streaming/hls.d.ts +120 -0
  149. package/dist/streaming/hls.js +722 -0
  150. package/dist/streaming/hls.js.map +1 -0
  151. package/dist/streaming/hlsSegments.d.ts +54 -0
  152. package/dist/streaming/hlsSegments.js +162 -0
  153. package/dist/streaming/hlsSegments.js.map +1 -0
  154. package/dist/streaming/lifecycle.d.ts +33 -0
  155. package/dist/streaming/lifecycle.js +185 -0
  156. package/dist/streaming/lifecycle.js.map +1 -0
  157. package/dist/streaming/monitor.d.ts +74 -0
  158. package/dist/streaming/monitor.js +1310 -0
  159. package/dist/streaming/monitor.js.map +1 -0
  160. package/dist/streaming/mp4Parser.d.ts +74 -0
  161. package/dist/streaming/mp4Parser.js +566 -0
  162. package/dist/streaming/mp4Parser.js.map +1 -0
  163. package/dist/streaming/mpegts.d.ts +14 -0
  164. package/dist/streaming/mpegts.js +248 -0
  165. package/dist/streaming/mpegts.js.map +1 -0
  166. package/dist/streaming/registry.d.ts +119 -0
  167. package/dist/streaming/registry.js +127 -0
  168. package/dist/streaming/registry.js.map +1 -0
  169. package/dist/streaming/setup.d.ts +135 -0
  170. package/dist/streaming/setup.js +670 -0
  171. package/dist/streaming/setup.js.map +1 -0
  172. package/dist/streaming/showInfo.d.ts +30 -0
  173. package/dist/streaming/showInfo.js +362 -0
  174. package/dist/streaming/showInfo.js.map +1 -0
  175. package/dist/streaming/statusEmitter.d.ts +125 -0
  176. package/dist/streaming/statusEmitter.js +139 -0
  177. package/dist/streaming/statusEmitter.js.map +1 -0
  178. package/dist/types/index.d.ts +403 -0
  179. package/dist/types/index.js +6 -0
  180. package/dist/types/index.js.map +1 -0
  181. package/dist/utils/debugFilter.d.ts +38 -0
  182. package/dist/utils/debugFilter.js +157 -0
  183. package/dist/utils/debugFilter.js.map +1 -0
  184. package/dist/utils/delay.d.ts +6 -0
  185. package/dist/utils/delay.js +15 -0
  186. package/dist/utils/delay.js.map +1 -0
  187. package/dist/utils/errors.d.ts +15 -0
  188. package/dist/utils/errors.js +40 -0
  189. package/dist/utils/errors.js.map +1 -0
  190. package/dist/utils/evaluate.d.ts +51 -0
  191. package/dist/utils/evaluate.js +124 -0
  192. package/dist/utils/evaluate.js.map +1 -0
  193. package/dist/utils/ffmpeg.d.ts +65 -0
  194. package/dist/utils/ffmpeg.js +317 -0
  195. package/dist/utils/ffmpeg.js.map +1 -0
  196. package/dist/utils/fileLogger.d.ts +25 -0
  197. package/dist/utils/fileLogger.js +248 -0
  198. package/dist/utils/fileLogger.js.map +1 -0
  199. package/dist/utils/format.d.ts +16 -0
  200. package/dist/utils/format.js +46 -0
  201. package/dist/utils/format.js.map +1 -0
  202. package/dist/utils/html.d.ts +6 -0
  203. package/dist/utils/html.js +24 -0
  204. package/dist/utils/html.js.map +1 -0
  205. package/dist/utils/index.d.ts +15 -0
  206. package/dist/utils/index.js +20 -0
  207. package/dist/utils/index.js.map +1 -0
  208. package/dist/utils/logEmitter.d.ts +17 -0
  209. package/dist/utils/logEmitter.js +30 -0
  210. package/dist/utils/logEmitter.js.map +1 -0
  211. package/dist/utils/logger.d.ts +82 -0
  212. package/dist/utils/logger.js +219 -0
  213. package/dist/utils/logger.js.map +1 -0
  214. package/dist/utils/m3u.d.ts +32 -0
  215. package/dist/utils/m3u.js +148 -0
  216. package/dist/utils/m3u.js.map +1 -0
  217. package/dist/utils/morganStream.d.ts +7 -0
  218. package/dist/utils/morganStream.js +33 -0
  219. package/dist/utils/morganStream.js.map +1 -0
  220. package/dist/utils/platform.d.ts +64 -0
  221. package/dist/utils/platform.js +157 -0
  222. package/dist/utils/platform.js.map +1 -0
  223. package/dist/utils/retry.d.ts +15 -0
  224. package/dist/utils/retry.js +82 -0
  225. package/dist/utils/retry.js.map +1 -0
  226. package/dist/utils/streamContext.d.ts +28 -0
  227. package/dist/utils/streamContext.js +33 -0
  228. package/dist/utils/streamContext.js.map +1 -0
  229. package/dist/utils/version.d.ts +37 -0
  230. package/dist/utils/version.js +228 -0
  231. package/dist/utils/version.js.map +1 -0
  232. package/package.json +92 -0
  233. package/prismcast.png +0 -0
  234. package/prismcast.svg +74 -0
@@ -0,0 +1,46 @@
1
+ /* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
2
+ *
3
+ * format.ts: Formatting utilities for PrismCast.
4
+ */
5
+ /**
6
+ * Formats a duration in milliseconds as a human-readable string. The format varies based on duration length:
7
+ * - Less than 60 seconds: "17s"
8
+ * - Less than 1 hour: "6m 39s"
9
+ * - 1 hour or more: "1h 23m"
10
+ * @param ms - Duration in milliseconds.
11
+ * @returns Formatted duration string.
12
+ */
13
+ export function formatDuration(ms) {
14
+ const totalSeconds = Math.round(ms / 1000);
15
+ const hours = Math.floor(totalSeconds / 3600);
16
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
17
+ const seconds = totalSeconds % 60;
18
+ if (hours > 0) {
19
+ return [String(hours), "h ", String(minutes), "m"].join("");
20
+ }
21
+ if (minutes > 0) {
22
+ return [String(minutes), "m ", String(seconds), "s"].join("");
23
+ }
24
+ return [String(seconds), "s"].join("");
25
+ }
26
+ /**
27
+ * Extracts a concise domain from a URL by keeping only the last two portions of the hostname (e.g., "watch.foodnetwork.com" becomes "foodnetwork.com",
28
+ * "www.hulu.com" becomes "hulu.com"). Used as a standard domain key for DOMAIN_CONFIG lookups and as a display fallback when no provider name is configured.
29
+ * @param url - The URL to extract the domain from.
30
+ * @returns The concise domain, or the original URL if parsing fails.
31
+ */
32
+ export function extractDomain(url) {
33
+ try {
34
+ const hostname = new URL(url).hostname;
35
+ const parts = hostname.split(".");
36
+ // Keep only the last two parts (e.g., "foodnetwork.com"). For single-part hostnames (e.g., "localhost"), return as-is.
37
+ if (parts.length > 2) {
38
+ return parts.slice(-2).join(".");
39
+ }
40
+ return hostname;
41
+ }
42
+ catch {
43
+ return url;
44
+ }
45
+ }
46
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU;IAEvC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;IAElC,IAAG,KAAK,GAAG,CAAC,EAAE,CAAC;QAEb,OAAO,CAAE,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,IAAG,OAAO,GAAG,CAAC,EAAE,CAAC;QAEf,OAAO,CAAE,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,CAAE,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IAEvC,IAAI,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAElC,uHAAuH;QACvH,IAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAEpB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QAEP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Escapes HTML special characters in a string to prevent XSS when displaying user-provided or dynamic content in HTML.
3
+ * @param text - The text to escape.
4
+ * @returns The escaped text safe for HTML display.
5
+ */
6
+ export declare function escapeHtml(text: string): string;
@@ -0,0 +1,24 @@
1
+ /* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
2
+ *
3
+ * html.ts: HTML utilities for PrismCast.
4
+ */
5
+ /* This utility provides HTML escaping for safely embedding dynamic content in HTML responses.
6
+ */
7
+ /**
8
+ * Escapes HTML special characters in a string to prevent XSS when displaying user-provided or dynamic content in HTML.
9
+ * @param text - The text to escape.
10
+ * @returns The escaped text safe for HTML display.
11
+ */
12
+ export function escapeHtml(text) {
13
+ const replacements = {
14
+ "\"": """,
15
+ "&": "&",
16
+ "'": "'",
17
+ "<": "&lt;",
18
+ ">": "&gt;"
19
+ };
20
+ return text.replace(/[&<>"']/g, (char) => {
21
+ return replacements[char];
22
+ });
23
+ }
24
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/utils/html.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;GACG;AAEH;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IAErC,MAAM,YAAY,GAA2B;QAE3C,IAAI,EAAE,QAAQ;QACd,GAAG,EAAE,OAAO;QACZ,GAAG,EAAE,OAAO;QACZ,GAAG,EAAE,MAAM;QACX,GAAG,EAAE,MAAM;KACZ,CAAC;IAEF,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE;QAEvC,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,15 @@
1
+ export * from "./debugFilter.js";
2
+ export * from "./delay.js";
3
+ export * from "./errors.js";
4
+ export * from "./evaluate.js";
5
+ export * from "./ffmpeg.js";
6
+ export * from "./format.js";
7
+ export * from "./html.js";
8
+ export * from "./logEmitter.js";
9
+ export * from "./logger.js";
10
+ export * from "./m3u.js";
11
+ export * from "./morganStream.js";
12
+ export * from "./platform.js";
13
+ export * from "./retry.js";
14
+ export * from "./streamContext.js";
15
+ export * from "./version.js";
@@ -0,0 +1,20 @@
1
+ /* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
2
+ *
3
+ * index.ts: Utility module exports for PrismCast.
4
+ */
5
+ export * from "./debugFilter.js";
6
+ export * from "./delay.js";
7
+ export * from "./errors.js";
8
+ export * from "./evaluate.js";
9
+ export * from "./ffmpeg.js";
10
+ export * from "./format.js";
11
+ export * from "./html.js";
12
+ export * from "./logEmitter.js";
13
+ export * from "./logger.js";
14
+ export * from "./m3u.js";
15
+ export * from "./morganStream.js";
16
+ export * from "./platform.js";
17
+ export * from "./retry.js";
18
+ export * from "./streamContext.js";
19
+ export * from "./version.js";
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,mBAAmB,CAAC;AAClC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC"}
@@ -0,0 +1,17 @@
1
+ export interface LogEntry {
2
+ categoryTag?: string;
3
+ level: "debug" | "error" | "info" | "warn";
4
+ message: string;
5
+ timestamp: string;
6
+ }
7
+ /**
8
+ * Emits a log entry to all subscribed SSE clients.
9
+ * @param entry - The log entry to broadcast.
10
+ */
11
+ export declare function emitLogEntry(entry: LogEntry): void;
12
+ /**
13
+ * Subscribes a callback to receive log entries. Returns an unsubscribe function.
14
+ * @param callback - Function to call when a log entry is emitted.
15
+ * @returns A function to unsubscribe the callback.
16
+ */
17
+ export declare function subscribeToLogs(callback: (entry: LogEntry) => void): () => void;
@@ -0,0 +1,30 @@
1
+ /* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
2
+ *
3
+ * logEmitter.ts: Event emitter for real-time log streaming via SSE.
4
+ */
5
+ import { EventEmitter } from "events";
6
+ /* A singleton EventEmitter that broadcasts log entries to all subscribed SSE clients. When a log entry is written via LOG.info/warn/error, the entry is emitted here
7
+ * for real-time streaming to connected browsers.
8
+ */
9
+ const logEmitter = new EventEmitter();
10
+ // Increase the default listener limit to support many concurrent SSE connections. Each browser tab viewing the Logs tab will have its own listener.
11
+ logEmitter.setMaxListeners(100);
12
+ /**
13
+ * Emits a log entry to all subscribed SSE clients.
14
+ * @param entry - The log entry to broadcast.
15
+ */
16
+ export function emitLogEntry(entry) {
17
+ logEmitter.emit("log", entry);
18
+ }
19
+ /**
20
+ * Subscribes a callback to receive log entries. Returns an unsubscribe function.
21
+ * @param callback - Function to call when a log entry is emitted.
22
+ * @returns A function to unsubscribe the callback.
23
+ */
24
+ export function subscribeToLogs(callback) {
25
+ logEmitter.on("log", callback);
26
+ return () => {
27
+ logEmitter.off("log", callback);
28
+ };
29
+ }
30
+ //# sourceMappingURL=logEmitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logEmitter.js","sourceRoot":"","sources":["../../src/utils/logEmitter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AActC;;GAEG;AAEH,MAAM,UAAU,GAAG,IAAI,YAAY,EAAE,CAAC;AAEtC,oJAAoJ;AACpJ,UAAU,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;AAEhC;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAAe;IAE1C,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,QAAmC;IAEjE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAE/B,OAAO,GAAS,EAAE;QAEhB,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Sets the logging mode. When true, logs go to console with colors. When false, logs go to the file logger.
3
+ * @param enabled - True to enable console logging, false for file logging.
4
+ */
5
+ export declare function setConsoleLogging(enabled: boolean): void;
6
+ /**
7
+ * Returns whether console logging is currently enabled.
8
+ * @returns True if using console logging, false if using file logging.
9
+ */
10
+ export declare function isConsoleLogging(): boolean;
11
+ /**
12
+ * Enables or disables debug logging. When called with true, initializes the debug filter with wildcard (*) to enable all categories.
13
+ * @param enabled - True to enable all debug logging, false to disable.
14
+ */
15
+ export declare function setDebugLogging(enabled: boolean): void;
16
+ /**
17
+ * Returns whether any debug logging is currently enabled.
18
+ * @returns True if any debug categories are enabled, false otherwise.
19
+ */
20
+ export declare function isDebugLogging(): boolean;
21
+ /**
22
+ * Bound logger interface returned by LOG.withStreamId(). Provides the same logging methods but with a fixed stream ID.
23
+ */
24
+ interface BoundLogger {
25
+ debug: (category: string, message: string, ...args: unknown[]) => void;
26
+ error: (message: string, ...args: unknown[]) => void;
27
+ info: (message: string, ...args: unknown[]) => void;
28
+ warn: (message: string, ...args: unknown[]) => void;
29
+ }
30
+ export declare const LOG: {
31
+ /**
32
+ * Logs a debug message in cyan, filtered by category. Debug messages are only output when the specified category is enabled via the PRISMCAST_DEBUG environment
33
+ * variable or the --debug CLI flag (which enables all categories). Use this for verbose diagnostic information that would clutter normal logs.
34
+ *
35
+ * Stream ID is automatically included if running within a stream context (established by runWithStreamContext()).
36
+ * @param category - The debug category (e.g., "tuning:hulu", "recovery:tab", "streaming:segmenter").
37
+ * @param message - The format string (supports %s, %d, %j, %o).
38
+ * @param args - Values to interpolate into the format string.
39
+ */
40
+ debug: (category: string, message: string, ...args: unknown[]) => void;
41
+ /**
42
+ * Logs an error message in red. Use this for critical failures that prevent normal operation, such as browser crashes, navigation failures after all retries, or
43
+ * stream initialization errors. The red color provides immediate visual indication of serious problems requiring attention.
44
+ *
45
+ * Stream ID is automatically included if running within a stream context (established by runWithStreamContext()).
46
+ * @param message - The format string (supports %s, %d, %j, %o).
47
+ * @param args - Values to interpolate into the format string.
48
+ */
49
+ error: (message: string, ...args: unknown[]) => void;
50
+ /**
51
+ * Logs an informational message in the default terminal color. Use this for normal operational messages like startup notifications, successful operations, and
52
+ * status updates.
53
+ *
54
+ * Stream ID is automatically included if running within a stream context (established by runWithStreamContext()).
55
+ * @param message - The format string (supports %s, %d, %j, %o).
56
+ * @param args - Values to interpolate into the format string.
57
+ */
58
+ info: (message: string, ...args: unknown[]) => void;
59
+ /**
60
+ * Logs a warning message in yellow. Use this for non-critical issues that do not prevent operation but indicate potential problems, such as timeouts that were
61
+ * recovered from, missing optional features, or degraded functionality.
62
+ *
63
+ * Stream ID is automatically included if running within a stream context (established by runWithStreamContext()).
64
+ * @param message - The format string (supports %s, %d, %j, %o).
65
+ * @param args - Values to interpolate into the format string.
66
+ */
67
+ warn: (message: string, ...args: unknown[]) => void;
68
+ /**
69
+ * Creates a bound logger with a fixed stream ID. Use this when logging about a stream from outside its async context, such as when iterating over multiple streams
70
+ * in a disconnect handler or cleanup routine.
71
+ *
72
+ * Example:
73
+ * const streamLog = LOG.withStreamId(streamId);
74
+ * streamLog.warn("Terminating stream due to browser disconnect.");
75
+ * streamLog.info("Cleanup complete.");
76
+ *
77
+ * @param streamId - The stream ID to include in all log messages.
78
+ * @returns A logger object with debug, error, warn, and info methods that include the specified stream ID.
79
+ */
80
+ withStreamId: (streamId: string) => BoundLogger;
81
+ };
82
+ export {};
@@ -0,0 +1,219 @@
1
+ /* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
2
+ *
3
+ * logger.ts: Logging utilities with color-coded output for PrismCast.
4
+ */
5
+ import { initDebugFilter, isAnyDebugEnabled, isCategoryEnabled } from "./debugFilter.js";
6
+ import { emitLogEntry } from "./logEmitter.js";
7
+ import { format } from "util";
8
+ import { getStreamId } from "./streamContext.js";
9
+ import { writeLogEntry } from "./fileLogger.js";
10
+ /* Terminal color codes for log output formatting. Warnings appear in yellow and errors in red, making it easy to spot issues when scanning log output. The reset
11
+ * code restores the default color after each colored message to prevent color bleeding into subsequent output.
12
+ */
13
+ const ANSI_COLORS = {
14
+ cyan: "\x1b[36m",
15
+ red: "\x1b[31m",
16
+ reset: "\x1b[0m",
17
+ yellow: "\x1b[33m"
18
+ };
19
+ /* The logger can operate in two modes: console mode (output to stdout/stderr with colors) or file mode (output to ~/.prismcast/prismcast.log). By default, file mode
20
+ * is used. Console mode is enabled via the --console CLI flag for Docker deployments or interactive debugging.
21
+ */
22
+ // Flag indicating whether to use console logging instead of file logging.
23
+ let useConsoleLogging = false;
24
+ /**
25
+ * Sets the logging mode. When true, logs go to console with colors. When false, logs go to the file logger.
26
+ * @param enabled - True to enable console logging, false for file logging.
27
+ */
28
+ export function setConsoleLogging(enabled) {
29
+ useConsoleLogging = enabled;
30
+ }
31
+ /**
32
+ * Returns whether console logging is currently enabled.
33
+ * @returns True if using console logging, false if using file logging.
34
+ */
35
+ export function isConsoleLogging() {
36
+ return useConsoleLogging;
37
+ }
38
+ /* Debug logging is controlled by the category-based filter system in debugFilter.ts. The --debug CLI flag enables all categories (equivalent to
39
+ * PRISMCAST_DEBUG=*), while the PRISMCAST_DEBUG environment variable allows fine-grained category selection.
40
+ */
41
+ /**
42
+ * Enables or disables debug logging. When called with true, initializes the debug filter with wildcard (*) to enable all categories.
43
+ * @param enabled - True to enable all debug logging, false to disable.
44
+ */
45
+ export function setDebugLogging(enabled) {
46
+ initDebugFilter(enabled ? "*" : "");
47
+ }
48
+ /**
49
+ * Returns whether any debug logging is currently enabled.
50
+ * @returns True if any debug categories are enabled, false otherwise.
51
+ */
52
+ export function isDebugLogging() {
53
+ return isAnyDebugEnabled();
54
+ }
55
+ /* The LOG object provides a centralized logging interface with color-coded output and printf-style format strings. All methods accept a format string followed by
56
+ * optional arguments, using Node's util.format() for interpolation. Supported format specifiers include %s (string), %d (number), %j (JSON), and %o (object).
57
+ *
58
+ * Stream context is automatically detected via AsyncLocalStorage. When running within a stream context (established by runWithStreamContext()), log messages are
59
+ * automatically prefixed with the stream ID for correlation across concurrent streaming sessions.
60
+ *
61
+ * For logging outside a stream context (e.g., iterating over streams in a disconnect handler), use LOG.withStreamId() to create a bound logger.
62
+ */
63
+ /**
64
+ * Formats the current time as a timestamp string matching the log file format.
65
+ * @returns A timestamp string in the format "YYYY/MM/DD HH:MM:ss.lll".
66
+ */
67
+ function formatTimestamp() {
68
+ const now = new Date();
69
+ const year = now.getFullYear();
70
+ const month = String(now.getMonth() + 1).padStart(2, "0");
71
+ const day = String(now.getDate()).padStart(2, "0");
72
+ const hours = String(now.getHours()).padStart(2, "0");
73
+ const minutes = String(now.getMinutes()).padStart(2, "0");
74
+ const seconds = String(now.getSeconds()).padStart(2, "0");
75
+ const ms = String(now.getMilliseconds()).padStart(3, "0");
76
+ return [year, "/", month, "/", day, " ", hours, ":", minutes, ":", seconds, ".", ms].join("");
77
+ }
78
+ /**
79
+ * Emits a log entry to SSE subscribers for real-time streaming.
80
+ * @param level - The log level.
81
+ * @param message - The formatted message.
82
+ * @param categoryTag - Optional debug category tag for category-filtered debug messages.
83
+ */
84
+ function emitToSubscribers(level, message, categoryTag) {
85
+ const entry = {
86
+ level,
87
+ message,
88
+ timestamp: formatTimestamp()
89
+ };
90
+ if (categoryTag) {
91
+ entry.categoryTag = categoryTag;
92
+ }
93
+ emitLogEntry(entry);
94
+ }
95
+ /**
96
+ * Core logging implementation shared by all log levels. Handles stream ID prefixing, SSE emission, and output routing.
97
+ * @param level - The log level (error, warn, info, debug).
98
+ * @param color - ANSI color code for console output (empty string for no color).
99
+ * @param message - The format string.
100
+ * @param args - Format arguments.
101
+ * @param explicitStreamId - Optional explicit stream ID (used by withStreamId helper).
102
+ * @param categoryTag - Optional debug category tag for category-filtered debug messages.
103
+ */
104
+ function logWithLevel(level, color, message, args, explicitStreamId, categoryTag) {
105
+ const streamId = explicitStreamId ?? getStreamId();
106
+ const formatted = args.length > 0 ? format(message, ...args) : message;
107
+ const logMessage = streamId ? ["[", streamId, "] ", formatted].join("") : formatted;
108
+ // Emit to SSE subscribers for real-time streaming.
109
+ emitToSubscribers(level, logMessage, categoryTag);
110
+ if (useConsoleLogging) {
111
+ /* eslint-disable no-console */
112
+ let consoleMethod;
113
+ switch (level) {
114
+ case "error": {
115
+ consoleMethod = console.error;
116
+ break;
117
+ }
118
+ case "warn": {
119
+ consoleMethod = console.warn;
120
+ break;
121
+ }
122
+ default: {
123
+ consoleMethod = console.log;
124
+ break;
125
+ }
126
+ }
127
+ /* eslint-enable no-console */
128
+ if (streamId && color) {
129
+ consoleMethod("%s[%s] %s%s", color, streamId, formatted, ANSI_COLORS.reset);
130
+ }
131
+ else if (streamId) {
132
+ consoleMethod("[%s] %s", streamId, formatted);
133
+ }
134
+ else if (color) {
135
+ consoleMethod("%s%s%s", color, formatted, ANSI_COLORS.reset);
136
+ }
137
+ else {
138
+ consoleMethod(formatted);
139
+ }
140
+ }
141
+ else {
142
+ writeLogEntry(level, logMessage, color || undefined, categoryTag);
143
+ }
144
+ }
145
+ export const LOG = {
146
+ /**
147
+ * Logs a debug message in cyan, filtered by category. Debug messages are only output when the specified category is enabled via the PRISMCAST_DEBUG environment
148
+ * variable or the --debug CLI flag (which enables all categories). Use this for verbose diagnostic information that would clutter normal logs.
149
+ *
150
+ * Stream ID is automatically included if running within a stream context (established by runWithStreamContext()).
151
+ * @param category - The debug category (e.g., "tuning:hulu", "recovery:tab", "streaming:segmenter").
152
+ * @param message - The format string (supports %s, %d, %j, %o).
153
+ * @param args - Values to interpolate into the format string.
154
+ */
155
+ debug: function (category, message, ...args) {
156
+ if (!isAnyDebugEnabled() || !isCategoryEnabled(category)) {
157
+ return;
158
+ }
159
+ logWithLevel("debug", ANSI_COLORS.cyan, message, args, undefined, category);
160
+ },
161
+ /**
162
+ * Logs an error message in red. Use this for critical failures that prevent normal operation, such as browser crashes, navigation failures after all retries, or
163
+ * stream initialization errors. The red color provides immediate visual indication of serious problems requiring attention.
164
+ *
165
+ * Stream ID is automatically included if running within a stream context (established by runWithStreamContext()).
166
+ * @param message - The format string (supports %s, %d, %j, %o).
167
+ * @param args - Values to interpolate into the format string.
168
+ */
169
+ error: function (message, ...args) {
170
+ logWithLevel("error", ANSI_COLORS.red, message, args);
171
+ },
172
+ /**
173
+ * Logs an informational message in the default terminal color. Use this for normal operational messages like startup notifications, successful operations, and
174
+ * status updates.
175
+ *
176
+ * Stream ID is automatically included if running within a stream context (established by runWithStreamContext()).
177
+ * @param message - The format string (supports %s, %d, %j, %o).
178
+ * @param args - Values to interpolate into the format string.
179
+ */
180
+ info: function (message, ...args) {
181
+ logWithLevel("info", "", message, args);
182
+ },
183
+ /**
184
+ * Logs a warning message in yellow. Use this for non-critical issues that do not prevent operation but indicate potential problems, such as timeouts that were
185
+ * recovered from, missing optional features, or degraded functionality.
186
+ *
187
+ * Stream ID is automatically included if running within a stream context (established by runWithStreamContext()).
188
+ * @param message - The format string (supports %s, %d, %j, %o).
189
+ * @param args - Values to interpolate into the format string.
190
+ */
191
+ warn: function (message, ...args) {
192
+ logWithLevel("warn", ANSI_COLORS.yellow, message, args);
193
+ },
194
+ /**
195
+ * Creates a bound logger with a fixed stream ID. Use this when logging about a stream from outside its async context, such as when iterating over multiple streams
196
+ * in a disconnect handler or cleanup routine.
197
+ *
198
+ * Example:
199
+ * const streamLog = LOG.withStreamId(streamId);
200
+ * streamLog.warn("Terminating stream due to browser disconnect.");
201
+ * streamLog.info("Cleanup complete.");
202
+ *
203
+ * @param streamId - The stream ID to include in all log messages.
204
+ * @returns A logger object with debug, error, warn, and info methods that include the specified stream ID.
205
+ */
206
+ withStreamId: function (streamId) {
207
+ return {
208
+ debug: (category, message, ...args) => {
209
+ if (isAnyDebugEnabled() && isCategoryEnabled(category)) {
210
+ logWithLevel("debug", ANSI_COLORS.cyan, message, args, streamId, category);
211
+ }
212
+ },
213
+ error: (message, ...args) => { logWithLevel("error", ANSI_COLORS.red, message, args, streamId); },
214
+ info: (message, ...args) => { logWithLevel("info", "", message, args, streamId); },
215
+ warn: (message, ...args) => { logWithLevel("warn", ANSI_COLORS.yellow, message, args, streamId); }
216
+ };
217
+ }
218
+ };
219
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAEzF,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;GAEG;AAEH,MAAM,WAAW,GAAG;IAElB,IAAI,EAAE,UAAU;IAChB,GAAG,EAAE,UAAU;IACf,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,UAAU;CACnB,CAAC;AAEF;;GAEG;AAEH,0EAA0E;AAC1E,IAAI,iBAAiB,GAAG,KAAK,CAAC;AAE9B;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAEhD,iBAAiB,GAAG,OAAO,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAE9B,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED;;GAEG;AAEH;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAgB;IAE9C,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc;IAE5B,OAAO,iBAAiB,EAAE,CAAC;AAC7B,CAAC;AAED;;;;;;;GAOG;AAEH;;;GAGG;AACH,SAAS,eAAe;IAEtB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1D,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAE1D,OAAO,CAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAClG,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,KAAwB,EAAE,OAAe,EAAE,WAAoB;IAExF,MAAM,KAAK,GAAa;QAEtB,KAAK;QACL,OAAO;QACP,SAAS,EAAE,eAAe,EAAE;KAC7B,CAAC;IAEF,IAAG,WAAW,EAAE,CAAC;QAEf,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;IAClC,CAAC;IAED,YAAY,CAAC,KAAK,CAAC,CAAC;AACtB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,KAAwB,EAAE,KAAa,EAAE,OAAe,EAAE,IAAe,EAAE,gBAAyB,EAAE,WAAoB;IAE9I,MAAM,QAAQ,GAAG,gBAAgB,IAAI,WAAW,EAAE,CAAC;IACnD,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACvE,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,CAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAEtF,mDAAmD;IACnD,iBAAiB,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAElD,IAAG,iBAAiB,EAAE,CAAC;QAErB,+BAA+B;QAC/B,IAAI,aAAa,CAAC;QAElB,QAAO,KAAK,EAAE,CAAC;YAEb,KAAK,OAAO,CAAC,CAAC,CAAC;gBAEb,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC;gBAE9B,MAAM;YACR,CAAC;YAED,KAAK,MAAM,CAAC,CAAC,CAAC;gBAEZ,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;gBAE7B,MAAM;YACR,CAAC;YAED,OAAO,CAAC,CAAC,CAAC;gBAER,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC;gBAE5B,MAAM;YACR,CAAC;QACH,CAAC;QACD,8BAA8B;QAE9B,IAAG,QAAQ,IAAI,KAAK,EAAE,CAAC;YAErB,aAAa,CAAC,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;QAC9E,CAAC;aAAM,IAAG,QAAQ,EAAE,CAAC;YAEnB,aAAa,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QAChD,CAAC;aAAM,IAAG,KAAK,EAAE,CAAC;YAEhB,aAAa,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;QAC/D,CAAC;aAAM,CAAC;YAEN,aAAa,CAAC,SAAS,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;SAAM,CAAC;QAEN,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,IAAI,SAAS,EAAE,WAAW,CAAC,CAAC;IACpE,CAAC;AACH,CAAC;AAaD,MAAM,CAAC,MAAM,GAAG,GAAG;IAEjB;;;;;;;;OAQG;IACH,KAAK,EAAE,UAAS,QAAgB,EAAE,OAAe,EAAE,GAAG,IAAe;QAEnE,IAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAExD,OAAO;QACT,CAAC;QAED,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC9E,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,EAAE,UAAS,OAAe,EAAE,GAAG,IAAe;QAEjD,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACxD,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,EAAE,UAAS,OAAe,EAAE,GAAG,IAAe;QAEhD,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,EAAE,UAAS,OAAe,EAAE,GAAG,IAAe;QAEhD,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED;;;;;;;;;;;OAWG;IACH,YAAY,EAAE,UAAS,QAAgB;QAErC,OAAO;YAEL,KAAK,EAAE,CAAC,QAAgB,EAAE,OAAe,EAAE,GAAG,IAAe,EAAQ,EAAE;gBAErE,IAAG,iBAAiB,EAAE,IAAI,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAEtD,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBAC7E,CAAC;YACH,CAAC;YACD,KAAK,EAAE,CAAC,OAAe,EAAE,GAAG,IAAe,EAAQ,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC1H,IAAI,EAAE,CAAC,OAAe,EAAE,GAAG,IAAe,EAAQ,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC3G,IAAI,EAAE,CAAC,OAAe,EAAE,GAAG,IAAe,EAAQ,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;SAC5H,CAAC;IACJ,CAAC;CACF,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Represents a channel parsed from an M3U playlist.
3
+ */
4
+ export interface M3UChannel {
5
+ name: string;
6
+ stationId?: string;
7
+ url: string;
8
+ }
9
+ /**
10
+ * Result of parsing an M3U playlist.
11
+ */
12
+ export interface M3UParseResult {
13
+ channels: M3UChannel[];
14
+ errors: string[];
15
+ }
16
+ /**
17
+ * Generates a URL-safe channel key from a display name. The key is used as the channel identifier in URLs and configuration.
18
+ * @param name - The display name to convert.
19
+ * @returns A lowercase, hyphen-separated key suitable for URLs.
20
+ *
21
+ * Examples:
22
+ * - "CNN Live!" → "cnn-live"
23
+ * - "BBC News 24/7" → "bbc-news-247"
24
+ * - " Spaces Everywhere " → "spaces-everywhere"
25
+ */
26
+ export declare function generateChannelKey(name: string): string;
27
+ /**
28
+ * Parses an M3U playlist and extracts channel information. Handles extended M3U format with #EXTINF tags.
29
+ * @param content - The M3U file content as a string.
30
+ * @returns Parse result containing channels and any errors encountered.
31
+ */
32
+ export declare function parseM3U(content: string): M3UParseResult;