watch-tail 0.4.0 → 0.6.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 (381) hide show
  1. package/README.md +158 -0
  2. package/build/client/_app/immutable/assets/0.Dfts6BC4.css +2 -0
  3. package/build/client/_app/immutable/assets/0.Dfts6BC4.css.br +0 -0
  4. package/build/client/_app/immutable/assets/0.Dfts6BC4.css.gz +0 -0
  5. package/build/client/_app/immutable/assets/BrushContext.2tkUc39H.css +1 -0
  6. package/build/client/_app/immutable/assets/BrushContext.2tkUc39H.css.br +0 -0
  7. package/build/client/_app/immutable/assets/BrushContext.2tkUc39H.css.gz +0 -0
  8. package/build/client/_app/immutable/assets/ChartAnnotations.Bw8CGteN.css +1 -0
  9. package/build/client/_app/immutable/assets/ChartAnnotations.Bw8CGteN.css.br +0 -0
  10. package/build/client/_app/immutable/assets/ChartAnnotations.Bw8CGteN.css.gz +0 -0
  11. package/build/client/_app/immutable/assets/Circle.C5MKzgk2.css +1 -0
  12. package/build/client/_app/immutable/assets/Circle.C5MKzgk2.css.br +1 -0
  13. package/build/client/_app/immutable/assets/Circle.C5MKzgk2.css.gz +0 -0
  14. package/build/client/_app/immutable/assets/DefaultTooltip.CGOVIm3D.css +1 -0
  15. package/build/client/_app/immutable/assets/DefaultTooltip.CGOVIm3D.css.br +0 -0
  16. package/build/client/_app/immutable/assets/DefaultTooltip.CGOVIm3D.css.gz +0 -0
  17. package/build/client/_app/immutable/assets/EventScatter.DA5sZ1c0.css +1 -0
  18. package/build/client/_app/immutable/assets/EventScatter.DA5sZ1c0.css.br +0 -0
  19. package/build/client/_app/immutable/assets/EventScatter.DA5sZ1c0.css.gz +0 -0
  20. package/build/client/_app/immutable/assets/Labels.sEaJtb97.css +1 -0
  21. package/build/client/_app/immutable/assets/Labels.sEaJtb97.css.br +0 -0
  22. package/build/client/_app/immutable/assets/Labels.sEaJtb97.css.gz +0 -0
  23. package/build/client/_app/immutable/assets/Legend.DnhxhJ2I.css +1 -0
  24. package/build/client/_app/immutable/assets/Legend.DnhxhJ2I.css.br +0 -0
  25. package/build/client/_app/immutable/assets/Legend.DnhxhJ2I.css.gz +0 -0
  26. package/build/client/_app/immutable/assets/Path.B0wDzTrn.css +1 -0
  27. package/build/client/_app/immutable/assets/Path.B0wDzTrn.css.br +0 -0
  28. package/build/client/_app/immutable/assets/Path.B0wDzTrn.css.gz +0 -0
  29. package/build/client/_app/immutable/assets/TransformContext.1cjyViIk.css +1 -0
  30. package/build/client/_app/immutable/assets/TransformContext.1cjyViIk.css.br +0 -0
  31. package/build/client/_app/immutable/assets/TransformContext.1cjyViIk.css.gz +0 -0
  32. package/build/client/_app/immutable/assets/Voronoi.ce7atosu.css +1 -0
  33. package/build/client/_app/immutable/assets/Voronoi.ce7atosu.css.br +0 -0
  34. package/build/client/_app/immutable/assets/Voronoi.ce7atosu.css.gz +0 -0
  35. package/build/client/_app/immutable/chunks/Amq8zxdJ.js +1 -0
  36. package/build/client/_app/immutable/chunks/Amq8zxdJ.js.br +0 -0
  37. package/build/client/_app/immutable/chunks/Amq8zxdJ.js.gz +0 -0
  38. package/build/client/_app/immutable/chunks/B3p3umIY.js +1 -0
  39. package/build/client/_app/immutable/chunks/B3p3umIY.js.br +0 -0
  40. package/build/client/_app/immutable/chunks/B3p3umIY.js.gz +0 -0
  41. package/build/client/_app/immutable/chunks/B43Eeyih.js +1 -0
  42. package/build/client/_app/immutable/chunks/B43Eeyih.js.br +0 -0
  43. package/build/client/_app/immutable/chunks/B43Eeyih.js.gz +0 -0
  44. package/build/client/_app/immutable/chunks/B5q6rkQ-.js +1 -0
  45. package/build/client/_app/immutable/chunks/B5q6rkQ-.js.br +0 -0
  46. package/build/client/_app/immutable/chunks/B5q6rkQ-.js.gz +0 -0
  47. package/build/client/_app/immutable/chunks/BAynhd7i.js +1 -0
  48. package/build/client/_app/immutable/chunks/BAynhd7i.js.br +0 -0
  49. package/build/client/_app/immutable/chunks/BAynhd7i.js.gz +0 -0
  50. package/build/client/_app/immutable/chunks/BDlvDAqe.js +1 -0
  51. package/build/client/_app/immutable/chunks/BDlvDAqe.js.br +0 -0
  52. package/build/client/_app/immutable/chunks/BDlvDAqe.js.gz +0 -0
  53. package/build/client/_app/immutable/chunks/BGmgUZMc.js +10 -0
  54. package/build/client/_app/immutable/chunks/BGmgUZMc.js.br +0 -0
  55. package/build/client/_app/immutable/chunks/BGmgUZMc.js.gz +0 -0
  56. package/build/client/_app/immutable/chunks/BJpWBbAS.js +1 -0
  57. package/build/client/_app/immutable/chunks/BJpWBbAS.js.br +0 -0
  58. package/build/client/_app/immutable/chunks/BJpWBbAS.js.gz +0 -0
  59. package/build/client/_app/immutable/chunks/BOT2hFMn.js +1 -0
  60. package/build/client/_app/immutable/chunks/BOT2hFMn.js.br +0 -0
  61. package/build/client/_app/immutable/chunks/BOT2hFMn.js.gz +0 -0
  62. package/build/client/_app/immutable/chunks/BR2LaRms.js +1 -0
  63. package/build/client/_app/immutable/chunks/BR2LaRms.js.br +1 -0
  64. package/build/client/_app/immutable/chunks/BR2LaRms.js.gz +0 -0
  65. package/build/client/_app/immutable/chunks/BZFYtRPj.js +1 -0
  66. package/build/client/_app/immutable/chunks/BZFYtRPj.js.br +0 -0
  67. package/build/client/_app/immutable/chunks/BZFYtRPj.js.gz +0 -0
  68. package/build/client/_app/immutable/chunks/BjxZ_neZ.js +5 -0
  69. package/build/client/_app/immutable/chunks/BjxZ_neZ.js.br +0 -0
  70. package/build/client/_app/immutable/chunks/BjxZ_neZ.js.gz +0 -0
  71. package/build/client/_app/immutable/chunks/Bl052uUt.js +1 -0
  72. package/build/client/_app/immutable/chunks/Bl052uUt.js.br +0 -0
  73. package/build/client/_app/immutable/chunks/Bl052uUt.js.gz +0 -0
  74. package/build/client/_app/immutable/chunks/{Bw_9uNRP.js → BsH4MNzX.js} +1 -1
  75. package/build/client/_app/immutable/chunks/BsH4MNzX.js.br +0 -0
  76. package/build/client/_app/immutable/chunks/BsH4MNzX.js.gz +0 -0
  77. package/build/client/_app/immutable/chunks/ByhwhtiG.js +1 -0
  78. package/build/client/_app/immutable/chunks/ByhwhtiG.js.br +0 -0
  79. package/build/client/_app/immutable/chunks/ByhwhtiG.js.gz +0 -0
  80. package/build/client/_app/immutable/chunks/C1lycbEF.js +1 -0
  81. package/build/client/_app/immutable/chunks/C1lycbEF.js.br +0 -0
  82. package/build/client/_app/immutable/chunks/C1lycbEF.js.gz +0 -0
  83. package/build/client/_app/immutable/chunks/C58PZtCD.js +4 -0
  84. package/build/client/_app/immutable/chunks/C58PZtCD.js.br +0 -0
  85. package/build/client/_app/immutable/chunks/C58PZtCD.js.gz +0 -0
  86. package/build/client/_app/immutable/chunks/CCch3uox.js +1 -0
  87. package/build/client/_app/immutable/chunks/CCch3uox.js.br +0 -0
  88. package/build/client/_app/immutable/chunks/CCch3uox.js.gz +0 -0
  89. package/build/client/_app/immutable/chunks/CEU4ihsz.js +1 -0
  90. package/build/client/_app/immutable/chunks/CEU4ihsz.js.br +0 -0
  91. package/build/client/_app/immutable/chunks/CEU4ihsz.js.gz +0 -0
  92. package/build/client/_app/immutable/chunks/CG6rRxUy.js +2 -0
  93. package/build/client/_app/immutable/chunks/CG6rRxUy.js.br +0 -0
  94. package/build/client/_app/immutable/chunks/CG6rRxUy.js.gz +0 -0
  95. package/build/client/_app/immutable/chunks/CM5sQDq_.js +1 -0
  96. package/build/client/_app/immutable/chunks/CM5sQDq_.js.br +0 -0
  97. package/build/client/_app/immutable/chunks/CM5sQDq_.js.gz +0 -0
  98. package/build/client/_app/immutable/chunks/CT_NYh_-.js +1 -0
  99. package/build/client/_app/immutable/chunks/CT_NYh_-.js.br +0 -0
  100. package/build/client/_app/immutable/chunks/CT_NYh_-.js.gz +0 -0
  101. package/build/client/_app/immutable/chunks/CZIk93qi.js +1 -0
  102. package/build/client/_app/immutable/chunks/CZIk93qi.js.br +0 -0
  103. package/build/client/_app/immutable/chunks/CZIk93qi.js.gz +0 -0
  104. package/build/client/_app/immutable/chunks/C_aXFBl3.js +1 -0
  105. package/build/client/_app/immutable/chunks/C_aXFBl3.js.br +0 -0
  106. package/build/client/_app/immutable/chunks/C_aXFBl3.js.gz +0 -0
  107. package/build/client/_app/immutable/chunks/CqWPu3PG.js +1 -0
  108. package/build/client/_app/immutable/chunks/CqWPu3PG.js.br +1 -0
  109. package/build/client/_app/immutable/chunks/CqWPu3PG.js.gz +0 -0
  110. package/build/client/_app/immutable/chunks/CyncJW0D.js +1 -0
  111. package/build/client/_app/immutable/chunks/CyncJW0D.js.br +0 -0
  112. package/build/client/_app/immutable/chunks/CyncJW0D.js.gz +0 -0
  113. package/build/client/_app/immutable/chunks/D4sC5v3c.js +1 -0
  114. package/build/client/_app/immutable/chunks/D4sC5v3c.js.br +0 -0
  115. package/build/client/_app/immutable/chunks/D4sC5v3c.js.gz +0 -0
  116. package/build/client/_app/immutable/chunks/D76YLq-2.js +1 -0
  117. package/build/client/_app/immutable/chunks/D76YLq-2.js.br +0 -0
  118. package/build/client/_app/immutable/chunks/D76YLq-2.js.gz +0 -0
  119. package/build/client/_app/immutable/chunks/D8H_ivbb.js +1 -0
  120. package/build/client/_app/immutable/chunks/D8H_ivbb.js.br +0 -0
  121. package/build/client/_app/immutable/chunks/D8H_ivbb.js.gz +0 -0
  122. package/build/client/_app/immutable/chunks/DU0OQtdJ.js +1 -0
  123. package/build/client/_app/immutable/chunks/DU0OQtdJ.js.br +0 -0
  124. package/build/client/_app/immutable/chunks/DU0OQtdJ.js.gz +0 -0
  125. package/build/client/_app/immutable/chunks/Db0q5_zr.js +1 -0
  126. package/build/client/_app/immutable/chunks/Db0q5_zr.js.br +0 -0
  127. package/build/client/_app/immutable/chunks/Db0q5_zr.js.gz +0 -0
  128. package/build/client/_app/immutable/chunks/Dfvzj6n2.js +1 -0
  129. package/build/client/_app/immutable/chunks/Dfvzj6n2.js.br +0 -0
  130. package/build/client/_app/immutable/chunks/Dfvzj6n2.js.gz +0 -0
  131. package/build/client/_app/immutable/chunks/HclGiUj8.js +1 -0
  132. package/build/client/_app/immutable/chunks/HclGiUj8.js.br +0 -0
  133. package/build/client/_app/immutable/chunks/HclGiUj8.js.gz +0 -0
  134. package/build/client/_app/immutable/chunks/RobXhXPM.js +1 -0
  135. package/build/client/_app/immutable/chunks/RobXhXPM.js.br +1 -0
  136. package/build/client/_app/immutable/chunks/RobXhXPM.js.gz +0 -0
  137. package/build/client/_app/immutable/chunks/Y5urAfNy.js +1 -0
  138. package/build/client/_app/immutable/chunks/Y5urAfNy.js.br +0 -0
  139. package/build/client/_app/immutable/chunks/Y5urAfNy.js.gz +0 -0
  140. package/build/client/_app/immutable/chunks/Yk6ZJZnu.js +1 -0
  141. package/build/client/_app/immutable/chunks/Yk6ZJZnu.js.br +0 -0
  142. package/build/client/_app/immutable/chunks/Yk6ZJZnu.js.gz +0 -0
  143. package/build/client/_app/immutable/chunks/jO4fmY1N.js +1 -0
  144. package/build/client/_app/immutable/chunks/jO4fmY1N.js.br +0 -0
  145. package/build/client/_app/immutable/chunks/jO4fmY1N.js.gz +0 -0
  146. package/build/client/_app/immutable/chunks/pqiPC7Y8.js +3 -0
  147. package/build/client/_app/immutable/chunks/pqiPC7Y8.js.br +0 -0
  148. package/build/client/_app/immutable/chunks/pqiPC7Y8.js.gz +0 -0
  149. package/build/client/_app/immutable/chunks/snfmbqby.js +1 -0
  150. package/build/client/_app/immutable/chunks/snfmbqby.js.br +0 -0
  151. package/build/client/_app/immutable/chunks/snfmbqby.js.gz +0 -0
  152. package/build/client/_app/immutable/chunks/wx-wtMGx.js +15 -0
  153. package/build/client/_app/immutable/chunks/wx-wtMGx.js.br +0 -0
  154. package/build/client/_app/immutable/chunks/wx-wtMGx.js.gz +0 -0
  155. package/build/client/_app/immutable/chunks/yCfI4PCa.js +1 -0
  156. package/build/client/_app/immutable/chunks/yCfI4PCa.js.br +0 -0
  157. package/build/client/_app/immutable/chunks/yCfI4PCa.js.gz +0 -0
  158. package/build/client/_app/immutable/chunks/zHL7lw4G.js +1 -0
  159. package/build/client/_app/immutable/chunks/zHL7lw4G.js.br +0 -0
  160. package/build/client/_app/immutable/chunks/zHL7lw4G.js.gz +0 -0
  161. package/build/client/_app/immutable/entry/app.DFSifnlU.js +2 -0
  162. package/build/client/_app/immutable/entry/app.DFSifnlU.js.br +0 -0
  163. package/build/client/_app/immutable/entry/app.DFSifnlU.js.gz +0 -0
  164. package/build/client/_app/immutable/entry/start.2H5s3Lol.js +1 -0
  165. package/build/client/_app/immutable/entry/start.2H5s3Lol.js.br +1 -0
  166. package/build/client/_app/immutable/entry/start.2H5s3Lol.js.gz +0 -0
  167. package/build/client/_app/immutable/nodes/0.BN3NguWs.js +1 -0
  168. package/build/client/_app/immutable/nodes/0.BN3NguWs.js.br +0 -0
  169. package/build/client/_app/immutable/nodes/0.BN3NguWs.js.gz +0 -0
  170. package/build/client/_app/immutable/nodes/1.Djdw1GzA.js +1 -0
  171. package/build/client/_app/immutable/nodes/1.Djdw1GzA.js.br +0 -0
  172. package/build/client/_app/immutable/nodes/1.Djdw1GzA.js.gz +0 -0
  173. package/build/client/_app/immutable/nodes/2.CjvaJDQJ.js +4 -0
  174. package/build/client/_app/immutable/nodes/2.CjvaJDQJ.js.br +0 -0
  175. package/build/client/_app/immutable/nodes/2.CjvaJDQJ.js.gz +0 -0
  176. package/build/client/_app/version.json +1 -1
  177. package/build/client/_app/version.json.br +0 -0
  178. package/build/client/_app/version.json.gz +0 -0
  179. package/build/handler.js +9 -7
  180. package/build/handler.js.map +1 -1
  181. package/build/index.js +9 -7
  182. package/build/index.js.map +1 -1
  183. package/build/server/chunks/chunks/Arc.canvas.js-D6g58nSp.js +701 -0
  184. package/build/server/chunks/chunks/Arc.canvas.js-D6g58nSp.js.map +1 -0
  185. package/build/server/chunks/chunks/Arc.js-D78Cf_4M.js +31 -0
  186. package/build/server/chunks/chunks/Arc.js-D78Cf_4M.js.map +1 -0
  187. package/build/server/chunks/chunks/Bar.js-Cv73T8_D.js +448 -0
  188. package/build/server/chunks/chunks/Bar.js-Cv73T8_D.js.map +1 -0
  189. package/build/server/chunks/chunks/ChartAnnotations.js-Ci22VB_6.js +983 -0
  190. package/build/server/chunks/chunks/ChartAnnotations.js-Ci22VB_6.js.map +1 -0
  191. package/build/server/chunks/chunks/Circle.html.js-BjwyNRG3.js +355 -0
  192. package/build/server/chunks/chunks/Circle.html.js-BjwyNRG3.js.map +1 -0
  193. package/build/server/chunks/chunks/ClipPath.canvas.js-CFTBDWVU.js +170 -0
  194. package/build/server/chunks/chunks/ClipPath.canvas.js-CFTBDWVU.js.map +1 -0
  195. package/build/server/chunks/chunks/DefaultTooltip.js-0r5rbE-1.js +352 -0
  196. package/build/server/chunks/chunks/DefaultTooltip.js-0r5rbE-1.js.map +1 -0
  197. package/build/server/chunks/chunks/EventScatter.js-D3Jaw_Cw.js +7308 -0
  198. package/build/server/chunks/chunks/EventScatter.js-D3Jaw_Cw.js.map +1 -0
  199. package/build/server/chunks/chunks/Labels.js-DpagpV6d.js +497 -0
  200. package/build/server/chunks/chunks/Labels.js-DpagpV6d.js.map +1 -0
  201. package/build/server/chunks/chunks/Legend.js-BOpwpe5s.js +343 -0
  202. package/build/server/chunks/chunks/Legend.js-BOpwpe5s.js.map +1 -0
  203. package/build/server/chunks/chunks/Line.html.js-BM5tR11G.js +423 -0
  204. package/build/server/chunks/chunks/Line.html.js-BM5tR11G.js.map +1 -0
  205. package/build/server/chunks/chunks/Link.canvas.js-P8ySzEAw.js +756 -0
  206. package/build/server/chunks/chunks/Link.canvas.js-P8ySzEAw.js.map +1 -0
  207. package/build/server/chunks/chunks/Path.canvas.js-DNAtnEBt.js +1259 -0
  208. package/build/server/chunks/chunks/Path.canvas.js-DNAtnEBt.js.map +1 -0
  209. package/build/server/chunks/chunks/Points.html.js-CLbHD6OP.js +228 -0
  210. package/build/server/chunks/chunks/Points.html.js-CLbHD6OP.js.map +1 -0
  211. package/build/server/chunks/chunks/Points.js-e6g0Re6H.js +14 -0
  212. package/build/server/chunks/chunks/Points.js-e6g0Re6H.js.map +1 -0
  213. package/build/server/chunks/chunks/Points2.js-BMGdkzTE.js +25 -0
  214. package/build/server/chunks/chunks/Points2.js-BMGdkzTE.js.map +1 -0
  215. package/build/server/chunks/chunks/Rect.html.js-Q3UvRwNn.js +547 -0
  216. package/build/server/chunks/chunks/Rect.html.js-Q3UvRwNn.js.map +1 -0
  217. package/build/server/chunks/chunks/Spline.js-BuZPz2PJ.js +516 -0
  218. package/build/server/chunks/chunks/Spline.js-BuZPz2PJ.js.map +1 -0
  219. package/build/server/chunks/chunks/Text.html.js-C8xO5Nz6.js +847 -0
  220. package/build/server/chunks/chunks/Text.html.js-C8xO5Nz6.js.map +1 -0
  221. package/build/server/chunks/chunks/TooltipItem.js-T0cKLjLu.js +314 -0
  222. package/build/server/chunks/chunks/TooltipItem.js-T0cKLjLu.js.map +1 -0
  223. package/build/server/chunks/chunks/Voronoi.js-DevTsXQE.js +2052 -0
  224. package/build/server/chunks/chunks/Voronoi.js-DevTsXQE.js.map +1 -0
  225. package/build/server/chunks/chunks/archive.js-C2D-5edp.js +823 -0
  226. package/build/server/chunks/chunks/archive.js-C2D-5edp.js.map +1 -0
  227. package/build/server/chunks/chunks/array.js-CBp0H4t3.js +8 -0
  228. package/build/server/chunks/chunks/array.js-CBp0H4t3.js.map +1 -0
  229. package/build/server/chunks/chunks/attributes.js-BVWo7wbg.js +25 -0
  230. package/build/server/chunks/chunks/attributes.js-BVWo7wbg.js.map +1 -0
  231. package/build/server/chunks/chunks/{env2.js-DXveJt1Y.js → aws.js-DkPqAybc.js} +2 -59
  232. package/build/server/chunks/chunks/aws.js-DkPqAybc.js.map +1 -0
  233. package/build/server/chunks/chunks/band.js-C7izXphE.js +155 -0
  234. package/build/server/chunks/chunks/band.js-C7izXphE.js.map +1 -0
  235. package/build/server/chunks/chunks/centroid.js-BnGN3LH0.js +1356 -0
  236. package/build/server/chunks/chunks/centroid.js-BnGN3LH0.js.map +1 -0
  237. package/build/server/chunks/chunks/common.js-BWQB8Die.js +5760 -0
  238. package/build/server/chunks/chunks/common.js-BWQB8Die.js.map +1 -0
  239. package/build/server/chunks/chunks/env2.js-CcIskxOZ.js +60 -0
  240. package/build/server/chunks/chunks/env2.js-CcIskxOZ.js.map +1 -0
  241. package/build/server/chunks/chunks/{exports.js-CvFPPbaH.js → exports.js-ClPPfcHj.js} +6 -1
  242. package/build/server/chunks/chunks/exports.js-ClPPfcHj.js.map +1 -0
  243. package/build/server/chunks/chunks/group.js-DBFzWAox.js +30 -0
  244. package/build/server/chunks/chunks/group.js-DBFzWAox.js.map +1 -0
  245. package/build/server/chunks/chunks/index-server.js-DNLOKvM0.js +248 -0
  246. package/build/server/chunks/chunks/index-server.js-DNLOKvM0.js.map +1 -0
  247. package/build/server/chunks/chunks/index-server2.js-l0sNRNKZ.js +2 -0
  248. package/build/server/chunks/chunks/index-server2.js-l0sNRNKZ.js.map +1 -0
  249. package/build/server/chunks/chunks/{internal2.js-DZ8ZzzjN.js → internal.js-DZ8ZzzjN.js} +1 -1
  250. package/build/server/chunks/chunks/internal.js-DZ8ZzzjN.js.map +1 -0
  251. package/build/server/chunks/chunks/internal2.js-BPo5dcDi.js +188 -0
  252. package/build/server/chunks/chunks/internal2.js-BPo5dcDi.js.map +1 -0
  253. package/build/server/chunks/chunks/key.svelte.js-CWIvXc6L.js +695 -0
  254. package/build/server/chunks/chunks/key.svelte.js-CWIvXc6L.js.map +1 -0
  255. package/build/server/chunks/chunks/{internal.js-Cc3oBhL-.js → legacy-client.js-DJmDw3Zx.js} +13 -439
  256. package/build/server/chunks/chunks/legacy-client.js-DJmDw3Zx.js.map +1 -0
  257. package/build/server/chunks/chunks/level-filter.js-B3o2hyWD.js +313 -0
  258. package/build/server/chunks/chunks/level-filter.js-B3o2hyWD.js.map +1 -0
  259. package/build/server/chunks/chunks/lineRadial.js-Dm0GMqo3.js +126 -0
  260. package/build/server/chunks/chunks/lineRadial.js-Dm0GMqo3.js.map +1 -0
  261. package/build/server/chunks/chunks/linear.js-CTOKrHn9.js +1046 -0
  262. package/build/server/chunks/chunks/linear.js-CTOKrHn9.js.map +1 -0
  263. package/build/server/chunks/chunks/log-buffer.js-BI_gQOls.js +587 -0
  264. package/build/server/chunks/chunks/log-buffer.js-BI_gQOls.js.map +1 -0
  265. package/build/server/chunks/chunks/math.js-BqujbaBs.js +50 -0
  266. package/build/server/chunks/chunks/math.js-BqujbaBs.js.map +1 -0
  267. package/build/server/chunks/chunks/max.js-CuS0BpRI.js +11 -0
  268. package/build/server/chunks/chunks/max.js-CuS0BpRI.js.map +1 -0
  269. package/build/server/chunks/chunks/min.js-DZWt5tPl.js +11 -0
  270. package/build/server/chunks/chunks/min.js-DZWt5tPl.js.map +1 -0
  271. package/build/server/chunks/chunks/motion.svelte.js-DCHSFMu-.js +677 -0
  272. package/build/server/chunks/chunks/motion.svelte.js-DCHSFMu-.js.map +1 -0
  273. package/build/server/chunks/chunks/occlusion.js-DJ-AdK9u.js +33 -0
  274. package/build/server/chunks/chunks/occlusion.js-DJ-AdK9u.js.map +1 -0
  275. package/build/server/chunks/chunks/path.js-BizMrlzb.js +488 -0
  276. package/build/server/chunks/chunks/path.js-BizMrlzb.js.map +1 -0
  277. package/build/server/chunks/chunks/path2.js-pquT2Kg6.js +27 -0
  278. package/build/server/chunks/chunks/path2.js-pquT2Kg6.js.map +1 -0
  279. package/build/server/chunks/chunks/pointRadial.js-Deeu1LXx.js +7 -0
  280. package/build/server/chunks/chunks/pointRadial.js-Deeu1LXx.js.map +1 -0
  281. package/build/server/chunks/chunks/rect.svelte.js-zeS7FWjB.js +187 -0
  282. package/build/server/chunks/chunks/rect.svelte.js-zeS7FWjB.js.map +1 -0
  283. package/build/server/chunks/chunks/scales.svelte.js-D_1popPi.js +276 -0
  284. package/build/server/chunks/chunks/scales.svelte.js-D_1popPi.js.map +1 -0
  285. package/build/server/chunks/chunks/series-buckets.js-BjigySff.js +290 -0
  286. package/build/server/chunks/chunks/series-buckets.js-BjigySff.js.map +1 -0
  287. package/build/server/chunks/chunks/{server.js-ByNB8uti.js → server.js-CAEBuMIH.js} +167 -2
  288. package/build/server/chunks/chunks/server.js-CAEBuMIH.js.map +1 -0
  289. package/build/server/chunks/chunks/source.js-DZEVvuho.js +21 -0
  290. package/build/server/chunks/chunks/source.js-DZEVvuho.js.map +1 -0
  291. package/build/server/chunks/chunks/{state.js-9DxsWxU-.js → state.js-DgkwfYFo.js} +5 -4
  292. package/build/server/chunks/chunks/state.js-DgkwfYFo.js.map +1 -0
  293. package/build/server/chunks/chunks/types.js-x3GyGPOz.js +11 -0
  294. package/build/server/chunks/chunks/types.js-x3GyGPOz.js.map +1 -0
  295. package/build/server/chunks/entries/endpoints/api/archive/_server.ts.js-83Ch7djd.js +39 -0
  296. package/build/server/chunks/entries/endpoints/api/archive/_server.ts.js-83Ch7djd.js.map +1 -0
  297. package/build/server/chunks/entries/endpoints/api/health/{_server.ts.js-BOjix7GN.js → _server.ts.js-VctnBhIJ.js} +5 -4
  298. package/build/server/chunks/entries/endpoints/api/health/_server.ts.js-VctnBhIJ.js.map +1 -0
  299. package/build/server/chunks/entries/endpoints/api/identity/{_server.ts.js-g13uvmrX.js → _server.ts.js-Dt540Sio.js} +4 -3
  300. package/build/server/chunks/entries/endpoints/api/identity/_server.ts.js-Dt540Sio.js.map +1 -0
  301. package/build/server/chunks/entries/endpoints/api/log-groups/{_server.ts.js-CmHRxdZK.js → _server.ts.js-drLgUdvB.js} +57 -8
  302. package/build/server/chunks/entries/endpoints/api/log-groups/_server.ts.js-drLgUdvB.js.map +1 -0
  303. package/build/server/chunks/entries/endpoints/api/regions/{_server.ts.js-BgUwioxp.js → _server.ts.js-CBqfN6Pg.js} +5 -4
  304. package/build/server/chunks/entries/endpoints/api/regions/_server.ts.js-CBqfN6Pg.js.map +1 -0
  305. package/build/server/chunks/entries/endpoints/api/series/_server.ts.js-DOvBhEDU.js +225 -0
  306. package/build/server/chunks/entries/endpoints/api/series/_server.ts.js-DOvBhEDU.js.map +1 -0
  307. package/build/server/chunks/entries/endpoints/api/stream/{_server.ts.js-CIYo4C-0.js → _server.ts.js-BWRHawY8.js} +324 -223
  308. package/build/server/chunks/entries/endpoints/api/stream/_server.ts.js-BWRHawY8.js.map +1 -0
  309. package/build/server/chunks/entries/fallbacks/{error.svelte.js-CFonuZkV.js → error.svelte.js-CsCL5PMW.js} +7 -5
  310. package/build/server/chunks/entries/fallbacks/{error.svelte.js-CFonuZkV.js.map → error.svelte.js-CsCL5PMW.js.map} +1 -1
  311. package/build/server/chunks/entries/pages/{_layout.svelte.js-Dzluuq12.js → _layout.svelte.js-CBQpEToy.js} +2 -2
  312. package/build/server/chunks/entries/pages/{_layout.svelte.js-Dzluuq12.js.map → _layout.svelte.js-CBQpEToy.js.map} +1 -1
  313. package/build/server/chunks/entries/pages/_page.svelte.js-qqtU0apo.js +1641 -0
  314. package/build/server/chunks/entries/pages/_page.svelte.js-qqtU0apo.js.map +1 -0
  315. package/build/server/chunks/{handler-DS32NMsJ.js → handler-DlfTB05m.js} +3 -3
  316. package/build/server/chunks/{handler-DS32NMsJ.js.map → handler-DlfTB05m.js.map} +1 -1
  317. package/build/server/chunks/{index.js-HHu-yOEK.js → index.js-BMrd9hfO.js} +6 -5
  318. package/build/server/chunks/index.js-BMrd9hfO.js.map +1 -0
  319. package/build/server/chunks/{manifest.js-BUrA7Zyr.js → manifest.js-D1kCuVe5.js} +24 -10
  320. package/build/server/chunks/manifest.js-D1kCuVe5.js.map +1 -0
  321. package/build/server/chunks/nodes/0.js-CNFDDPj5.js +9 -0
  322. package/build/server/chunks/nodes/{0.js-gSRmrAt_.js.map → 0.js-CNFDDPj5.js.map} +1 -1
  323. package/build/server/chunks/nodes/1.js-B5FPLYnf.js +9 -0
  324. package/build/server/chunks/nodes/{1.js-D68K7Ad_.js.map → 1.js-B5FPLYnf.js.map} +1 -1
  325. package/build/server/chunks/nodes/2.js-BEuxzw6b.js +9 -0
  326. package/build/server/chunks/nodes/2.js-BEuxzw6b.js.map +1 -0
  327. package/dist/cli/completions.js +6 -0
  328. package/dist/cli/index.js +131 -88
  329. package/dist/cli/options.js +28 -2
  330. package/dist/cli/preflight.js +30 -0
  331. package/dist/cli/ui.js +18 -3
  332. package/dist/lib/cli/aws.js +12 -4
  333. package/dist/lib/log-buffer.js +443 -0
  334. package/dist/lib/log-format.js +185 -0
  335. package/dist/lib/types.js +0 -4
  336. package/package.json +6 -2
  337. package/build/client/_app/immutable/assets/0.BPmQoXaO.css +0 -2
  338. package/build/client/_app/immutable/assets/0.BPmQoXaO.css.br +0 -0
  339. package/build/client/_app/immutable/assets/0.BPmQoXaO.css.gz +0 -0
  340. package/build/client/_app/immutable/chunks/Bw_9uNRP.js.br +0 -0
  341. package/build/client/_app/immutable/chunks/Bw_9uNRP.js.gz +0 -0
  342. package/build/client/_app/immutable/chunks/De_x7GQi.js +0 -1
  343. package/build/client/_app/immutable/chunks/De_x7GQi.js.br +0 -0
  344. package/build/client/_app/immutable/chunks/De_x7GQi.js.gz +0 -0
  345. package/build/client/_app/immutable/chunks/ZAD2y5xJ.js +0 -3
  346. package/build/client/_app/immutable/chunks/ZAD2y5xJ.js.br +0 -0
  347. package/build/client/_app/immutable/chunks/ZAD2y5xJ.js.gz +0 -0
  348. package/build/client/_app/immutable/entry/app.Be166AxG.js +0 -2
  349. package/build/client/_app/immutable/entry/app.Be166AxG.js.br +0 -0
  350. package/build/client/_app/immutable/entry/app.Be166AxG.js.gz +0 -0
  351. package/build/client/_app/immutable/entry/start.clEDpQL9.js +0 -1
  352. package/build/client/_app/immutable/entry/start.clEDpQL9.js.br +0 -0
  353. package/build/client/_app/immutable/entry/start.clEDpQL9.js.gz +0 -0
  354. package/build/client/_app/immutable/nodes/0.BJ6Zdc8H.js +0 -1
  355. package/build/client/_app/immutable/nodes/0.BJ6Zdc8H.js.br +0 -4
  356. package/build/client/_app/immutable/nodes/0.BJ6Zdc8H.js.gz +0 -0
  357. package/build/client/_app/immutable/nodes/1.xMNWuLLz.js +0 -1
  358. package/build/client/_app/immutable/nodes/1.xMNWuLLz.js.br +0 -0
  359. package/build/client/_app/immutable/nodes/1.xMNWuLLz.js.gz +0 -0
  360. package/build/client/_app/immutable/nodes/2.CaxDXwmh.js +0 -5
  361. package/build/client/_app/immutable/nodes/2.CaxDXwmh.js.br +0 -0
  362. package/build/client/_app/immutable/nodes/2.CaxDXwmh.js.gz +0 -0
  363. package/build/server/chunks/chunks/env2.js-DXveJt1Y.js.map +0 -1
  364. package/build/server/chunks/chunks/exports.js-CvFPPbaH.js.map +0 -1
  365. package/build/server/chunks/chunks/internal.js-Cc3oBhL-.js.map +0 -1
  366. package/build/server/chunks/chunks/internal2.js-DZ8ZzzjN.js.map +0 -1
  367. package/build/server/chunks/chunks/server.js-ByNB8uti.js.map +0 -1
  368. package/build/server/chunks/chunks/state.js-9DxsWxU-.js.map +0 -1
  369. package/build/server/chunks/entries/endpoints/api/health/_server.ts.js-BOjix7GN.js.map +0 -1
  370. package/build/server/chunks/entries/endpoints/api/identity/_server.ts.js-g13uvmrX.js.map +0 -1
  371. package/build/server/chunks/entries/endpoints/api/log-groups/_server.ts.js-CmHRxdZK.js.map +0 -1
  372. package/build/server/chunks/entries/endpoints/api/regions/_server.ts.js-BgUwioxp.js.map +0 -1
  373. package/build/server/chunks/entries/endpoints/api/stream/_server.ts.js-CIYo4C-0.js.map +0 -1
  374. package/build/server/chunks/entries/pages/_page.svelte.js-CpwYbxbM.js +0 -1291
  375. package/build/server/chunks/entries/pages/_page.svelte.js-CpwYbxbM.js.map +0 -1
  376. package/build/server/chunks/index.js-HHu-yOEK.js.map +0 -1
  377. package/build/server/chunks/manifest.js-BUrA7Zyr.js.map +0 -1
  378. package/build/server/chunks/nodes/0.js-gSRmrAt_.js +0 -9
  379. package/build/server/chunks/nodes/1.js-D68K7Ad_.js +0 -9
  380. package/build/server/chunks/nodes/2.js-ChYsaaoC.js +0 -9
  381. package/build/server/chunks/nodes/2.js-ChYsaaoC.js.map +0 -1
@@ -0,0 +1,823 @@
1
+ import { d as detectRequestId, a as detectLevelWithSource, i as isLogLevel, L as LEVEL_RANK } from './log-buffer.js-BI_gQOls.js';
2
+ import { mkdirSync, statSync } from 'node:fs';
3
+ import { homedir } from 'node:os';
4
+ import { join, dirname } from 'node:path';
5
+ import { setTimeout } from 'node:timers/promises';
6
+ import { createHash } from 'node:crypto';
7
+
8
+ //#region src/lib/server/archive-sql.ts
9
+ /**
10
+ * SQL and row mapping for the local DuckDB archive.
11
+ *
12
+ * DuckDB is a native dependency and is loaded lazily by `archive.ts`; everything
13
+ * in this file is plain text and pure functions so the archive can be unit
14
+ * tested without the driver. Column order matters: {@link ARCHIVE_INSERT_COLUMNS}
15
+ * is the contract with {@link toArchiveParams}, and the `SELECT` in
16
+ * {@link buildPageQuery} uses the same names as {@link rowsToPage}.
17
+ *
18
+ * `level` and `request_id` are both derived from the message on the way in, and
19
+ * both may be NULL in an archive written by an older build. NULL does not mean
20
+ * the same thing for the two columns: for `level` it is a verdict ("this line
21
+ * carries no level"), while for `request_id` it means "not looked at yet", since
22
+ * the client can still detect an id in the message it renders. {@link rowsToPage}
23
+ * and the request-id backfill below are written from that difference.
24
+ */
25
+ /**
26
+ * Statements that bring a database file up to the current schema.
27
+ *
28
+ * Every statement is idempotent so an existing archive can be opened by a newer
29
+ * build without a migration step. `seq` orders events by arrival, which keeps
30
+ * paging stable when many events share a millisecond timestamp.
31
+ */
32
+ var ARCHIVE_SCHEMA = [
33
+ `CREATE SEQUENCE IF NOT EXISTS log_events_seq`,
34
+ `CREATE TABLE IF NOT EXISTS log_events (
35
+ region VARCHAR NOT NULL,
36
+ log_group VARCHAR NOT NULL,
37
+ log_stream VARCHAR,
38
+ event_key VARCHAR NOT NULL,
39
+ event_id VARCHAR,
40
+ timestamp_ms BIGINT NOT NULL,
41
+ ingestion_time_ms BIGINT,
42
+ message VARCHAR NOT NULL,
43
+ level VARCHAR,
44
+ level_source VARCHAR,
45
+ request_id VARCHAR,
46
+ seq BIGINT NOT NULL DEFAULT nextval('log_events_seq'),
47
+ archived_at TIMESTAMP NOT NULL DEFAULT now()
48
+ )`,
49
+ `ALTER TABLE log_events ADD COLUMN IF NOT EXISTS level VARCHAR`,
50
+ `ALTER TABLE log_events ADD COLUMN IF NOT EXISTS level_source VARCHAR`,
51
+ `ALTER TABLE log_events ADD COLUMN IF NOT EXISTS request_id VARCHAR`,
52
+ `CREATE TABLE IF NOT EXISTS archive_meta (key VARCHAR PRIMARY KEY, value VARCHAR)`,
53
+ `CREATE UNIQUE INDEX IF NOT EXISTS log_events_unique ON log_events (region, log_group, event_key)`,
54
+ `CREATE INDEX IF NOT EXISTS log_events_time ON log_events (region, log_group, timestamp_ms)`
55
+ ];
56
+ /** Columns written by {@link buildInsertSql}, in binding order. */
57
+ var ARCHIVE_INSERT_COLUMNS = [
58
+ "region",
59
+ "log_group",
60
+ "log_stream",
61
+ "event_key",
62
+ "event_id",
63
+ "timestamp_ms",
64
+ "ingestion_time_ms",
65
+ "message",
66
+ "level",
67
+ "level_source",
68
+ "request_id"
69
+ ];
70
+ /** Escape character used with `LIKE`/`ILIKE` so user input cannot inject wildcards. */
71
+ var LIKE_ESCAPE = "\\";
72
+ /**
73
+ * Stable identity of an event inside one log group.
74
+ *
75
+ * CloudWatch event ids are unique per log group and are reused as the key;
76
+ * events without an id (floci and LocalStack omit them) get a deterministic
77
+ * hash of timestamp, stream and message, so re-scanning the same window is
78
+ * idempotent instead of duplicating rows.
79
+ */
80
+ function archiveEventKey(event) {
81
+ if (event.id !== null && event.id.length > 0) return event.id;
82
+ return `h:${createHash("sha256").update(`${event.timestamp}\u0000${event.streamName ?? ""}\u0000${event.message}`).digest("hex").slice(0, 32)}`;
83
+ }
84
+ /** Renders `count` placeholder rows, one group of columns per row. */
85
+ function placeholderRows(count) {
86
+ const row = `(${ARCHIVE_INSERT_COLUMNS.map(() => "?").join(", ")})`;
87
+ return Array.from({ length: count }, () => row).join(", ");
88
+ }
89
+ /**
90
+ * Builds a multi-row `INSERT OR IGNORE`, so events already archived are skipped
91
+ * by the unique index instead of raising.
92
+ */
93
+ function buildInsertSql(rowCount) {
94
+ if (!Number.isInteger(rowCount) || rowCount < 1) throw new RangeError(`rowCount must be a positive integer, received ${String(rowCount)}`);
95
+ return `INSERT OR IGNORE INTO log_events (${ARCHIVE_INSERT_COLUMNS.join(", ")}) VALUES ${placeholderRows(rowCount)}`;
96
+ }
97
+ /**
98
+ * Flattens events into the parameter list {@link buildInsertSql} expects.
99
+ *
100
+ * The request id is detected here, exactly like the level, so the archive holds
101
+ * what a reader of the line would see rather than whatever a writer claimed.
102
+ */
103
+ function toArchiveParams(region, logGroup, events) {
104
+ const params = [];
105
+ for (const event of events) {
106
+ const detected = detectLevelWithSource(event.message);
107
+ params.push(region, logGroup, event.streamName ?? null, archiveEventKey(event), event.id ?? null, BigInt(Math.round(event.timestamp)), event.ingestionTime === void 0 ? null : BigInt(Math.round(event.ingestionTime)), event.message, detected.level, detected.source, detectRequestId(event.message));
108
+ }
109
+ return params;
110
+ }
111
+ /** Column list shared by {@link buildPageQuery} and {@link rowsToPage}. */
112
+ var PAGE_COLUMNS = `region, log_group, log_stream, event_key, event_id, timestamp_ms, ingestion_time_ms, message, level, level_source, request_id, seq`;
113
+ /** Escapes `LIKE` metacharacters so a search term is matched literally. */
114
+ function escapeLike(value) {
115
+ return value.replace(/[\\%_]/g, (match) => `${LIKE_ESCAPE}${match}`);
116
+ }
117
+ /**
118
+ * Builds one keyset page of archived events.
119
+ *
120
+ * Ordering is `(timestamp_ms, seq)`, and the cursor compares the same tuple, so
121
+ * pages never repeat or skip a row even when thousands of events share a
122
+ * timestamp.
123
+ */
124
+ function buildPageQuery(request) {
125
+ const limit = Math.max(1, Math.round(request.limit));
126
+ const groups = request.logGroups.length > 0 ? request.logGroups : [""];
127
+ const where = [
128
+ "region = ?",
129
+ `log_group IN (${groups.map(() => "?").join(", ")})`,
130
+ "timestamp_ms >= ?",
131
+ "timestamp_ms <= ?"
132
+ ];
133
+ const params = [
134
+ request.region,
135
+ ...groups,
136
+ BigInt(Math.round(request.startTime)),
137
+ BigInt(Math.round(request.endTime))
138
+ ];
139
+ const search = request.search?.trim() ?? "";
140
+ if (search.length > 0) {
141
+ where.push(`message ILIKE ? ESCAPE '${LIKE_ESCAPE}'`);
142
+ params.push(`%${escapeLike(search)}%`);
143
+ }
144
+ const prefix = request.streamPrefix?.trim() ?? "";
145
+ if (prefix.length > 0) {
146
+ where.push(`log_stream LIKE ? ESCAPE '${LIKE_ESCAPE}'`);
147
+ params.push(`${escapeLike(prefix)}%`);
148
+ }
149
+ const levels = request.levels ?? [];
150
+ if (levels.length > 0) {
151
+ where.push(`level IN (${levels.map(() => "?").join(", ")})`);
152
+ params.push(...levels);
153
+ }
154
+ const after = request.after ?? null;
155
+ if (after !== null) {
156
+ where.push("(timestamp_ms > ? OR (timestamp_ms = ? AND seq > ?))");
157
+ params.push(BigInt(Math.round(after.timestamp)), BigInt(Math.round(after.timestamp)), BigInt(Math.round(after.seq)));
158
+ }
159
+ params.push(BigInt(limit));
160
+ return {
161
+ sql: `SELECT ${PAGE_COLUMNS} FROM log_events WHERE ${where.join(" AND ")} ORDER BY timestamp_ms, seq LIMIT ?`,
162
+ params
163
+ };
164
+ }
165
+ /** Converts a DuckDB value (which may be a bigint) into a JS number. */
166
+ function toNumber(value) {
167
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
168
+ if (typeof value === "bigint") return Number(value);
169
+ if (typeof value === "string" && value.trim().length > 0) {
170
+ const parsed = Number(value);
171
+ return Number.isFinite(parsed) ? parsed : null;
172
+ }
173
+ return null;
174
+ }
175
+ /** Converts a nullable DuckDB string column into `string` or `null`. */
176
+ function toNullableString(value) {
177
+ if (typeof value === "string") return value.length > 0 ? value : null;
178
+ return null;
179
+ }
180
+ /** Reads one column from a row object, tolerating case differences. */
181
+ function pick(row, column) {
182
+ if (column in row) return row[column];
183
+ const upper = column.toUpperCase();
184
+ if (upper in row) return row[upper];
185
+ }
186
+ /**
187
+ * Maps query rows onto wire events plus the cursor of the last row.
188
+ *
189
+ * Rows without a usable timestamp are dropped rather than rendered as 1970.
190
+ */
191
+ function rowsToPage(rows) {
192
+ const events = [];
193
+ let last = null;
194
+ for (const row of rows) {
195
+ const timestamp = toNumber(pick(row, "timestamp_ms"));
196
+ const seq = toNumber(pick(row, "seq"));
197
+ if (timestamp === null || seq === null) continue;
198
+ const rawLevel = pick(row, "level");
199
+ const group = toNullableString(pick(row, "log_group"));
200
+ const event = {
201
+ id: toNullableString(pick(row, "event_key")),
202
+ timestamp,
203
+ message: typeof pick(row, "message") === "string" ? pick(row, "message") : "",
204
+ level: isLogLevel(rawLevel) ? rawLevel : null
205
+ };
206
+ if (group !== null) event.group = group;
207
+ const requestId = toNullableString(pick(row, "request_id"));
208
+ if (requestId !== null) event.requestId = requestId;
209
+ const streamName = toNullableString(pick(row, "log_stream"));
210
+ if (streamName !== null) event.streamName = streamName;
211
+ const ingestionTime = toNumber(pick(row, "ingestion_time_ms"));
212
+ if (ingestionTime !== null) event.ingestionTime = ingestionTime;
213
+ events.push(event);
214
+ last = {
215
+ timestamp,
216
+ seq
217
+ };
218
+ }
219
+ return {
220
+ events,
221
+ last
222
+ };
223
+ }
224
+ /** Aggregate query behind {@link ArchiveTotals}. */
225
+ var ARCHIVE_TOTALS_SQL = `SELECT count(*) AS rows, count(DISTINCT log_group) AS groups, count(DISTINCT region) AS regions, min(timestamp_ms) AS oldest, max(timestamp_ms) AS newest FROM log_events`;
226
+ /** Log groups held by the archive, optionally limited to one region. */
227
+ function buildGroupsQuery(region) {
228
+ const where = region === null || region.length === 0 ? "" : "WHERE region = ?";
229
+ return {
230
+ sql: `SELECT region, log_group, count(*) AS events, min(timestamp_ms) AS oldest, max(timestamp_ms) AS newest FROM log_events ${where} GROUP BY region, log_group ORDER BY region, log_group`,
231
+ params: where === "" ? [] : [region]
232
+ };
233
+ }
234
+ /** Maps the single row of {@link ARCHIVE_TOTALS_SQL}. */
235
+ function rowToTotals(row) {
236
+ if (row === void 0) return {
237
+ rows: 0,
238
+ groups: 0,
239
+ regions: 0,
240
+ oldest: null,
241
+ newest: null
242
+ };
243
+ return {
244
+ rows: toNumber(pick(row, "rows")) ?? 0,
245
+ groups: toNumber(pick(row, "groups")) ?? 0,
246
+ regions: toNumber(pick(row, "regions")) ?? 0,
247
+ oldest: toNumber(pick(row, "oldest")),
248
+ newest: toNumber(pick(row, "newest"))
249
+ };
250
+ }
251
+ /** Maps the rows of {@link buildGroupsQuery}. */
252
+ function rowsToGroups(rows) {
253
+ const groups = [];
254
+ for (const row of rows) {
255
+ const region = pick(row, "region");
256
+ const logGroup = pick(row, "log_group");
257
+ if (typeof region !== "string" || typeof logGroup !== "string") continue;
258
+ groups.push({
259
+ region,
260
+ logGroup,
261
+ events: toNumber(pick(row, "events")) ?? 0,
262
+ oldest: toNumber(pick(row, "oldest")),
263
+ newest: toNumber(pick(row, "newest"))
264
+ });
265
+ }
266
+ return groups;
267
+ }
268
+ /**
269
+ * Row budget of one request-id backfill pass.
270
+ *
271
+ * The pass runs on every open, so it has to stay cheap. 20000 messages is a
272
+ * fraction of a second of regex work, and an archive with more than that scans
273
+ * the rest on the next open, because the watermark moves.
274
+ */
275
+ var REQUEST_ID_BACKFILL_LIMIT = 2e4;
276
+ /** `archive_meta` key holding the request-id backfill watermark. */
277
+ var REQUEST_ID_BACKFILL_KEY = "request_id_backfill";
278
+ /** Highest `seq` in the archive: the ceiling of a backfill pass. */
279
+ var ARCHIVE_MAX_SEQ_SQL = `SELECT max(seq) AS maxSeq FROM log_events`;
280
+ /** Reads the single row of {@link ARCHIVE_MAX_SEQ_SQL}; `null` for an empty archive. */
281
+ function rowToMaxSeq(row) {
282
+ return row === void 0 ? null : toNumber(pick(row, "maxSeq"));
283
+ }
284
+ /** Statement that reads the backfill watermark; no row means it never ran. */
285
+ function buildRequestIdBackfillStateQuery() {
286
+ return `SELECT value FROM archive_meta WHERE key = '${REQUEST_ID_BACKFILL_KEY}'`;
287
+ }
288
+ /** Statement that stores the backfill watermark, which is the highest scanned `seq`. */
289
+ function buildRequestIdBackfillStateWrite() {
290
+ return `INSERT OR REPLACE INTO archive_meta (key, value) VALUES ('${REQUEST_ID_BACKFILL_KEY}', ?)`;
291
+ }
292
+ /** Reads the watermark row; an absent row or junk means "scan from the start". */
293
+ function rowToBackfillWatermark(row) {
294
+ const value = row === void 0 ? null : toNumber(pick(row, "value"));
295
+ return value === null || value < 0 ? null : value;
296
+ }
297
+ /**
298
+ * Builds the scan that finds rows archived before `request_id` existed.
299
+ *
300
+ * `seq` is selected although the update does not need it: the caller stores
301
+ * where the pass stopped. `afterSeq` skips the range a previous pass already
302
+ * looked at, which is what lets a capped pass resume - a message with no request
303
+ * id stays NULL for ever, so without the lower bound every pass would start on
304
+ * the same id-less rows and never reach the rows above them.
305
+ */
306
+ function buildRequestIdBackfillQuery(request) {
307
+ const limit = Math.max(1, Math.round(request.limit));
308
+ const scanned = request.afterSeq ?? 0;
309
+ const after = scanned > 0 ? " AND seq > ?" : "";
310
+ const params = [BigInt(Math.round(request.maxSeq))];
311
+ if (scanned > 0) params.push(BigInt(Math.round(scanned)));
312
+ params.push(BigInt(limit));
313
+ return {
314
+ sql: `SELECT event_key, log_group, region, message, seq FROM log_events WHERE seq <= ?${after} AND request_id IS NULL ORDER BY seq LIMIT ?`,
315
+ params
316
+ };
317
+ }
318
+ /** Maps the rows of {@link buildRequestIdBackfillQuery}, dropping unusable ones. */
319
+ function rowsToBackfillCandidates(rows) {
320
+ const candidates = [];
321
+ for (const row of rows) {
322
+ const seq = toNumber(pick(row, "seq"));
323
+ const region = pick(row, "region");
324
+ const logGroup = pick(row, "log_group");
325
+ const eventKey = pick(row, "event_key");
326
+ const message = pick(row, "message");
327
+ if (seq === null || typeof region !== "string" || typeof logGroup !== "string" || typeof eventKey !== "string" || typeof message !== "string") continue;
328
+ candidates.push({
329
+ seq,
330
+ region,
331
+ logGroup,
332
+ eventKey,
333
+ message
334
+ });
335
+ }
336
+ return candidates;
337
+ }
338
+ /** Highest `seq` of a scanned set, or `null` when nothing was scanned. */
339
+ function maxSeqOf(candidates) {
340
+ let highest = null;
341
+ for (const candidate of candidates) if (highest === null || candidate.seq > highest) highest = candidate.seq;
342
+ return highest;
343
+ }
344
+ /**
345
+ * Detects the request id of every candidate.
346
+ *
347
+ * A message that yields no id is dropped rather than written as an empty string:
348
+ * it is a finished row, not a failure, and the watermark moves past it so it is
349
+ * never looked at again.
350
+ */
351
+ function planRequestIdBackfill(candidates) {
352
+ const updates = [];
353
+ for (const candidate of candidates) {
354
+ const requestId = detectRequestId(candidate.message);
355
+ if (requestId === null) continue;
356
+ updates.push({
357
+ region: candidate.region,
358
+ logGroup: candidate.logGroup,
359
+ eventKey: candidate.eventKey,
360
+ requestId
361
+ });
362
+ }
363
+ return updates;
364
+ }
365
+ /**
366
+ * Builds one `UPDATE ... FROM (VALUES ...)` that writes many ids at once.
367
+ *
368
+ * One statement per chunk instead of one per row keeps a 20000-row pass down to
369
+ * a handful of statements, and the predicate is an exact row match on the unique
370
+ * index (`region`, `log_group`, `event_key`).
371
+ */
372
+ function buildRequestIdBackfillUpdate(rowCount) {
373
+ if (!Number.isInteger(rowCount) || rowCount < 1) throw new RangeError(`rowCount must be a positive integer, received ${String(rowCount)}`);
374
+ return `UPDATE log_events SET request_id = v.request_id FROM (VALUES ${Array.from({ length: rowCount }, () => "(?, ?, ?, ?)").join(", ")}) AS v(region, log_group, event_key, request_id) WHERE log_events.region = v.region AND log_events.log_group = v.log_group AND log_events.event_key = v.event_key`;
375
+ }
376
+ /** Flattens updates into the parameter list {@link buildRequestIdBackfillUpdate} expects. */
377
+ function toRequestIdBackfillParams(updates) {
378
+ const params = [];
379
+ for (const update of updates) params.push(update.region, update.logGroup, update.eventKey, update.requestId);
380
+ return params;
381
+ }
382
+ /** Levels and their rank, highest first; `unknown` is left to the `ELSE` branch. */
383
+ function rankArms() {
384
+ return Object.entries(LEVEL_RANK).filter(([level]) => level !== "unknown");
385
+ }
386
+ /**
387
+ * SQL `CASE` that turns a level into its severity rank.
388
+ *
389
+ * Generated from {@link LEVEL_RANK} so the ranks have one source of truth: the
390
+ * statement and the UI cannot disagree about which level is worse.
391
+ */
392
+ function levelRankCase(expression) {
393
+ return `CASE ${expression} ${rankArms().map(([level, rank]) => `WHEN '${level}' THEN ${rank}`).join(" ")} ELSE ${LEVEL_RANK.unknown} END`;
394
+ }
395
+ /** SQL `CASE` that turns a severity rank back into a level name. */
396
+ function levelNameCase(expression) {
397
+ return `CASE ${expression} ${rankArms().map(([level, rank]) => `WHEN ${rank} THEN '${level}'`).join(" ")} ELSE 'unknown' END`;
398
+ }
399
+ /** The `WHERE` clause both series forms share: one region, one window, one or more groups. */
400
+ function seriesScope(request, groups) {
401
+ return {
402
+ where: [
403
+ "region = ?",
404
+ `log_group IN (${groups.map(() => "?").join(", ")})`,
405
+ "timestamp_ms >= ?",
406
+ "timestamp_ms <= ?"
407
+ ],
408
+ params: [
409
+ request.region,
410
+ ...groups,
411
+ BigInt(Math.round(request.startTime)),
412
+ BigInt(Math.round(request.endTime))
413
+ ]
414
+ };
415
+ }
416
+ /**
417
+ * Builds the bucketed counts behind the chart.
418
+ *
419
+ * One statement returns every series. The bucket is plain integer arithmetic on
420
+ * `timestamp_ms`, so it cannot drift with a time zone; NULL levels are reported
421
+ * as `unknown` rather than dropped; and a level filter matches only rows that
422
+ * carry one of the requested levels.
423
+ *
424
+ * `by: 'request'` selects the request form below; `by: 'event'` (the default)
425
+ * keeps the event form unchanged.
426
+ */
427
+ function buildSeriesQuery(request) {
428
+ const bucketMs = Math.max(1, Math.round(request.bucketMs));
429
+ const scope = seriesScope(request, request.logGroups.length > 0 ? request.logGroups : [""]);
430
+ if (request.by === "request") return buildRequestSeriesQuery(request, bucketMs, scope.where, scope.params);
431
+ const params = [
432
+ BigInt(bucketMs),
433
+ BigInt(bucketMs),
434
+ ...scope.params
435
+ ];
436
+ const where = scope.where.slice();
437
+ const levels = request.levels ?? [];
438
+ if (levels.length > 0) {
439
+ where.push(`level IN (${levels.map(() => "?").join(", ")})`);
440
+ params.push(...levels);
441
+ }
442
+ return {
443
+ sql: `SELECT CAST(floor(timestamp_ms / ?) * ? AS BIGINT) AS bucket, log_group, coalesce(level, 'unknown') AS level, count(*) AS events FROM log_events WHERE ${where.join(" AND ")} GROUP BY bucket, log_group, level ORDER BY bucket, log_group, level`,
444
+ params
445
+ };
446
+ }
447
+ /**
448
+ * Builds the request form: one mark per request instead of one per line.
449
+ *
450
+ * `coalesce(request_id, event_key)` makes a line with no request id a request of
451
+ * its own, so no line is dropped. A request is placed at its FIRST line
452
+ * (`min(timestamp_ms)`) and counted once, and it takes the WORST level of its
453
+ * lines (`max` of the ranks). A level filter selects on that same worst level in
454
+ * the `HAVING`: asking for errors keeps every request that logged one, whatever
455
+ * else it logged, and drops the requests that stayed below it.
456
+ *
457
+ * BIND ORDER: DuckDB binds `?` positionally in statement text order, and the CTE
458
+ * comes first, so the parameters are the scope ones, then one rank per requested
459
+ * level (the RANKS, not the level names), and the bucket width LAST - the
460
+ * opposite of the event form above.
461
+ */
462
+ function buildRequestSeriesQuery(request, bucketMs, where, scopeParams) {
463
+ const levels = request.levels ?? [];
464
+ const having = levels.length > 0 ? ` HAVING level_rank IN (${levels.map(() => "?").join(", ")})` : "";
465
+ const params = [
466
+ ...scopeParams,
467
+ ...levels.map((level) => LEVEL_RANK[level]),
468
+ BigInt(bucketMs),
469
+ BigInt(bucketMs)
470
+ ];
471
+ return {
472
+ sql: [
473
+ "WITH requests AS (",
474
+ `SELECT coalesce(request_id, event_key) AS request_key, log_group, min(timestamp_ms) AS start_ms, max(${levelRankCase(`coalesce(level, 'unknown')`)}) AS level_rank`,
475
+ `FROM log_events WHERE ${where.join(" AND ")}`,
476
+ `GROUP BY request_key, log_group${having})`,
477
+ `SELECT CAST(floor(start_ms / ?) * ? AS BIGINT) AS bucket, log_group, ${levelNameCase("level_rank")} AS level, count(*) AS events`,
478
+ "FROM requests GROUP BY bucket, log_group, level ORDER BY bucket, log_group, level"
479
+ ].join(" "),
480
+ params
481
+ };
482
+ }
483
+ /** Maps the rows of {@link buildSeriesQuery} onto chart points. */
484
+ function rowsToSeries(rows) {
485
+ const points = [];
486
+ for (const row of rows) {
487
+ const t = toNumber(pick(row, "bucket"));
488
+ const group = pick(row, "log_group");
489
+ const level = pick(row, "level");
490
+ if (t === null || typeof group !== "string") continue;
491
+ points.push({
492
+ t,
493
+ group,
494
+ level: typeof level === "string" && level.length > 0 ? level : "unknown",
495
+ events: toNumber(pick(row, "events")) ?? 0
496
+ });
497
+ }
498
+ return points;
499
+ }
500
+ //#endregion
501
+ //#region src/lib/server/archive.ts
502
+ /**
503
+ * Local DuckDB archive of the events the app has streamed.
504
+ *
505
+ * The driver (`@duckdb/node-api` plus its per-platform native binding) is an
506
+ * optional dependency: it is imported lazily, on the first request that needs
507
+ * it, and every failure is turned into an unavailable archive instead of an
508
+ * error. The rest of the app therefore works unchanged on platforms where the
509
+ * binding is missing.
510
+ *
511
+ * One process owns the file: DuckDB allows a single writer, and the SvelteKit
512
+ * server is that writer. Statements are serialised through an internal queue so
513
+ * a stream writing while another request reads cannot interleave on the
514
+ * connection.
515
+ */
516
+ /** Package name of the optional DuckDB driver. */
517
+ var DUCKDB_MODULE = "@duckdb/node-api";
518
+ /** Directory name used under the platform data directory. */
519
+ var ARCHIVE_DIR_NAME = "watch-tail";
520
+ /** File name of the archive inside {@link ARCHIVE_DIR_NAME}. */
521
+ var ARCHIVE_FILE_NAME = "archive.duckdb";
522
+ /**
523
+ * Imports the optional DuckDB driver.
524
+ *
525
+ * The specifier is held in a variable on purpose: bundlers must leave the
526
+ * import alone so Node resolves it at run time, where a missing binding can be
527
+ * reported as an unavailable archive rather than a build error.
528
+ */
529
+ async function loadDuckDbDriver() {
530
+ const loaded = await import(DUCKDB_MODULE);
531
+ if (typeof loaded.DuckDBInstance?.create !== "function") throw new Error(`${DUCKDB_MODULE} did not expose DuckDBInstance.create`);
532
+ return loaded;
533
+ }
534
+ var DISABLED_VALUES = /* @__PURE__ */ new Set([
535
+ "0",
536
+ "false",
537
+ "no",
538
+ "off"
539
+ ]);
540
+ /** True when an environment value means "off". */
541
+ function isDisabled(value) {
542
+ return value !== void 0 && DISABLED_VALUES.has(value.trim().toLowerCase());
543
+ }
544
+ /**
545
+ * True when this process is a test runner.
546
+ *
547
+ * Vitest sets `VITEST`, and `NODE_ENV=test` covers other harnesses. Tests must
548
+ * not append to the archive of the machine they run on, so the archive is off
549
+ * unless a test asks for it through `WATCH_STREAM_ARCHIVE_DB` or
550
+ * `WATCH_STREAM_ARCHIVE=on`.
551
+ */
552
+ function isTestProcess(env) {
553
+ return env.VITEST !== void 0 || env.NODE_ENV === "test";
554
+ }
555
+ /**
556
+ * Resolves the archive file path.
557
+ *
558
+ * `WATCH_STREAM_ARCHIVE_DB` wins; otherwise the file lives in the platform's
559
+ * data directory (`XDG_DATA_HOME`, `%LOCALAPPDATA%` or
560
+ * `~/Library/Application Support`), never in the current directory, so history
561
+ * survives running the CLI from a different folder.
562
+ */
563
+ function resolveArchiveConfig(env, platform = process.platform, home = homedir()) {
564
+ const path = env.WATCH_STREAM_ARCHIVE_DB?.trim() ?? "";
565
+ const dataDir = env.XDG_DATA_HOME?.trim() ?? (platform === "darwin" ? join(home, "Library", "Application Support") : platform === "win32" ? env.LOCALAPPDATA?.trim() ?? join(home, "AppData", "Local") : join(home, ".local", "share"));
566
+ const requested = env.WATCH_STREAM_ARCHIVE?.trim() ?? "";
567
+ return {
568
+ enabled: isDisabled(requested) ? false : path.length > 0 || requested.length > 0 ? true : !isTestProcess(env),
569
+ path: path.length > 0 ? path : join(dataDir, ARCHIVE_DIR_NAME, ARCHIVE_FILE_NAME)
570
+ };
571
+ }
572
+ /**
573
+ * A short, non-throwing description of an unknown failure.
574
+ *
575
+ * A conflicting lock is the one failure a user can act on, and DuckDB's own
576
+ * message buries the reason in a pid and a documentation link, so it is
577
+ * reported as what it means for this app.
578
+ */
579
+ function describeOpenError(error, path) {
580
+ const message = error instanceof Error ? error.message : String(error);
581
+ if (/Could not set lock|Conflicting lock/i.test(message)) return `the archive file ${path} is locked by another process (another watch-tail is using it); use --db to keep a separate file`;
582
+ return message;
583
+ }
584
+ /** True when the failure is the exclusive file lock. */
585
+ function isLockError(error) {
586
+ const message = error instanceof Error ? error.message : String(error);
587
+ return /Could not set lock|Conflicting lock/i.test(message);
588
+ }
589
+ /**
590
+ * One DuckDB file holding every event the app has streamed.
591
+ *
592
+ * `open` never throws: a missing driver, a locked file or a corrupt database all
593
+ * produce an instance with `available === false` and the reason on `error`. The
594
+ * read and write methods then behave as no-ops, so callers never have to guard
595
+ * their happy path.
596
+ */
597
+ var LogArchive = class LogArchive {
598
+ /** Database file this archive uses. */
599
+ path;
600
+ #connection = null;
601
+ #available = false;
602
+ #error = null;
603
+ #queue = Promise.resolve();
604
+ constructor(path) {
605
+ this.path = path;
606
+ }
607
+ /**
608
+ * Opens (and creates) the archive.
609
+ *
610
+ * Statements are executed in order: the sequence first, then the table, then
611
+ * the indexes, so an existing file from an older build is upgraded in place.
612
+ * The request-id backfill runs last, inside the same serialised path, and
613
+ * cannot fail the open.
614
+ */
615
+ static async open(options) {
616
+ const archive = new LogArchive(options.path);
617
+ const load = options.load ?? loadDuckDbDriver;
618
+ const ensureDir = options.ensureDir ?? ((dir) => mkdirSync(dir, { recursive: true }));
619
+ try {
620
+ ensureDir(dirname(options.path));
621
+ const driver = await load();
622
+ for (let attempt = 1;; attempt += 1) try {
623
+ const connection = await (await driver.DuckDBInstance.create(options.path)).connect();
624
+ for (const statement of ARCHIVE_SCHEMA) await connection.run(statement);
625
+ archive.#connection = connection;
626
+ archive.#available = true;
627
+ await archive.#backfillRequestIds();
628
+ break;
629
+ } catch (error) {
630
+ if (attempt >= 3 || !isLockError(error)) throw error;
631
+ await setTimeout(150);
632
+ }
633
+ } catch (error) {
634
+ archive.#available = false;
635
+ archive.#error = describeOpenError(error, options.path);
636
+ }
637
+ return archive;
638
+ }
639
+ /**
640
+ * An archive that is off by configuration or could not be opened.
641
+ *
642
+ * Every method degrades to a no-op, so callers can use one code path for
643
+ * "no DuckDB on this machine" and "the user asked for no archive".
644
+ */
645
+ static unavailable(path, error = null) {
646
+ const archive = new LogArchive(path);
647
+ archive.#available = false;
648
+ archive.#error = error;
649
+ return archive;
650
+ }
651
+ /** True when the archive can be read and written. */
652
+ get available() {
653
+ return this.#available;
654
+ }
655
+ /** Why the archive is unavailable, or the last failure, or `null`. */
656
+ get error() {
657
+ return this.#error;
658
+ }
659
+ /** Runs one task after every task queued before it. */
660
+ #enqueue(task) {
661
+ const next = this.#queue.then(task, task);
662
+ this.#queue = next.then(() => void 0, () => void 0);
663
+ return next;
664
+ }
665
+ /** Runs a statement, returning the failure instead of throwing. */
666
+ async #guard(fallback, task) {
667
+ if (this.#connection === null) return fallback;
668
+ return this.#enqueue(async () => {
669
+ try {
670
+ return await task();
671
+ } catch (error) {
672
+ this.#error = error instanceof Error ? error.message : String(error);
673
+ return fallback;
674
+ }
675
+ });
676
+ }
677
+ /**
678
+ * Migrates the request id of rows written before the column existed.
679
+ *
680
+ * It runs inside {@link LogArchive.#guard}, so it shares the serialised
681
+ * statement queue with every other write and reports a failure on `error`
682
+ * instead of letting it escape `open`. The watermark is the highest `seq` the
683
+ * migration has looked at, so a capped or interrupted pass carries on from
684
+ * there on the next open and no row is scanned twice; a row whose message
685
+ * holds no id stays NULL, which is the archive's answer for that row.
686
+ */
687
+ async #backfillRequestIds() {
688
+ await this.#guard(void 0, async () => {
689
+ const connection = this.#connection;
690
+ if (connection === null) return;
691
+ const ceiling = rowToMaxSeq((await connection.runAndReadAll(ARCHIVE_MAX_SEQ_SQL)).getRowObjects()[0]);
692
+ if (ceiling === null) return;
693
+ const watermark = rowToBackfillWatermark((await connection.runAndReadAll(buildRequestIdBackfillStateQuery())).getRowObjects()[0]);
694
+ if (watermark !== null && watermark >= ceiling) return;
695
+ const { sql, params } = buildRequestIdBackfillQuery({
696
+ maxSeq: ceiling,
697
+ afterSeq: watermark,
698
+ limit: REQUEST_ID_BACKFILL_LIMIT
699
+ });
700
+ const candidates = rowsToBackfillCandidates((await connection.runAndReadAll(sql, params)).getRowObjects());
701
+ const updates = planRequestIdBackfill(candidates);
702
+ for (let start = 0; start < updates.length; start += 500) {
703
+ const chunk = updates.slice(start, start + 500);
704
+ await connection.run(buildRequestIdBackfillUpdate(chunk.length), toRequestIdBackfillParams(chunk));
705
+ }
706
+ const scanned = candidates.length < 2e4 ? ceiling : maxSeqOf(candidates);
707
+ await connection.run(buildRequestIdBackfillStateWrite(), [String(scanned ?? ceiling)]);
708
+ });
709
+ }
710
+ /**
711
+ * Writes one batch of streamed events.
712
+ *
713
+ * Batches are split into chunks of {@link ARCHIVE_INSERT_CHUNK} rows, and
714
+ * `INSERT OR IGNORE` plus the unique index make a repeated scan idempotent.
715
+ * Failures never propagate: a full disk must not interrupt a log stream.
716
+ */
717
+ async record(region, logGroup, events) {
718
+ if (events.length === 0) return 0;
719
+ return this.#guard(0, async () => {
720
+ const connection = this.#connection;
721
+ if (connection === null) return 0;
722
+ let written = 0;
723
+ for (let start = 0; start < events.length; start += 500) {
724
+ const chunk = events.slice(start, start + 500);
725
+ await connection.run(buildInsertSql(chunk.length), toArchiveParams(region, logGroup, chunk));
726
+ written += chunk.length;
727
+ }
728
+ return written;
729
+ });
730
+ }
731
+ /** Reads one page of archived events. */
732
+ async page(request) {
733
+ const empty = {
734
+ events: [],
735
+ last: null
736
+ };
737
+ return this.#guard(empty, async () => {
738
+ const connection = this.#connection;
739
+ if (connection === null) return empty;
740
+ const { sql, params } = buildPageQuery(request);
741
+ return rowsToPage((await connection.runAndReadAll(sql, params)).getRowObjects());
742
+ });
743
+ }
744
+ /**
745
+ * Bucketed counts for the chart, per group and level.
746
+ *
747
+ * The request is forwarded as it arrives: it carries the grouping that says
748
+ * whether a mark counts an event or a request.
749
+ */
750
+ async seriesQuery(request) {
751
+ return this.#guard([], async () => {
752
+ const connection = this.#connection;
753
+ if (connection === null) return [];
754
+ const { sql, params } = buildSeriesQuery(request);
755
+ return rowsToSeries((await connection.runAndReadAll(sql, params)).getRowObjects());
756
+ });
757
+ }
758
+ /** Aggregate row count and time bounds. */
759
+ async totals() {
760
+ return this.#guard(rowToTotals(void 0), async () => {
761
+ const connection = this.#connection;
762
+ if (connection === null) return rowToTotals(void 0);
763
+ return rowToTotals((await connection.runAndReadAll(ARCHIVE_TOTALS_SQL)).getRowObjects()[0]);
764
+ });
765
+ }
766
+ /** Log groups held by the archive, optionally limited to one region. */
767
+ async groups(region = null) {
768
+ return this.#guard([], async () => {
769
+ const connection = this.#connection;
770
+ if (connection === null) return [];
771
+ const { sql, params } = buildGroupsQuery(region);
772
+ return rowsToGroups((await connection.runAndReadAll(sql, params)).getRowObjects());
773
+ });
774
+ }
775
+ /** Status for `GET /api/archive`, including the file size on disk. */
776
+ async status() {
777
+ const totals = await this.totals();
778
+ let bytes = null;
779
+ if (this.#available) try {
780
+ bytes = statSync(this.path).size;
781
+ } catch {
782
+ bytes = null;
783
+ }
784
+ return {
785
+ path: this.path,
786
+ available: this.#available,
787
+ error: this.#error,
788
+ bytes,
789
+ totals
790
+ };
791
+ }
792
+ /** Closes the connection. Safe to call twice. */
793
+ async close() {
794
+ const connection = this.#connection;
795
+ this.#connection = null;
796
+ this.#available = false;
797
+ if (connection?.closeSync === void 0) return;
798
+ await this.#enqueue(async () => {
799
+ connection.closeSync?.();
800
+ });
801
+ }
802
+ };
803
+ /** The archive for the running server, opened once per process. */
804
+ var sharedArchive = null;
805
+ /**
806
+ * Returns the process-wide archive for `env`, opening it on first use.
807
+ *
808
+ * The same file is never opened twice per process; a disabled archive
809
+ * (`WATCH_STREAM_ARCHIVE=off`) is remembered so no driver import is attempted.
810
+ */
811
+ function getArchive(env, load) {
812
+ if (sharedArchive === null) {
813
+ const config = resolveArchiveConfig(env);
814
+ sharedArchive = config.enabled ? LogArchive.open({
815
+ path: config.path,
816
+ ...{}
817
+ }) : Promise.resolve(LogArchive.unavailable(config.path));
818
+ }
819
+ return sharedArchive;
820
+ }
821
+
822
+ export { getArchive as g };
823
+ //# sourceMappingURL=archive.js-C2D-5edp.js.map