prismcast 1.9.0 → 1.10.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 (360) hide show
  1. package/dist/app.d.ts +1 -1
  2. package/dist/app.js +27 -9
  3. package/dist/app.js.map +1 -1
  4. package/dist/browser/cdp.js +7 -7
  5. package/dist/browser/cdp.js.map +1 -1
  6. package/dist/browser/channelSelection.d.ts +41 -11
  7. package/dist/browser/channelSelection.js +75 -24
  8. package/dist/browser/channelSelection.js.map +1 -1
  9. package/dist/browser/display.d.ts +1 -1
  10. package/dist/browser/index.d.ts +8 -8
  11. package/dist/browser/index.js +42 -43
  12. package/dist/browser/index.js.map +1 -1
  13. package/dist/browser/login.d.ts +2 -2
  14. package/dist/browser/login.js +1 -1
  15. package/dist/browser/manifestInterceptor.d.ts +77 -0
  16. package/dist/browser/manifestInterceptor.js +323 -0
  17. package/dist/browser/manifestInterceptor.js.map +1 -0
  18. package/dist/browser/precaching.js +4 -4
  19. package/dist/browser/tuning/comcastPolymer.d.ts +1 -1
  20. package/dist/browser/tuning/cox.d.ts +1 -1
  21. package/dist/browser/tuning/directv.d.ts +1 -1
  22. package/dist/browser/tuning/directv.js +61 -62
  23. package/dist/browser/tuning/directv.js.map +1 -1
  24. package/dist/browser/tuning/fox.d.ts +1 -1
  25. package/dist/browser/tuning/fox.js +171 -14
  26. package/dist/browser/tuning/fox.js.map +1 -1
  27. package/dist/browser/tuning/hbo.d.ts +1 -1
  28. package/dist/browser/tuning/hbo.js +6 -6
  29. package/dist/browser/tuning/hbo.js.map +1 -1
  30. package/dist/browser/tuning/hulu.d.ts +1 -1
  31. package/dist/browser/tuning/hulu.js +117 -110
  32. package/dist/browser/tuning/hulu.js.map +1 -1
  33. package/dist/browser/tuning/shared.d.ts +3 -3
  34. package/dist/browser/tuning/shared.js +5 -5
  35. package/dist/browser/tuning/sling.d.ts +1 -1
  36. package/dist/browser/tuning/sling.js +28 -28
  37. package/dist/browser/tuning/sling.js.map +1 -1
  38. package/dist/browser/tuning/spectrum.d.ts +1 -1
  39. package/dist/browser/tuning/spectrum.js +21 -22
  40. package/dist/browser/tuning/spectrum.js.map +1 -1
  41. package/dist/browser/tuning/thumbnailRow.d.ts +1 -1
  42. package/dist/browser/tuning/thumbnailRow.js +1 -1
  43. package/dist/browser/tuning/tileClick.d.ts +1 -1
  44. package/dist/browser/tuning/tileClick.js +5 -5
  45. package/dist/browser/tuning/xfinity.d.ts +1 -1
  46. package/dist/browser/tuning/youtubeTv.d.ts +1 -1
  47. package/dist/browser/tuning/youtubeTv.js +17 -18
  48. package/dist/browser/tuning/youtubeTv.js.map +1 -1
  49. package/dist/browser/video.d.ts +20 -6
  50. package/dist/browser/video.js +30 -38
  51. package/dist/browser/video.js.map +1 -1
  52. package/dist/channels/index.d.ts +1 -2
  53. package/dist/channels/index.js +73 -40
  54. package/dist/channels/index.js.map +1 -1
  55. package/dist/config/channelForm.d.ts +58 -0
  56. package/dist/config/channelForm.js +129 -0
  57. package/dist/config/channelForm.js.map +1 -0
  58. package/dist/config/consistencyProbe.d.ts +7 -0
  59. package/dist/config/consistencyProbe.js +143 -0
  60. package/dist/config/consistencyProbe.js.map +1 -0
  61. package/dist/config/health.d.ts +4 -3
  62. package/dist/config/health.js +75 -62
  63. package/dist/config/health.js.map +1 -1
  64. package/dist/config/index.d.ts +1 -1
  65. package/dist/config/index.js +19 -12
  66. package/dist/config/index.js.map +1 -1
  67. package/dist/config/paths.d.ts +9 -3
  68. package/dist/config/paths.js +12 -4
  69. package/dist/config/paths.js.map +1 -1
  70. package/dist/config/persistence.context.d.ts +8 -0
  71. package/dist/config/persistence.context.js +30 -0
  72. package/dist/config/persistence.context.js.map +1 -0
  73. package/dist/config/persistence.d.ts +110 -12
  74. package/dist/config/persistence.js +351 -32
  75. package/dist/config/persistence.js.map +1 -1
  76. package/dist/config/presets.d.ts +14 -4
  77. package/dist/config/presets.js +84 -75
  78. package/dist/config/presets.js.map +1 -1
  79. package/dist/config/profiles.d.ts +2 -2
  80. package/dist/config/profiles.js +7 -9
  81. package/dist/config/profiles.js.map +1 -1
  82. package/dist/config/servicePacks.d.ts +2 -2
  83. package/dist/config/servicePacks.js +28 -28
  84. package/dist/config/servicePacks.js.map +1 -1
  85. package/dist/config/services.d.ts +62 -36
  86. package/dist/config/services.js +150 -136
  87. package/dist/config/services.js.map +1 -1
  88. package/dist/config/sites.d.ts +3 -3
  89. package/dist/config/sites.js +16 -16
  90. package/dist/config/sites.js.map +1 -1
  91. package/dist/config/userChannels.d.ts +500 -41
  92. package/dist/config/userChannels.js +1201 -312
  93. package/dist/config/userChannels.js.map +1 -1
  94. package/dist/config/userConfig.d.ts +103 -10
  95. package/dist/config/userConfig.js +277 -117
  96. package/dist/config/userConfig.js.map +1 -1
  97. package/dist/config/userProfiles.d.ts +4 -2
  98. package/dist/config/userProfiles.js +72 -26
  99. package/dist/config/userProfiles.js.map +1 -1
  100. package/dist/hdhr/channelMap.js +8 -11
  101. package/dist/hdhr/channelMap.js.map +1 -1
  102. package/dist/hdhr/deviceId.js +10 -9
  103. package/dist/hdhr/deviceId.js.map +1 -1
  104. package/dist/hdhr/discover.js +4 -5
  105. package/dist/hdhr/discover.js.map +1 -1
  106. package/dist/hdhr/index.js +6 -10
  107. package/dist/hdhr/index.js.map +1 -1
  108. package/dist/index.js +12 -12
  109. package/dist/index.js.map +1 -1
  110. package/dist/native/codecInference.d.ts +44 -0
  111. package/dist/native/codecInference.js +327 -0
  112. package/dist/native/codecInference.js.map +1 -0
  113. package/dist/native/decrypt.d.ts +1 -1
  114. package/dist/native/index.d.ts +5 -5
  115. package/dist/native/index.js +42 -64
  116. package/dist/native/index.js.map +1 -1
  117. package/dist/native/probe.d.ts +27 -9
  118. package/dist/native/probe.js +158 -67
  119. package/dist/native/probe.js.map +1 -1
  120. package/dist/native/proxy.d.ts +4 -2
  121. package/dist/native/proxy.js +52 -49
  122. package/dist/native/proxy.js.map +1 -1
  123. package/dist/native/tokenExpiry.d.ts +22 -0
  124. package/dist/native/tokenExpiry.js +153 -0
  125. package/dist/native/tokenExpiry.js.map +1 -0
  126. package/dist/routes/auth.js +6 -10
  127. package/dist/routes/auth.js.map +1 -1
  128. package/dist/routes/components.js +2 -2
  129. package/dist/routes/components.js.map +1 -1
  130. package/dist/routes/config/channels/endpoints/browse.d.ts +6 -0
  131. package/dist/routes/config/channels/endpoints/browse.js +195 -0
  132. package/dist/routes/config/channels/endpoints/browse.js.map +1 -0
  133. package/dist/routes/config/channels/endpoints/bulk.d.ts +6 -0
  134. package/dist/routes/config/channels/endpoints/bulk.js +128 -0
  135. package/dist/routes/config/channels/endpoints/bulk.js.map +1 -0
  136. package/dist/routes/config/channels/endpoints/crud.d.ts +6 -0
  137. package/dist/routes/config/channels/endpoints/crud.js +504 -0
  138. package/dist/routes/config/channels/endpoints/crud.js.map +1 -0
  139. package/dist/routes/config/channels/endpoints/importExport.d.ts +6 -0
  140. package/dist/routes/config/channels/endpoints/importExport.js +131 -0
  141. package/dist/routes/config/channels/endpoints/importExport.js.map +1 -0
  142. package/dist/routes/config/channels/endpoints/predefined.d.ts +6 -0
  143. package/dist/routes/config/channels/endpoints/predefined.js +78 -0
  144. package/dist/routes/config/channels/endpoints/predefined.js.map +1 -0
  145. package/dist/routes/config/channels/endpoints/prefs.d.ts +6 -0
  146. package/dist/routes/config/channels/endpoints/prefs.js +58 -0
  147. package/dist/routes/config/channels/endpoints/prefs.js.map +1 -0
  148. package/dist/routes/config/channels/endpoints/service.d.ts +6 -0
  149. package/dist/routes/config/channels/endpoints/service.js +149 -0
  150. package/dist/routes/config/channels/endpoints/service.js.map +1 -0
  151. package/dist/routes/config/channels/endpoints/tags.d.ts +6 -0
  152. package/dist/routes/config/channels/endpoints/tags.js +185 -0
  153. package/dist/routes/config/channels/endpoints/tags.js.map +1 -0
  154. package/dist/routes/config/channels/http/handler.d.ts +10 -0
  155. package/dist/routes/config/channels/http/handler.js +20 -0
  156. package/dist/routes/config/channels/http/handler.js.map +1 -0
  157. package/dist/routes/config/channels/http/playlistHint.d.ts +25 -0
  158. package/dist/routes/config/channels/http/playlistHint.js +40 -0
  159. package/dist/routes/config/channels/http/playlistHint.js.map +1 -0
  160. package/dist/routes/config/channels/http/serviceWarning.d.ts +10 -0
  161. package/dist/routes/config/channels/http/serviceWarning.js +28 -0
  162. package/dist/routes/config/channels/http/serviceWarning.js.map +1 -0
  163. package/dist/routes/config/channels/index.d.ts +3 -3
  164. package/dist/routes/config/channels/index.js +1 -1
  165. package/dist/routes/config/channels/index.js.map +1 -1
  166. package/dist/routes/config/channels/{routes.d.ts → setup.d.ts} +1 -1
  167. package/dist/routes/config/channels/setup.js +23 -0
  168. package/dist/routes/config/channels/setup.js.map +1 -0
  169. package/dist/routes/config/channels/table.d.ts +9 -9
  170. package/dist/routes/config/channels/table.js +124 -76
  171. package/dist/routes/config/channels/table.js.map +1 -1
  172. package/dist/routes/config/http/envelope.d.ts +111 -0
  173. package/dist/routes/config/http/envelope.js +103 -0
  174. package/dist/routes/config/http/envelope.js.map +1 -0
  175. package/dist/routes/config/index.d.ts +9 -9
  176. package/dist/routes/config/index.js +2 -2
  177. package/dist/routes/config/index.js.map +1 -1
  178. package/dist/routes/config/services.js +69 -68
  179. package/dist/routes/config/services.js.map +1 -1
  180. package/dist/routes/config/settings.d.ts +1 -1
  181. package/dist/routes/config/settings.js +45 -38
  182. package/dist/routes/config/settings.js.map +1 -1
  183. package/dist/routes/debug.js +12 -11
  184. package/dist/routes/debug.js.map +1 -1
  185. package/dist/routes/icons.js +2 -2
  186. package/dist/routes/icons.js.map +1 -1
  187. package/dist/routes/logs.js +19 -30
  188. package/dist/routes/logs.js.map +1 -1
  189. package/dist/routes/mpegts.js +1 -1
  190. package/dist/routes/playlist.d.ts +1 -1
  191. package/dist/routes/playlist.js +37 -26
  192. package/dist/routes/playlist.js.map +1 -1
  193. package/dist/routes/root/content.js +27 -6
  194. package/dist/routes/root/content.js.map +1 -1
  195. package/dist/routes/root/index.js +2 -5
  196. package/dist/routes/root/index.js.map +1 -1
  197. package/dist/routes/root/scripts/channels.js +16 -16
  198. package/dist/routes/root/scripts/channels.js.map +1 -1
  199. package/dist/routes/root/scripts/config.js +59 -59
  200. package/dist/routes/root/scripts/config.js.map +1 -1
  201. package/dist/routes/root/scripts/index.d.ts +4 -4
  202. package/dist/routes/root/scripts/shared.js +24 -10
  203. package/dist/routes/root/scripts/shared.js.map +1 -1
  204. package/dist/routes/root/scripts/status.d.ts +4 -0
  205. package/dist/routes/root/scripts/status.handlers.d.ts +182 -0
  206. package/dist/routes/root/scripts/status.handlers.js +713 -0
  207. package/dist/routes/root/scripts/status.handlers.js.map +1 -0
  208. package/dist/routes/root/scripts/status.js +86 -488
  209. package/dist/routes/root/scripts/status.js.map +1 -1
  210. package/dist/routes/root/styles.js +5 -5
  211. package/dist/routes/services.js +18 -15
  212. package/dist/routes/services.js.map +1 -1
  213. package/dist/routes/sse.d.ts +16 -0
  214. package/dist/routes/sse.js +29 -0
  215. package/dist/routes/sse.js.map +1 -0
  216. package/dist/routes/streams.js +10 -23
  217. package/dist/routes/streams.js.map +1 -1
  218. package/dist/routes/ui.d.ts +2 -2
  219. package/dist/routes/upgrade.js +6 -7
  220. package/dist/routes/upgrade.js.map +1 -1
  221. package/dist/service/commands.context.d.ts +6 -0
  222. package/dist/service/commands.context.js +47 -0
  223. package/dist/service/commands.context.js.map +1 -0
  224. package/dist/service/commands.d.ts +53 -8
  225. package/dist/service/commands.js +171 -188
  226. package/dist/service/commands.js.map +1 -1
  227. package/dist/service/generators.context.d.ts +6 -0
  228. package/dist/service/generators.context.js +45 -0
  229. package/dist/service/generators.context.js.map +1 -0
  230. package/dist/service/generators.d.ts +56 -16
  231. package/dist/service/generators.js +499 -383
  232. package/dist/service/generators.js.map +1 -1
  233. package/dist/service/index.d.ts +2 -2
  234. package/dist/streaming/clients.d.ts +2 -2
  235. package/dist/streaming/clients.js +2 -2
  236. package/dist/streaming/codec.d.ts +2 -2
  237. package/dist/streaming/codec.js +0 -1
  238. package/dist/streaming/codec.js.map +1 -1
  239. package/dist/streaming/fmp4Segmenter.d.ts +2 -2
  240. package/dist/streaming/fmp4Segmenter.js +12 -12
  241. package/dist/streaming/hls.d.ts +3 -3
  242. package/dist/streaming/hls.js +81 -70
  243. package/dist/streaming/hls.js.map +1 -1
  244. package/dist/streaming/hlsResume.d.ts +3 -3
  245. package/dist/streaming/hlsResume.js +5 -5
  246. package/dist/streaming/hlsSegments.d.ts +5 -2
  247. package/dist/streaming/hlsSegments.js +14 -9
  248. package/dist/streaming/hlsSegments.js.map +1 -1
  249. package/dist/streaming/monitor.d.ts +12 -12
  250. package/dist/streaming/monitor.js +80 -54
  251. package/dist/streaming/monitor.js.map +1 -1
  252. package/dist/streaming/mp4Parser.d.ts +34 -4
  253. package/dist/streaming/mp4Parser.js +111 -29
  254. package/dist/streaming/mp4Parser.js.map +1 -1
  255. package/dist/streaming/mpegts.d.ts +1 -1
  256. package/dist/streaming/mpegts.js +13 -10
  257. package/dist/streaming/mpegts.js.map +1 -1
  258. package/dist/streaming/playlistBuilder.d.ts +1 -1
  259. package/dist/streaming/playlistBuilder.js +2 -2
  260. package/dist/streaming/preroll.d.ts +9 -9
  261. package/dist/streaming/preroll.js +39 -41
  262. package/dist/streaming/preroll.js.map +1 -1
  263. package/dist/streaming/pretune.js +4 -4
  264. package/dist/streaming/pretune.js.map +1 -1
  265. package/dist/streaming/recovery.d.ts +3 -3
  266. package/dist/streaming/recovery.js +4 -4
  267. package/dist/streaming/registry.d.ts +6 -6
  268. package/dist/streaming/setup.d.ts +9 -8
  269. package/dist/streaming/setup.js +97 -49
  270. package/dist/streaming/setup.js.map +1 -1
  271. package/dist/streaming/showInfo.d.ts +9 -3
  272. package/dist/streaming/showInfo.js +26 -18
  273. package/dist/streaming/showInfo.js.map +1 -1
  274. package/dist/streaming/statusEmitter.d.ts +4 -4
  275. package/dist/streaming/statusEmitter.js +2 -2
  276. package/dist/types/channels.d.ts +133 -34
  277. package/dist/types/channels.js +39 -1
  278. package/dist/types/channels.js.map +1 -1
  279. package/dist/types/config.d.ts +20 -1
  280. package/dist/types/index.d.ts +9 -8
  281. package/dist/types/index.js +1 -0
  282. package/dist/types/index.js.map +1 -1
  283. package/dist/types/profiles.d.ts +5 -4
  284. package/dist/types/selection.d.ts +48 -4
  285. package/dist/types/streaming.d.ts +1 -1
  286. package/dist/upgrade/commands.context.d.ts +6 -0
  287. package/dist/upgrade/commands.context.js +29 -0
  288. package/dist/upgrade/commands.context.js.map +1 -0
  289. package/dist/upgrade/commands.d.ts +29 -2
  290. package/dist/upgrade/commands.js +87 -134
  291. package/dist/upgrade/commands.js.map +1 -1
  292. package/dist/upgrade/detection.context.d.ts +6 -0
  293. package/dist/upgrade/detection.context.js +24 -0
  294. package/dist/upgrade/detection.context.js.map +1 -0
  295. package/dist/upgrade/detection.d.ts +140 -10
  296. package/dist/upgrade/detection.js +153 -66
  297. package/dist/upgrade/detection.js.map +1 -1
  298. package/dist/upgrade/index.d.ts +2 -2
  299. package/dist/utils/chromeFetch.d.ts +1 -1
  300. package/dist/utils/chromeFetch.js +1 -1
  301. package/dist/utils/clock.d.ts +14 -0
  302. package/dist/utils/clock.js +28 -0
  303. package/dist/utils/clock.js.map +1 -0
  304. package/dist/utils/debugFilter.d.ts +1 -1
  305. package/dist/utils/debugFilter.js +6 -4
  306. package/dist/utils/debugFilter.js.map +1 -1
  307. package/dist/utils/delay.d.ts +2 -3
  308. package/dist/utils/delay.js +10 -16
  309. package/dist/utils/delay.js.map +1 -1
  310. package/dist/utils/evaluate.js +12 -14
  311. package/dist/utils/evaluate.js.map +1 -1
  312. package/dist/utils/ffmpeg.context.d.ts +6 -0
  313. package/dist/utils/ffmpeg.context.js +31 -0
  314. package/dist/utils/ffmpeg.context.js.map +1 -0
  315. package/dist/utils/ffmpeg.d.ts +85 -29
  316. package/dist/utils/ffmpeg.js +126 -129
  317. package/dist/utils/ffmpeg.js.map +1 -1
  318. package/dist/utils/fileLogger.d.ts +18 -2
  319. package/dist/utils/fileLogger.js +58 -30
  320. package/dist/utils/fileLogger.js.map +1 -1
  321. package/dist/utils/format.d.ts +1 -1
  322. package/dist/utils/format.js +2 -2
  323. package/dist/utils/format.js.map +1 -1
  324. package/dist/utils/html.js +1 -3
  325. package/dist/utils/html.js.map +1 -1
  326. package/dist/utils/index.d.ts +21 -20
  327. package/dist/utils/index.js +1 -0
  328. package/dist/utils/index.js.map +1 -1
  329. package/dist/utils/logger.js +16 -20
  330. package/dist/utils/logger.js.map +1 -1
  331. package/dist/utils/m3u.d.ts +18 -3
  332. package/dist/utils/m3u.js +28 -14
  333. package/dist/utils/m3u.js.map +1 -1
  334. package/dist/utils/memo.d.ts +19 -0
  335. package/dist/utils/memo.js +53 -0
  336. package/dist/utils/memo.js.map +1 -0
  337. package/dist/utils/morganStream.js +2 -2
  338. package/dist/utils/morganStream.js.map +1 -1
  339. package/dist/utils/pid.d.ts +2 -2
  340. package/dist/utils/pid.js +2 -2
  341. package/dist/utils/platform.d.ts +1 -1
  342. package/dist/utils/platform.js +3 -3
  343. package/dist/utils/platform.js.map +1 -1
  344. package/dist/utils/retry.d.ts +2 -0
  345. package/dist/utils/retry.js +9 -7
  346. package/dist/utils/retry.js.map +1 -1
  347. package/dist/utils/sanitize.d.ts +2 -2
  348. package/dist/utils/sanitize.js +4 -4
  349. package/dist/utils/timing.d.ts +6 -3
  350. package/dist/utils/timing.js +10 -6
  351. package/dist/utils/timing.js.map +1 -1
  352. package/dist/utils/version.d.ts +3 -2
  353. package/dist/utils/version.js +14 -27
  354. package/dist/utils/version.js.map +1 -1
  355. package/package.json +13 -7
  356. package/dist/native/intercept.d.ts +0 -35
  357. package/dist/native/intercept.js +0 -181
  358. package/dist/native/intercept.js.map +0 -1
  359. package/dist/routes/config/channels/routes.js +0 -1505
  360. package/dist/routes/config/channels/routes.js.map +0 -1
@@ -0,0 +1,30 @@
1
+ import fs from "node:fs";
2
+ const { promises: fsPromises } = fs;
3
+ /**
4
+ * Builds the default StorageBackend wired to node:fs/promises. The returned adapter is stateless - every call delegates to fsPromises with the framework's
5
+ * documented contract (UTF-8 encoding for text I/O, recursive mkdir, native error propagation including the ENOENT code that the framework's branch detection
6
+ * relies on). Sharing one default instance across every store in the process is safe and cheap; persistence.ts caches a single one at module load.
7
+ * @returns A StorageBackend implementation backed by the real filesystem via node:fs/promises.
8
+ */
9
+ export function createDefaultStorageBackend() {
10
+ return {
11
+ access: async (path) => fsPromises.access(path),
12
+ copyFile: async (source, destination) => fsPromises.copyFile(source, destination),
13
+ mkdir: async (path) => {
14
+ // The framework only ever uses recursive mkdir, so the adapter bakes that in rather than exposing the options bag through the StorageBackend surface.
15
+ await fsPromises.mkdir(path, { recursive: true });
16
+ },
17
+ readFile: async (path) => fsPromises.readFile(path, "utf-8"),
18
+ readdir: async (path) => fsPromises.readdir(path),
19
+ rename: async (source, destination) => fsPromises.rename(source, destination),
20
+ stat: async (path) => {
21
+ // Project Stats down to the field the framework actually uses (mtimeMs for snapshot pruning). Hides the wider Stats surface so backend implementers do not
22
+ // have to fabricate fields that the framework would never read.
23
+ const result = await fsPromises.stat(path);
24
+ return { mtimeMs: result.mtimeMs };
25
+ },
26
+ unlink: async (path) => fsPromises.unlink(path),
27
+ writeFile: async (path, content) => fsPromises.writeFile(path, content, "utf-8")
28
+ };
29
+ }
30
+ //# sourceMappingURL=persistence.context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.context.js","sourceRoot":"","sources":["../../src/config/persistence.context.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B;IAEzC,OAAO;QAEL,MAAM,EAAE,KAAK,EAAE,IAAY,EAAiB,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;QAEtE,QAAQ,EAAE,KAAK,EAAE,MAAc,EAAE,WAAmB,EAAiB,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;QAEhH,KAAK,EAAE,KAAK,EAAE,IAAY,EAAiB,EAAE;YAE3C,sJAAsJ;YACtJ,MAAM,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,QAAQ,EAAE,KAAK,EAAE,IAAY,EAAmB,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;QAErF,OAAO,EAAE,KAAK,EAAE,IAAY,EAAqB,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC;QAE5E,MAAM,EAAE,KAAK,EAAE,MAAc,EAAE,WAAmB,EAAiB,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;QAE5G,IAAI,EAAE,KAAK,EAAE,IAAY,EAAgC,EAAE;YAEzD,2JAA2J;YAC3J,gEAAgE;YAChE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE3C,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QACrC,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,IAAY,EAAiB,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;QAEtE,SAAS,EAAE,KAAK,EAAE,IAAY,EAAE,OAAe,EAAiB,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC;KAChH,CAAC;AACJ,CAAC"}
@@ -1,59 +1,157 @@
1
1
  /**
2
- * Error thrown by `mutate()` when the backing file contains invalid JSON. Route handlers can catch this specifically to return 400 instead of 500. Background code
3
- * paths that swallow errors via try/catch will handle it like any other Error.
2
+ * Storage backend abstraction. The framework operates on any durable store that exposes the operations below over a path namespace - the default backend lives
3
+ * in persistence.context.ts and wires real-filesystem I/O via node:fs/promises, but the surface is intentionally narrow so alternative backends (for example, an
4
+ * in-memory backend used during tests, or a future object-store backend) can plug in without modifying the framework.
5
+ *
6
+ * Error contract: when a path is missing, throw a NodeJS.ErrnoException with `code: "ENOENT"` so the framework's existing branch detection (the read() ENOENT
7
+ * fast path, the doMutate ENOENT-tolerant backup copy, the snapshot ENOENT-tolerant source) continues to behave identically. All other failures (permission
8
+ * denied, I/O error, etc.) propagate as Error or NodeJS.ErrnoException with their native code so the framework's error logging surfaces accurate diagnostics.
9
+ *
10
+ * Encoding: every text operation is UTF-8 by contract. Backends do not accept other encodings - JSON is what the framework writes, and JSON is text.
11
+ */
12
+ export interface StorageBackend {
13
+ readonly access: (path: string) => Promise<void>;
14
+ readonly copyFile: (source: string, destination: string) => Promise<void>;
15
+ readonly mkdir: (path: string) => Promise<void>;
16
+ readonly readdir: (path: string) => Promise<string[]>;
17
+ readonly readFile: (path: string) => Promise<string>;
18
+ readonly rename: (source: string, destination: string) => Promise<void>;
19
+ readonly stat: (path: string) => Promise<{
20
+ mtimeMs: number;
21
+ }>;
22
+ readonly unlink: (path: string) => Promise<void>;
23
+ readonly writeFile: (path: string, content: string) => Promise<void>;
24
+ }
25
+ /**
26
+ * Error thrown by `mutate()` when the backing file contains invalid JSON and recovery from .bak also failed. Route handlers can catch this specifically to
27
+ * return 400 instead of 500. Background code paths that swallow errors via try/catch will handle it like any other Error.
4
28
  */
5
29
  export declare class FileStoreParseError extends Error {
6
30
  name: string;
7
31
  constructor(label: string, filePath: string, parseMessage: string);
8
32
  }
33
+ /**
34
+ * A single declarative schema migration. Migrations are keyed by their target schema version inside FileStoreOptions.migrations - the framework runs them in
35
+ * order from the file's current version up to the store's currentSchemaVersion, mutating the in-memory data in place and stamping the new version after each
36
+ * application.
37
+ */
38
+ export interface Migration<T> {
39
+ description: string;
40
+ apply: (data: T) => void;
41
+ }
42
+ /**
43
+ * The result of running migrations during a read operation.
44
+ */
45
+ export interface MigrationResult {
46
+ applied: string[];
47
+ fromVersion: number;
48
+ toVersion: number;
49
+ }
50
+ /**
51
+ * A single integrity issue detected by a store's validator. Surfaced via logging; the write proceeds regardless of severity.
52
+ */
53
+ export interface ValidationIssue {
54
+ category: string;
55
+ description: string;
56
+ severity: "warning" | "error";
57
+ }
9
58
  /**
10
59
  * Result from a read-only file store access. Callers that only need data (export endpoints, API responses) use this without risking a save-back.
11
60
  */
12
61
  export interface FileStoreReadResult<T> {
13
62
  data: T;
63
+ migrationResult: MigrationResult;
14
64
  parseError: boolean;
15
65
  parseErrorMessage?: string;
66
+ recoveredFromBackup: boolean;
16
67
  }
17
68
  /**
18
- * Options for creating a file store instance.
69
+ * Options for creating a file store instance. The first three fields (defaultValue, label, parse, path) are the minimum surface required for any store. The
70
+ * remaining fields opt in to schema versioning, migrations, and integrity validation - any store can adopt them as its data shape grows.
19
71
  * @template T - The in-memory data type that callers mutate.
20
72
  */
21
73
  export interface FileStoreOptions<T> {
74
+ backend?: StorageBackend;
22
75
  beforeWrite?: (data: T) => unknown;
76
+ currentSchemaVersion?: number;
23
77
  defaultValue: () => T;
78
+ getSchemaVersion?: (data: T) => number;
24
79
  label: string;
80
+ migrations?: Record<number, Migration<T>>;
25
81
  parse: (raw: string) => T;
26
82
  path: () => string;
83
+ recordMigration?: (data: T, description: string) => void;
84
+ setSchemaVersion?: (data: T, version: number) => void;
85
+ validate?: (prev: T, next: T) => ValidationIssue[];
27
86
  }
28
87
  /**
29
- * A transactional file store that provides atomic writes, serialized mutations, corruption protection, and backup rotation. Callers interact with data through
30
- * `mutate()` (serialized read-modify-write) and `read()` (read-only access). Direct file I/O is never exposed.
88
+ * A transactional file store that provides atomic writes, serialized mutations, corruption recovery, snapshots, declarative migrations, and integrity
89
+ * validation. Callers interact with data through `mutate()` (serialized read-modify-write) and `read()` (read-only access). Direct file I/O is never exposed.
31
90
  * @template T - The in-memory data type that callers mutate.
32
91
  */
33
92
  export interface FileStore<T> {
34
93
  /**
35
- * Serialized read-modify-write operation. The mutation function receives the current data and modifies it in place. The store handles atomicity,
36
- * serialization, corruption guard, backup, and beforeWrite transforms.
94
+ * Verifies migrations are up-to-date and persists the upgrade if any were applied. Idempotent - when the file is already at the current schema version this
95
+ * is a single read with no write. Called once per store at startup by the release boot coordinator after snapshots have been captured.
96
+ * @returns The migration result so callers can log per-store outcomes.
97
+ */
98
+ ensureMigrated(): Promise<MigrationResult>;
99
+ /**
100
+ * Serialized read-modify-write operation. The mutation function receives the current data (already migrated to the latest schema version) and modifies it in
101
+ * place. The store handles atomicity, serialization, corruption guard, backup, validation, and beforeWrite transforms.
37
102
  * @param fn - Mutation function. Receives current data. Modify in place; return value is ignored.
38
- * @throws FileStoreParseError if the file contains invalid JSON (corruption guard).
103
+ * @throws FileStoreParseError if the file contains invalid JSON and no usable backup is available (corruption guard).
39
104
  */
40
105
  mutate(fn: (current: T) => void): Promise<void>;
41
106
  /**
42
- * Read-only access to the current file contents. Returns the parsed data with parse status. Does not acquire the serialization lock...safe to call concurrently.
107
+ * Read-only access to the current file contents. Returns the parsed data with parse status, recovery status, and migration result. Does not acquire the
108
+ * serialization lock - safe to call concurrently. Migrations run in-memory but are not persisted by read() alone; callers who need to persist an upgrade
109
+ * should use ensureMigrated() (or do so implicitly via mutate()).
43
110
  */
44
111
  read(): Promise<FileStoreReadResult<T>>;
112
+ /**
113
+ * Creates a labeled snapshot copy of the current file inside a `snapshots/` subdirectory next to the source file (named `<file>.<label>`). Idempotent on
114
+ * the label - if a snapshot with the same label already exists, this is a no-op. After a successful create, prunes older snapshots for the same file so at
115
+ * most SNAPSHOT_RETENTION remain (by mtime). Used to preserve a guaranteed restore point at release boundaries before any migrations can mutate the file.
116
+ * @param label - The filename suffix appended after the source file's basename and a dot. Typically a version string like `pre-v1.10.0`.
117
+ */
118
+ snapshot(label: string): Promise<void>;
45
119
  }
120
+ /**
121
+ * Snapshots every registered store under the given label. Used at startup to capture a guaranteed restore point at release boundaries before any migrations
122
+ * can run. The label is typically `pre-v<package-version>` so each release boot leaves a snapshot named for the version that was running.
123
+ *
124
+ * Snapshots run in parallel since they are independent file copies. Failures within individual snapshots are logged by the snapshot helper itself and do not
125
+ * propagate; the coordinator always returns successfully so a single store's snapshot failure does not block startup.
126
+ * @param label - The snapshot label suffix.
127
+ */
128
+ export declare function snapshotAllForRelease(label: string): Promise<void>;
129
+ /**
130
+ * Runs ensureMigrated() on every registered store. Called once at startup after snapshotAllForRelease so that any pending migrations execute against a file
131
+ * that already has its pre-version snapshot captured. Idempotent within a release - subsequent boots see no pending migrations and skip the upgrade write.
132
+ */
133
+ export declare function ensureAllMigrated(): Promise<void>;
46
134
  /**
47
135
  * Creates a transactional file store instance. Each instance owns a single JSON file and provides serialized, atomic access to it.
48
136
  *
49
137
  * Safety guarantees:
50
138
  * - **Atomic writes:** data is written to a `.tmp` file and renamed over the original. `rename()` is atomic on POSIX and NTFS.
51
139
  * - **Serialization:** a promise chain ensures only one `mutate()` runs at a time. Concurrent callers queue behind the active operation.
52
- * - **Corruption guard:** `mutate()` throws `FileStoreParseError` if the file contains invalid JSON, preventing save-over-corrupt cascades.
53
- * - **Backup rotation:** before each write, the current file is copied to `.bak`. One-deep rotation provides a recovery path.
140
+ * - **Corruption guard:** `mutate()` throws `FileStoreParseError` if both the main file and its `.bak` are unparseable, preventing save-over-corrupt cascades.
141
+ * - **Backup rotation:** before each write, the current file is copied to `.bak`. One-deep rotation provides a recovery path for the previous good version.
142
+ * - **Auto-recovery:** when the main file fails to parse, `read()` transparently restores from `.bak` (atomic temp+rename) and surfaces `recoveredFromBackup`
143
+ * on the result so callers can banner the event. Only when both files are unparseable does the result fall back to defaults with `parseError: true`.
144
+ * - **Versioned snapshots:** `snapshot(label)` writes a copy of the current file into a `snapshots/` subdirectory, named `<file>.<label>`, idempotent on the
145
+ * label. After each successful create the directory is pruned to at most SNAPSHOT_RETENTION entries per file (by mtime).
146
+ * - **Declarative migrations:** when `migrations` and `currentSchemaVersion` are provided, `read()` runs any pending migrations in memory and returns the
147
+ * upgraded data. `ensureMigrated()` persists the upgrade if any were applied. Migrations are version-keyed and idempotent across boots.
148
+ * - **Pre-write validation:** when `validate` is provided, `mutate()` invokes it with the pre-mutation snapshot and post-mutation state, surfacing integrity
149
+ * issues via the log.
150
+ * - **Post-write integrity check:** after every successful rename, the file is read back and byte-compared against what was written. On mismatch, the .bak is
151
+ * restored and the call throws - catches encoder bugs, partial writes, and any filesystem-level corruption that happened during the write.
54
152
  *
55
153
  * @template T - The in-memory data type that callers mutate.
56
154
  * @param options - Store configuration.
57
- * @returns A FileStore instance with `read()` and `mutate()` methods.
155
+ * @returns A FileStore instance. Auto-registers in the global store registry so the release boot coordinator can snapshot it.
58
156
  */
59
157
  export declare function createFileStore<T>(options: FileStoreOptions<T>): FileStore<T>;