@hot-updater/console 1.0.0-rc.9 → 1.0.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 (341) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/ConsoleFeatureUnavailable-jB4Loglh.js +1 -0
  3. package/.output/public/assets/EventDetails-B6yUsyNA.js +1 -0
  4. package/.output/public/assets/HashValueDisplay-BFX_kY3-.js +1 -0
  5. package/.output/public/assets/InsightsInfo-BNO0WznZ.js +1 -0
  6. package/.output/public/assets/InsightsPageHeader-B892oVml.js +1 -0
  7. package/.output/public/assets/NotFoundPage-DIqCpWa3.js +1 -0
  8. package/.output/public/assets/alert-dialog-Bbk_4-WJ.js +1 -0
  9. package/.output/public/assets/api-DCM0wr6O.js +1 -0
  10. package/.output/public/assets/api-keys-CIO9L_wu.js +1 -0
  11. package/.output/public/assets/api-keys-DVTL_--f.js +1 -0
  12. package/.output/public/assets/arrow-left-CnMYpqB7.js +1 -0
  13. package/.output/public/assets/arrow-up-right-BtffZA6e.js +1 -0
  14. package/.output/public/assets/chevron-right-BqD5wtFb.js +1 -0
  15. package/.output/public/assets/clipboard-DS9ucUQL.js +1 -0
  16. package/.output/public/assets/console-features-api-BH5m_PtQ.js +1 -0
  17. package/.output/public/assets/dialog-Bqbb7B0N.js +1 -0
  18. package/.output/public/assets/dist-LxKJB-Vu.js +1 -0
  19. package/.output/public/assets/empty-CuT2UhFp.js +1 -0
  20. package/.output/public/assets/field-BBDpjIqu.js +1 -0
  21. package/.output/public/assets/index-6o51GkFe.js +11 -0
  22. package/.output/public/assets/input-group-ja_30qaF.js +1 -0
  23. package/.output/public/assets/insights-CmraDzQh.js +1 -0
  24. package/.output/public/assets/insights-CxZ2GCYV.js +2 -0
  25. package/.output/public/assets/insights-api-BigAU9sZ.js +1 -0
  26. package/.output/public/assets/insights-usage-rpc-DYEhsCKT.js +1 -0
  27. package/.output/public/assets/insights-vNRCrfnS.js +42 -0
  28. package/.output/public/assets/insights_.distribution-ChOerfJt.js +1 -0
  29. package/.output/public/assets/insights_.distribution-D-e4iga8.js +1 -0
  30. package/.output/public/assets/insights_.distribution-DZtkibX1.js +2 -0
  31. package/.output/public/assets/installations-BazSJXE0.js +2 -0
  32. package/.output/public/assets/installations-ClHTqdAO.js +1 -0
  33. package/.output/public/assets/installations-DpKsBuHi.js +1 -0
  34. package/.output/public/assets/key-round-wS_SIZ6b.js +1 -0
  35. package/.output/public/assets/list-CgrYiadM.js +1 -0
  36. package/.output/public/assets/refresh-cw-BYgoNCco.js +1 -0
  37. package/.output/public/assets/remote-config-BWwHOkCK.js +1 -0
  38. package/.output/public/assets/remote-config-Br56BODb.js +6 -0
  39. package/.output/public/assets/remote-config-CXOi0LRu.js +1 -0
  40. package/.output/public/assets/routes-B88Erkpk.js +2 -0
  41. package/.output/public/assets/routes-CfzsAleC.js +1 -0
  42. package/.output/public/assets/search-DaTDPW25.js +1 -0
  43. package/.output/public/assets/select-BZZBXMkr.js +1 -0
  44. package/.output/public/assets/sidebar-DNVyJPfX.js +3 -0
  45. package/.output/public/assets/smartphone-DpTFgtKf.js +1 -0
  46. package/.output/public/assets/styles-DTGEAJFv.css +2 -0
  47. package/.output/public/assets/switch-DZ1TPwx-.js +1 -0
  48. package/.output/public/assets/table-Gm4qRWwE.js +1 -0
  49. package/.output/public/assets/tabs-C7FOEjFC.js +1 -0
  50. package/.output/public/assets/undo-2-CmrHjwFc.js +1 -0
  51. package/.output/public/assets/useCompositeListItem-9E4pj_CH.js +1 -0
  52. package/.output/public/assets/valueToPercent-CH8GCHaL.js +1 -0
  53. package/.output/server/__23tanstack-start-server-fn-resolver-BpRlos5Q.mjs +170 -0
  54. package/.output/server/_libs/@base-ui/react+[...].mjs +4389 -4207
  55. package/.output/server/_libs/@tanstack/react-router+[...].mjs +3802 -4022
  56. package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +140 -97
  57. package/.output/server/_libs/lucide-react.mjs +221 -9
  58. package/.output/server/_libs/next-themes.mjs +1 -1
  59. package/.output/server/_libs/react-redux+[...].mjs +1 -1
  60. package/.output/server/_libs/recharts+[...].mjs +483 -901
  61. package/.output/server/_libs/sonner.mjs +1 -1
  62. package/.output/server/_libs/tanstack__history.mjs +68 -41
  63. package/.output/server/_libs/tanstack__query-core.mjs +2010 -309
  64. package/.output/server/_libs/tanstack__react-query.mjs +448 -21
  65. package/.output/server/_libs/verkit.mjs +102 -1
  66. package/.output/server/_ssr/BundleIdDisplay-x94o9rlU.mjs +13 -0
  67. package/.output/server/_ssr/ConsoleFeatureUnavailable-ldW8v8-q.mjs +58 -0
  68. package/.output/server/_ssr/EventDetails-Q8kfj9Nr.mjs +344 -0
  69. package/.output/server/_ssr/{HashValueDisplay-CyMmr0O9.mjs → HashValueDisplay-n1GholGS.mjs} +3 -3
  70. package/.output/server/_ssr/InsightsInfo-DuJFatQO.mjs +75 -0
  71. package/.output/server/_ssr/InsightsPageHeader-BSUX3Ye9.mjs +145 -0
  72. package/.output/server/_ssr/NotFoundPage-DZzOOzS3.mjs +37 -0
  73. package/.output/server/_ssr/{dialog-CKvQ4VIE.mjs → alert-dialog-C43Doa0I.mjs} +6 -83
  74. package/.output/server/_ssr/{api-keys-CzZ7Ont4.mjs → api-keys-B4sYm8dM.mjs} +48 -9
  75. package/.output/server/_ssr/api-keys-CEnM9fqG.mjs +5 -0
  76. package/.output/server/_ssr/api-keys-rpc-BIFuUgMt.mjs +52 -0
  77. package/.output/server/_ssr/api-oZjRn9tP.mjs +186 -0
  78. package/.output/server/_ssr/api-rpc-BNiFRRK8.mjs +240 -0
  79. package/.output/server/_ssr/{auth-BF8mbAgF.mjs → auth-UP0wXs4i.mjs} +1 -1
  80. package/.output/server/_ssr/{auth-rpc-DH6Bhwcz.mjs → auth-rpc-DnZqYxyq.mjs} +6 -6
  81. package/.output/server/_ssr/auth.server-DFpyxRDd.mjs +5374 -0
  82. package/.output/server/_ssr/bundleActivity-M5gzBFNg.mjs +18 -0
  83. package/.output/server/_ssr/config-WVX4IxSR.mjs +15 -0
  84. package/.output/server/_ssr/config.server-DskXCAyI.mjs +35 -0
  85. package/.output/server/_ssr/console-access-BJfAXknd.mjs +17 -0
  86. package/.output/server/_ssr/console-features-Oz0q20jJ.mjs +61 -0
  87. package/.output/server/_ssr/console-features-api-C9kiKvaV.mjs +43 -0
  88. package/.output/server/_ssr/console-features-rpc-P0GL7Z-R.mjs +19 -0
  89. package/.output/server/_ssr/{createServerFn-B2hcXoPM.mjs → createMiddleware-Cm6Tn0_Y.mjs} +67 -56
  90. package/.output/server/_ssr/{createServerRpc-DB29C_5p.mjs → createServerRpc-RLR4H-Fn.mjs} +2 -2
  91. package/.output/server/_ssr/databaseConfig-C5SkAyUy.mjs +5 -0
  92. package/.output/server/_ssr/{databaseJsonValue-d6I3nAS4.mjs → databaseJsonValue-Csbuzc9Q.mjs} +28 -5
  93. package/.output/server/_ssr/databaseRows-CPphvbag.mjs +73 -0
  94. package/.output/server/_ssr/dialog-BbYDMjdC.mjs +84 -0
  95. package/.output/server/_ssr/{dist-CyzPaI5v.mjs → dist-CbQbBIw-.mjs} +140 -7
  96. package/.output/server/_ssr/{downloadBundle-CI7JUKvC.mjs → downloadBundle-CZysjmNW.mjs} +10 -10
  97. package/.output/server/_ssr/empty-CVLGfxuu.mjs +60 -0
  98. package/.output/server/_ssr/{empty-plugin-adapters-B5QvGpEl.mjs → empty-plugin-adapters-CPtwX8a7.mjs} +1 -1
  99. package/.output/server/_ssr/failureReports-DKDhVsXA.mjs +33 -0
  100. package/.output/server/_ssr/field-asw83X0v.mjs +189 -0
  101. package/.output/server/_ssr/getBundleChildren-Cv9iz1As.mjs +22 -0
  102. package/.output/server/_ssr/{input-group-BrGSjz4S.mjs → input-group-CuYJHosb.mjs} +2 -2
  103. package/.output/server/_ssr/insights-B55FG5fm.mjs +14 -0
  104. package/.output/server/_ssr/insights-CWnHIFUV.mjs +5 -0
  105. package/.output/server/_ssr/insights-CpLpedFZ.mjs +2315 -0
  106. package/.output/server/_ssr/insights-api-sjws23WF.mjs +122 -0
  107. package/.output/server/_ssr/insights-errors-BjnFUyZj.mjs +34 -0
  108. package/.output/server/_ssr/insights-failures-rpc-BvbWvqNf.mjs +36 -0
  109. package/.output/server/_ssr/insights-failures-xaa41Buf.mjs +46 -0
  110. package/.output/server/_ssr/insights-recovery-BWQhiZaF.mjs +28 -0
  111. package/.output/server/_ssr/insights-recovery-rpc-GiYXdkaY.mjs +32 -0
  112. package/.output/server/_ssr/{insights-rpc-DDKmIrpV.mjs → insights-rpc-DP_8Rmz4.mjs} +22 -14
  113. package/.output/server/_ssr/insights-usage-BpBM0U0c.mjs +29 -0
  114. package/.output/server/_ssr/insights-usage-rpc-BiolgB8e.mjs +29 -0
  115. package/.output/server/_ssr/insights-usage-rpc-KStL0zOx.mjs +41 -0
  116. package/.output/server/_ssr/insightsUsage-CzhVjsc8.mjs +56 -0
  117. package/.output/server/_ssr/insights_.distribution-CVrnbP3R.mjs +7 -0
  118. package/.output/server/_ssr/insights_.distribution-D2HaNTAA.mjs +16 -0
  119. package/.output/server/_ssr/{insights_.distribution-cIsU-kHG.mjs → insights_.distribution-DN9pR422.mjs} +50 -22
  120. package/.output/server/_ssr/installations-BHmbbnH8.mjs +5 -0
  121. package/.output/server/_ssr/{installations-C5anhyP0.mjs → installations-BSCmFq8Q.mjs} +279 -367
  122. package/.output/server/_ssr/installations-DD1g__Nc.mjs +69 -0
  123. package/.output/server/_ssr/listReleases-BfUBlCHo.mjs +79 -0
  124. package/.output/server/_ssr/plugins-BaD1slHx.mjs +2086 -0
  125. package/.output/server/_ssr/release-adoption-005tQRpo.mjs +55 -0
  126. package/.output/server/_ssr/release-adoption-rpc-BsstqxUp.mjs +41 -0
  127. package/.output/server/_ssr/releaseAdoption-CtOFkwli.mjs +114 -0
  128. package/.output/server/_ssr/releaseManagement-DFMUnDF5.mjs +11 -0
  129. package/.output/server/_ssr/remote-config-C2Ee8lXO.mjs +5 -0
  130. package/.output/server/_ssr/remote-config-Dv1ccMo-.mjs +17 -0
  131. package/.output/server/_ssr/remote-config-of0lGQH8.mjs +2648 -0
  132. package/.output/server/_ssr/remote-config-rpc-BzX31mUS.mjs +115 -0
  133. package/.output/server/_ssr/rolldown-runtime-rSIU-vHC.mjs +13 -0
  134. package/.output/server/_ssr/{router-BuanSsRI.mjs → router-D8NuoJ_I.mjs} +107 -134
  135. package/.output/server/_ssr/{routes-DY-vqU6R.mjs → routes-DgvnFqDy.mjs} +195 -429
  136. package/.output/server/_ssr/routes-V8sDybGf.mjs +409 -0
  137. package/.output/server/_ssr/runtime.server-De0QVWc9.mjs +104 -0
  138. package/.output/server/_ssr/schema-BiAVyEj2.mjs +361 -0
  139. package/.output/server/_ssr/{select-DD2szs3Y.mjs → select-t3iXRwc9.mjs} +3 -3
  140. package/.output/server/_ssr/server-h4VxnExB.mjs +8325 -0
  141. package/.output/server/_ssr/{createSsrRpc-CdlfejmI.mjs → sidebar-DJcErBMo.mjs} +107 -47
  142. package/.output/server/_ssr/ssr.mjs +1 -1
  143. package/.output/server/_ssr/start-BfFbHKMK.mjs +4 -0
  144. package/.output/server/_ssr/switch-E-btwMGt.mjs +43 -0
  145. package/.output/server/_ssr/{table-CTj6n-4F.mjs → table-37Dd23TN.mjs} +2 -2
  146. package/.output/server/_ssr/tabs-DEFnTm95.mjs +45 -0
  147. package/.output/server/_ssr/updateFailures-H6pnnYK4.mjs +40 -0
  148. package/.output/server/_ssr/{uuidv7-D0QFkPL_.mjs → uuidv7-C88s9jWF.mjs} +2 -2
  149. package/.output/server/_tanstack-start-manifest_v-55AGsehh.mjs +139 -0
  150. package/.output/server/index.mjs +309 -211
  151. package/LICENSE +13 -14
  152. package/README.md +80 -71
  153. package/lib/index.d.mts +23 -11
  154. package/lib/vite-internal.mjs +13 -3
  155. package/lib/vite.d.mts +2 -0
  156. package/package.json +14 -14
  157. package/src/components/AppSidebar.tsx +69 -74
  158. package/src/components/ConsoleFeatureUnavailable.tsx +80 -0
  159. package/src/components/NotFoundPage.tsx +7 -7
  160. package/src/components/features/FeatureSlots.tsx +103 -0
  161. package/src/components/features/api-keys/apiKeysFeatureUi.tsx +15 -0
  162. package/src/components/features/bundles/BundleMetadata.tsx +8 -5
  163. package/src/components/features/bundles/RolloutCohortsDialog.tsx +1 -1
  164. package/src/components/features/channels/ChannelManagementDialog.tsx +8 -6
  165. package/src/components/features/insights/AppUsage.tsx +41 -14
  166. package/src/components/features/insights/BuiltinBundle.tsx +36 -0
  167. package/src/components/features/insights/ComparedBundlesChart.tsx +310 -0
  168. package/src/components/features/insights/EstimatedCount.tsx +18 -0
  169. package/src/components/features/insights/EventDetails.tsx +390 -26
  170. package/src/components/features/insights/EventHistoryCard.tsx +111 -25
  171. package/src/components/features/insights/EventHistoryList.tsx +1 -1
  172. package/src/components/features/insights/FailureReports.tsx +407 -0
  173. package/src/components/features/insights/InsightsControls.tsx +240 -142
  174. package/src/components/features/insights/InsightsErrorAlert.tsx +14 -1
  175. package/src/components/features/insights/InsightsOverview.tsx +601 -403
  176. package/src/components/features/insights/InsightsPageHeader.tsx +19 -14
  177. package/src/components/features/insights/InsightsPeriodSelector.tsx +67 -12
  178. package/src/components/features/insights/InstallationHistoryCard.tsx +65 -10
  179. package/src/components/features/insights/InstallationMatchesCard.tsx +1 -1
  180. package/src/components/features/insights/ReleaseActivity.tsx +308 -0
  181. package/src/components/features/insights/ReportingDevicesSummary.tsx +13 -13
  182. package/src/components/features/insights/RollbackButton.tsx +118 -0
  183. package/src/components/features/insights/UpdateFailures.tsx +382 -0
  184. package/src/components/features/insights/insightsFeatureUi.tsx +35 -0
  185. package/src/components/features/releases/ReleaseEditorSheet.tsx +27 -13
  186. package/src/components/features/remote-config/ConditionDialog.tsx +592 -0
  187. package/src/components/features/remote-config/ConditionsCard.tsx +247 -0
  188. package/src/components/features/remote-config/ParameterDialog.tsx +426 -0
  189. package/src/components/features/remote-config/ParametersCard.tsx +254 -0
  190. package/src/components/features/remote-config/PreviewCard.tsx +284 -0
  191. package/src/components/features/remote-config/PublishDialog.tsx +325 -0
  192. package/src/components/features/remote-config/RemoteConfigPage.tsx +353 -0
  193. package/src/components/features/remote-config/RuleSummary.tsx +21 -0
  194. package/src/components/features/remote-config/ValueInput.tsx +151 -0
  195. package/src/components/features/remote-config/VersionsCard.tsx +384 -0
  196. package/src/components/features/remote-config/remoteConfigFeatureUi.tsx +15 -0
  197. package/src/components/features/remote-config/useDateTimeText.ts +16 -0
  198. package/src/components/ui/sidebar.tsx +22 -29
  199. package/src/index.ts +26 -19
  200. package/src/lib/api-keys-api.ts +0 -28
  201. package/src/lib/api-keys-rpc.ts +27 -38
  202. package/src/lib/api-rpc.ts +125 -288
  203. package/src/lib/api.ts +15 -134
  204. package/src/lib/bundle-activity.ts +24 -4
  205. package/src/lib/console-access.ts +20 -0
  206. package/src/lib/console-features-api.ts +68 -0
  207. package/src/lib/console-features-rpc.ts +13 -0
  208. package/src/lib/console-features.ts +98 -0
  209. package/src/lib/insights-api.ts +56 -2
  210. package/src/lib/insights-errors.ts +64 -0
  211. package/src/lib/insights-failures-rpc.ts +36 -0
  212. package/src/lib/insights-failures.ts +130 -0
  213. package/src/lib/insights-recovery-rpc.ts +13 -17
  214. package/src/lib/insights-recovery.ts +12 -36
  215. package/src/lib/insights-retention.ts +21 -0
  216. package/src/lib/insights-rpc.ts +30 -12
  217. package/src/lib/insights-search.ts +50 -4
  218. package/src/lib/insights-usage-rpc.ts +15 -9
  219. package/src/lib/insights-usage.ts +41 -3
  220. package/src/lib/insights-view.ts +34 -5
  221. package/src/lib/release-adoption-api.ts +214 -0
  222. package/src/lib/release-adoption-rpc.ts +49 -0
  223. package/src/lib/release-adoption.ts +164 -0
  224. package/src/lib/remote-config-api.ts +119 -0
  225. package/src/lib/remote-config-draft.ts +666 -0
  226. package/src/lib/remote-config-rpc.ts +196 -0
  227. package/src/lib/scroll-restoration.ts +21 -0
  228. package/src/lib/server/auth.server.ts +13 -5
  229. package/src/lib/server/bundleActivity.ts +27 -28
  230. package/src/lib/server/config.server.ts +21 -76
  231. package/src/lib/server/console-feature-apis.ts +70 -0
  232. package/src/lib/server/console-runtime.server.ts +82 -38
  233. package/src/lib/server/downloadBundle.ts +14 -15
  234. package/src/lib/server/failureReports.ts +50 -0
  235. package/src/lib/server/getBundleChildren.ts +31 -122
  236. package/src/lib/server/insightsUsage.ts +52 -113
  237. package/src/lib/server/listReleases.ts +109 -44
  238. package/src/lib/server/releaseAdoption.ts +151 -0
  239. package/src/lib/server/releaseReachability.ts +8 -8
  240. package/src/lib/server/remoteConfig.ts +75 -0
  241. package/src/lib/server/runtime.server.ts +120 -31
  242. package/src/lib/server/updateFailures.ts +66 -0
  243. package/src/lib/use-dialog-target.ts +27 -0
  244. package/src/routeTree.gen.ts +44 -44
  245. package/src/router.tsx +3 -2
  246. package/src/routes/-installations-search.ts +32 -8
  247. package/src/routes/-releases-search.ts +76 -29
  248. package/src/routes/__root.tsx +7 -1
  249. package/src/routes/api/bundles/$bundleId/download.ts +2 -5
  250. package/src/routes/api-keys.tsx +5 -2
  251. package/src/routes/index.tsx +210 -152
  252. package/src/routes/insights.tsx +91 -23
  253. package/src/routes/insights_.distribution.tsx +50 -9
  254. package/src/routes/installations.tsx +97 -40
  255. package/src/routes/remote-config.tsx +42 -0
  256. package/src/styles.css +9 -0
  257. package/src/vite-internal.ts +15 -3
  258. package/src/vite.ts +2 -0
  259. package/.output/public/assets/HashValueDisplay-BpTc3Oyg.js +0 -1
  260. package/.output/public/assets/InsightsPageHeader-DC2eEst8.js +0 -1
  261. package/.output/public/assets/api-CdUyUqzR.js +0 -42
  262. package/.output/public/assets/api-keys-64PM9PwW.js +0 -1
  263. package/.output/public/assets/api-keys-api-BeaJnvY5.js +0 -1
  264. package/.output/public/assets/arrow-left-04Rh8Zgp.js +0 -1
  265. package/.output/public/assets/card-CYHs5FZv.js +0 -1
  266. package/.output/public/assets/chart-no-axes-combined-DwyMsVFW.js +0 -1
  267. package/.output/public/assets/createServerFn-DU71xucx.js +0 -3
  268. package/.output/public/assets/dialog-IVMkBRCq.js +0 -1
  269. package/.output/public/assets/dist-BR4GzeEu.js +0 -1
  270. package/.output/public/assets/field-B3CYDpjg.js +0 -1
  271. package/.output/public/assets/index-Cb_D1D6N.js +0 -10
  272. package/.output/public/assets/info-C3y9HNoU.js +0 -1
  273. package/.output/public/assets/input-group-nLZylhWF.js +0 -1
  274. package/.output/public/assets/insights-Bm9v8uO3.js +0 -2
  275. package/.output/public/assets/insights-DS3iO7Up.js +0 -1
  276. package/.output/public/assets/insights-search-Byj3g3Mp.js +0 -1
  277. package/.output/public/assets/insights-usage-rpc-BaGR3lgq.js +0 -1
  278. package/.output/public/assets/insights_.distribution-B1i6cjlQ.js +0 -1
  279. package/.output/public/assets/insights_.distribution-C1Wf27eB.js +0 -2
  280. package/.output/public/assets/installations-CkFW4fV9.js +0 -2
  281. package/.output/public/assets/installations-DxTaIcHD.js +0 -1
  282. package/.output/public/assets/lazyRouteComponent-BapzjYnb.js +0 -1
  283. package/.output/public/assets/list-Dqt53fWZ.js +0 -1
  284. package/.output/public/assets/loader-circle-CUKfUqow.js +0 -1
  285. package/.output/public/assets/preload-helper-ClBMtM1g.js +0 -1
  286. package/.output/public/assets/refresh-cw-CNE_2PnD.js +0 -1
  287. package/.output/public/assets/routes-Cgtvspjg.js +0 -2
  288. package/.output/public/assets/routes-O2r2UUN8.js +0 -1
  289. package/.output/public/assets/shield-check-BFcJ46kz.js +0 -1
  290. package/.output/public/assets/signing-BgspC-xP.js +0 -1
  291. package/.output/public/assets/styles-DnrWuBwd.css +0 -2
  292. package/.output/public/assets/table-BuWQgxJJ.js +0 -1
  293. package/.output/public/assets/useMutation-CSV9NCUl.js +0 -1
  294. package/.output/public/assets/useOpenInteractionType-D5kduCTD.js +0 -1
  295. package/.output/public/assets/valueToPercent-BAtcbSLk.js +0 -1
  296. package/.output/server/__23tanstack-start-server-fn-resolver-DBRojHaG.mjs +0 -150
  297. package/.output/server/_ssr/InsightsPageHeader-mtxVuZKK.mjs +0 -64
  298. package/.output/server/_ssr/api-BfCgYlj5.mjs +0 -332
  299. package/.output/server/_ssr/api-keys-api-C3oeq01R.mjs +0 -60
  300. package/.output/server/_ssr/api-keys-rpc-CdPFdGOx.mjs +0 -136
  301. package/.output/server/_ssr/api-rpc-B2E1ZIG5.mjs +0 -1399
  302. package/.output/server/_ssr/auth.server-CmicHh0J.mjs +0 -47
  303. package/.output/server/_ssr/bundle-signing-rpc-Di7-I6fE.mjs +0 -16
  304. package/.output/server/_ssr/bundle-signing.server-Uqt1OF49.mjs +0 -12
  305. package/.output/server/_ssr/bundleActivity-pBrPSG01.mjs +0 -28
  306. package/.output/server/_ssr/card-Bemj0dpY.mjs +0 -108
  307. package/.output/server/_ssr/config-Dv8qLDZ0.mjs +0 -13
  308. package/.output/server/_ssr/config.server-B8WsT3s0.mjs +0 -368
  309. package/.output/server/_ssr/databaseRows-5bCRTxm-.mjs +0 -126
  310. package/.output/server/_ssr/deleteBundle-8X-jq7Z7.mjs +0 -66
  311. package/.output/server/_ssr/field-BrQ2u0fT.mjs +0 -74
  312. package/.output/server/_ssr/getBundleChildren-DoL8l_AS.mjs +0 -50
  313. package/.output/server/_ssr/insights-BwQ-wF2a.mjs +0 -10
  314. package/.output/server/_ssr/insights-gr1I_dJU.mjs +0 -938
  315. package/.output/server/_ssr/insights-recovery-Cv6RSyeR.mjs +0 -21
  316. package/.output/server/_ssr/insights-recovery-rpc-DOzxfYfv.mjs +0 -37
  317. package/.output/server/_ssr/insights-search-1czJMZgk.mjs +0 -21
  318. package/.output/server/_ssr/insights-usage-rpc-4ImOq_0p.mjs +0 -184
  319. package/.output/server/_ssr/insights-usage-rpc-BUruODjE.mjs +0 -24
  320. package/.output/server/_ssr/insightsContract-B09K_Px1.mjs +0 -303
  321. package/.output/server/_ssr/insightsHistory-Ci4rYAgl.mjs +0 -41
  322. package/.output/server/_ssr/insightsRecovery-CaghWL2t.mjs +0 -113
  323. package/.output/server/_ssr/insightsUsage-DNIj6jxF.mjs +0 -71
  324. package/.output/server/_ssr/insights_.distribution-VmHuikRE.mjs +0 -10
  325. package/.output/server/_ssr/installations-HXMF_kKf.mjs +0 -29
  326. package/.output/server/_ssr/routes-Dru3IRj0.mjs +0 -37
  327. package/.output/server/_ssr/runtime.server-CsiKFp_Z.mjs +0 -436
  328. package/.output/server/_ssr/server-DJm72Kj-.mjs +0 -7468
  329. package/.output/server/_ssr/signing-H8Lg4lPe.mjs +0 -133
  330. package/.output/server/_ssr/start-DpViQGnt.mjs +0 -4
  331. package/.output/server/_tanstack-start-manifest_v-DsFcTLw_.mjs +0 -125
  332. package/src/components/features/bundles/BundleActivityChart.tsx +0 -97
  333. package/src/components/features/bundles/BundleInsightsSummary.tsx +0 -126
  334. package/src/components/features/signing/BundleSigningPage.tsx +0 -139
  335. package/src/lib/bundle-signing-api.ts +0 -14
  336. package/src/lib/bundle-signing-rpc.ts +0 -16
  337. package/src/lib/server/bundle-signing.server.ts +0 -23
  338. package/src/lib/server/deleteBundle.ts +0 -145
  339. package/src/lib/server/insightsHistory.ts +0 -52
  340. package/src/lib/server/insightsRecovery.ts +0 -187
  341. package/src/routes/signing.tsx +0 -37
@@ -1,124 +1,19 @@
1
1
  import { i as __toESM } from "../_runtime.mjs";
2
- import { c as createServerFn } from "./createServerFn-B2hcXoPM.mjs";
3
- import { ht as require_react, mt as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
4
- import { B as Activity, F as Check, L as ArrowUpRight, P as ChevronDown, d as RotateCcw, f as RefreshCw, l as Search, t as X, z as ArrowLeft } from "../_libs/lucide-react.mjs";
5
- import { C as cn, S as buttonVariants, _ as Skeleton, r as Separator$1, t as Button$1, w as createSsrRpc } from "./createSsrRpc-CdlfejmI.mjs";
6
- import { m as Link, s as useElementScrollRestoration } from "../_libs/@tanstack/react-router+[...].mjs";
7
- import { n as useQuery } from "../_libs/tanstack__react-query.mjs";
8
- import { a as Badge, d as CardTitle, o as Card, s as CardContent, u as CardHeader } from "./card-Bemj0dpY.mjs";
9
- import { a as FieldLabel, t as Field } from "./field-BrQ2u0fT.mjs";
10
- import { a as TableHeader, i as TableHead, n as TableBody, o as TableRow, r as TableCell, t as Table } from "./table-CTj6n-4F.mjs";
11
- import { i as InputGroupInput, n as InputGroupAddon, r as InputGroupButton, t as InputGroup } from "./input-group-BrGSjz4S.mjs";
12
- import { n as InsightsPageHeader, t as InsightsErrorAlert } from "./InsightsPageHeader-mtxVuZKK.mjs";
13
- import { n as getInsightsScrollRestorationKey, t as Route } from "./installations-HXMF_kKf.mjs";
14
- import { n as shortenIdentifier, t as HashValueDisplay } from "./HashValueDisplay-CyMmr0O9.mjs";
15
- //#region node_modules/.nitro/vite/services/ssr/assets/installations-C5anhyP0.js
2
+ import { _t as require_react, gt as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
3
+ import { $ as ArrowLeft, G as Check, W as ChevronDown, X as ArrowUpRight, g as RefreshCw, p as Search, t as X } from "../_libs/lucide-react.mjs";
4
+ import { C as Skeleton, O as buttonVariants, k as cn, r as Separator$1, t as Button$1 } from "./sidebar-DJcErBMo.mjs";
5
+ import { c as CardDescription, d as CardTitle, f as Field, g as FieldLabel, o as Card, s as CardContent, u as CardHeader } from "./field-asw83X0v.mjs";
6
+ import { a as TableHeader, i as TableHead, n as TableBody, o as TableRow, r as TableCell, t as Table } from "./table-37Dd23TN.mjs";
7
+ import { c as useElementScrollRestoration, h as Link, o as useLocation } from "../_libs/@tanstack/react-router+[...].mjs";
8
+ import { a as useInsightsEventsQuery, c as useInsightsInstallationsQuery, l as useInsightsRetention, n as formatDays, o as useInsightsInstallationEventsQuery, s as useInsightsInstallationQuery, t as DEFAULT_INSIGHTS_RETENTION } from "./insights-api-sjws23WF.mjs";
9
+ import { i as InputGroupInput, n as InputGroupAddon, r as InputGroupButton, t as InputGroup } from "./input-group-CuYJHosb.mjs";
10
+ import { a as PeriodSelector, n as InsightsErrorAlert, r as InsightsPageHeader, s as isBuiltinBundle, t as BuiltinBundleBadge } from "./InsightsPageHeader-BSUX3Ye9.mjs";
11
+ import { n as shortenIdentifier, t as HashValueDisplay } from "./HashValueDisplay-n1GholGS.mjs";
12
+ import { a as HttpResponseDetails, n as EventTimestamp, o as useInsightsTimeFormat, r as EventTypeDetails, t as EventBundleTransition } from "./EventDetails-Q8kfj9Nr.mjs";
13
+ import { a as installationsScrollRestorationKey, i as eventRanges, n as Route, o as widerEventRange, r as eventRangeBounds, t as EVENT_RANGES } from "./installations-DD1g__Nc.mjs";
14
+ //#region node_modules/.nitro/vite/services/ssr/assets/installations-BSCmFq8Q.js
16
15
  var import_react = /* @__PURE__ */ __toESM(require_react());
17
16
  var import_jsx_runtime = require_jsx_runtime();
18
- var eventTypes = {
19
- UPDATE_APPLIED: {
20
- label: "Update applied",
21
- description: "The app started using the downloaded update.",
22
- variant: "success",
23
- icon: Check
24
- },
25
- RECOVERED: {
26
- label: "Rolled back",
27
- description: "The app recovered to a previous working bundle.",
28
- variant: "warning",
29
- icon: RotateCcw
30
- },
31
- UNCHANGED: {
32
- label: "No change",
33
- description: "The app continues using the same bundle files.",
34
- variant: "secondary",
35
- icon: Activity
36
- }
37
- };
38
- function useInsightsTimeFormat() {
39
- const [timeZone, setTimeZone] = (0, import_react.useState)("UTC");
40
- (0, import_react.useEffect)(() => {
41
- setTimeZone(Intl.DateTimeFormat().resolvedOptions().timeZone);
42
- }, []);
43
- return new Intl.DateTimeFormat("en", {
44
- timeZone,
45
- timeZoneName: "shortOffset",
46
- year: "numeric",
47
- month: "2-digit",
48
- day: "2-digit",
49
- hour: "2-digit",
50
- minute: "2-digit",
51
- second: "2-digit",
52
- hourCycle: "h23"
53
- });
54
- }
55
- function formatInsightsTimestamp(value, formatter) {
56
- const parts = Object.fromEntries(formatter.formatToParts(new Date(value)).map(({ type, value }) => [type, value]));
57
- const offset = parts.timeZoneName === "GMT" ? "GMT+0" : parts.timeZoneName;
58
- return `${parts.year}/${parts.month}/${parts.day} ${parts.hour}:${parts.minute}:${parts.second} ${offset}`;
59
- }
60
- function EventTimestamp({ value, formatter, touch = false }) {
61
- const date = new Date(value);
62
- const localTime = formatInsightsTimestamp(value, formatter);
63
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", {
64
- className: "group/time",
65
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", {
66
- className: `cursor-pointer list-none rounded-md outline-none focus-visible:ring-2 focus-visible:ring-ring/30 [&::-webkit-details-marker]:hidden ${touch ? "flex min-h-11 items-center" : ""}`,
67
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
68
- className: "flex items-center gap-1",
69
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("time", {
70
- dateTime: date.toISOString(),
71
- className: "whitespace-nowrap",
72
- children: localTime
73
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, {
74
- "aria-hidden": "true",
75
- className: "size-3 text-muted-foreground group-open/time:rotate-180"
76
- })]
77
- })
78
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
79
- className: "mt-2 text-muted-foreground",
80
- children: date.toISOString().replace("T", " ").replace("Z", " UTC")
81
- })]
82
- });
83
- }
84
- function EventTypeDetails({ type }) {
85
- const eventType = eventTypes[type];
86
- const Icon = eventType.icon;
87
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
88
- className: "flex min-w-0 flex-col items-start gap-2",
89
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge, {
90
- variant: eventType.variant,
91
- className: "gap-1 whitespace-nowrap [&_svg]:size-3",
92
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Icon, { "aria-hidden": "true" }), eventType.label]
93
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
94
- className: "max-w-56 whitespace-normal text-xs text-muted-foreground",
95
- children: eventType.description
96
- })]
97
- });
98
- }
99
- function EventBundleTransition({ event, touch = false }) {
100
- const changed = event.type === "UPDATE_APPLIED" || event.type === "RECOVERED";
101
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", {
102
- className: "grid grid-cols-[auto_minmax(0,1fr)] items-center gap-x-2 gap-y-2",
103
- children: [
104
- event.fromBundleId && changed ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
105
- className: "text-muted-foreground",
106
- children: "From"
107
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HashValueDisplay, {
108
- value: event.fromBundleId,
109
- buttonClassName: touch ? "min-h-11 px-3" : void 0
110
- }) })] }) : null,
111
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
112
- className: "text-muted-foreground",
113
- children: changed ? "To" : "Current"
114
- }),
115
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HashValueDisplay, {
116
- value: event.toBundleId,
117
- buttonClassName: touch ? "min-h-11 px-3" : void 0
118
- }) })
119
- ]
120
- });
121
- }
122
17
  function EventHistoryList({ events, formatter, renderIdentity }) {
123
18
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
124
19
  className: "px-4 pb-2 text-xs text-muted-foreground sm:px-6",
@@ -131,7 +26,7 @@ function EventHistoryList({ events, formatter, renderIdentity }) {
131
26
  children: [
132
27
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
133
28
  className: "flex flex-wrap items-center justify-between gap-x-4 gap-y-1",
134
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventTypeDetails, { type: event.type }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
29
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventTypeDetails, { event }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
135
30
  className: "text-xs tabular-nums",
136
31
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventTimestamp, {
137
32
  value: event.receivedAtMs,
@@ -208,6 +103,8 @@ function InsightsPagination({ hasPrevious, label, nextCursor, onNext, onPrevious
208
103
  })]
209
104
  });
210
105
  }
106
+ /** The ranges within the days raw events are kept, the shortest always. */
107
+ var rangesWithin = (days) => EVENT_RANGES.filter((value, position) => position === 0 || eventRanges[value].durationMs <= days * 864e5);
211
108
  function EventIdentity({ event, eventsLocation, touch = false }) {
212
109
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
213
110
  className: touch ? "flex min-w-0 flex-wrap items-center justify-between gap-2" : "flex min-w-0 flex-col items-start gap-2",
@@ -223,10 +120,11 @@ function EventIdentity({ event, eventsLocation, touch = false }) {
223
120
  query: event.installId || void 0,
224
121
  installId: event.installId
225
122
  },
226
- "aria-label": `View history for ${event.userId ?? event.username ?? "anonymous installation"} (${event.installId})`,
123
+ state: (previous) => ({ insightsPagination: { eventsBack: previous.insightsPagination?.eventsBack } }),
124
+ "aria-label": `View history for ${event.userId ?? "anonymous installation"} (${event.installId})`,
227
125
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
228
126
  className: touch ? "min-w-0 text-left wrap-anywhere" : "truncate",
229
- children: event.userId ?? event.username ?? "Anonymous installation"
127
+ children: event.userId ?? "Anonymous installation"
230
128
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowUpRight, {
231
129
  "aria-hidden": "true",
232
130
  "data-icon": "inline-end"
@@ -238,27 +136,51 @@ function EventIdentity({ event, eventsLocation, touch = false }) {
238
136
  })]
239
137
  });
240
138
  }
241
- function EventHistoryCard({ children, error, eventsLocation, history, isFetching, isLoading, onNext, onPrevious, onRefresh, pageNumber, title = "All events" }) {
139
+ function EventHistoryCard({ children, description, error, eventsLocation, history, isFetching, isLoading, onNext, onPrevious, onRangeChange, onRefresh, pageNumber, range, rawDays = 90, title = "All events" }) {
242
140
  const dateTimeFormat = useInsightsTimeFormat();
243
141
  const hasPrevious = pageNumber > 1;
142
+ const ranges = rangesWithin(rawDays);
143
+ const next = range === void 0 ? void 0 : widerEventRange(range);
144
+ const wider = next !== void 0 && ranges.includes(next) ? next : void 0;
145
+ const widen = wider !== void 0 && onRangeChange ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
146
+ className: "h-11 px-3 lg:h-8",
147
+ onClick: () => onRangeChange(wider),
148
+ type: "button",
149
+ variant: "outline",
150
+ children: `Show the last ${eventRanges[wider].period}`
151
+ }) : null;
244
152
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, {
245
153
  className: "@container min-w-0 shadow-sm",
246
154
  "aria-busy": isFetching,
247
155
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardHeader, {
248
156
  className: "gap-4 p-4 sm:p-6",
249
157
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
250
- className: "flex flex-wrap items-center justify-between gap-3",
251
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: title }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
252
- className: "h-11 lg:h-8",
253
- disabled: isFetching,
254
- onClick: onRefresh,
255
- size: "lg",
256
- variant: "outline",
257
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, {
258
- "aria-hidden": "true",
259
- "data-icon": "inline-start"
260
- }), "Refresh"]
261
- })]
158
+ className: "flex flex-col gap-1.5",
159
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
160
+ className: "flex flex-wrap items-center justify-between gap-3",
161
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: title }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
162
+ className: "flex flex-wrap items-center gap-2",
163
+ children: [range !== void 0 && onRangeChange ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PeriodSelector, {
164
+ label: "Time range",
165
+ onPeriodChange: onRangeChange,
166
+ period: range,
167
+ periods: ranges.map((value) => ({
168
+ value,
169
+ name: `Last ${eventRanges[value].period}`
170
+ }))
171
+ }) : null, /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
172
+ className: "h-11 lg:h-8",
173
+ disabled: isFetching,
174
+ onClick: onRefresh,
175
+ size: "lg",
176
+ variant: "outline",
177
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RefreshCw, {
178
+ "aria-hidden": "true",
179
+ "data-icon": "inline-start"
180
+ }), "Refresh"]
181
+ })]
182
+ })]
183
+ }), description ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardDescription, { children: description }) : null]
262
184
  }), children]
263
185
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, {
264
186
  className: "min-w-0 p-0",
@@ -277,113 +199,136 @@ function EventHistoryCard({ children, error, eventsLocation, history, isFetching
277
199
  error,
278
200
  fallbackTitle: "Event history unavailable"
279
201
  })
280
- }) : history ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [history.data.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
281
- className: "@[58rem]:hidden",
282
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventHistoryList, {
283
- events: history.data,
284
- formatter: dateTimeFormat,
285
- renderIdentity: (event) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventIdentity, {
286
- event,
287
- eventsLocation,
288
- touch: true
202
+ }) : history ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
203
+ history.data.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
204
+ className: "@[58rem]:hidden",
205
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventHistoryList, {
206
+ events: history.data,
207
+ formatter: dateTimeFormat,
208
+ renderIdentity: (event) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventIdentity, {
209
+ event,
210
+ eventsLocation,
211
+ touch: true
212
+ })
289
213
  })
290
- })
291
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
292
- className: "hidden @[58rem]:block",
293
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table, {
294
- className: "min-w-4xl table-fixed",
295
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableRow, {
296
- className: "[&>th]:px-4 sm:[&>th]:px-6",
297
- children: [
298
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
299
- className: "w-64",
300
- children: "Time"
301
- }),
302
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
303
- className: "w-48",
304
- children: "Event"
305
- }),
306
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
307
- className: "w-48",
308
- children: "User / installation"
309
- }),
310
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
311
- className: "w-32",
312
- children: "App"
313
- }),
314
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
315
- className: "w-52",
316
- children: "Bundle"
317
- })
318
- ]
319
- }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableBody, { children: history.data.map((event) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableRow, {
320
- className: "[&>td]:px-4 [&>td]:py-4 [&>td]:align-top sm:[&>td]:px-6",
321
- children: [
322
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
323
- className: "whitespace-normal text-xs tabular-nums",
324
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventTimestamp, {
325
- value: event.receivedAtMs,
326
- formatter: dateTimeFormat
214
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
215
+ className: "hidden @[58rem]:block",
216
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table, {
217
+ className: "min-w-4xl table-fixed",
218
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableRow, {
219
+ className: "[&>th]:px-4 sm:[&>th]:px-6",
220
+ children: [
221
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
222
+ className: "w-64",
223
+ children: "Time"
224
+ }),
225
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
226
+ className: "w-48",
227
+ children: "Event"
228
+ }),
229
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
230
+ className: "w-48",
231
+ children: "User / installation"
232
+ }),
233
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
234
+ className: "w-32",
235
+ children: "App"
236
+ }),
237
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
238
+ className: "w-52",
239
+ children: "Bundle"
327
240
  })
328
- }),
329
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventTypeDetails, { type: event.type }) }),
330
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventIdentity, {
331
- event,
332
- eventsLocation
333
- }) }),
334
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
335
- className: "whitespace-normal text-xs",
336
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
337
- className: "flex flex-col gap-2",
338
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
339
- event.platform === "ios" ? "iOS" : "Android",
340
- " ",
341
- event.appVersion
342
- ] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
343
- className: "text-muted-foreground",
344
- children: event.channel
345
- })]
241
+ ]
242
+ }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableBody, { children: history.data.map((event) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableRow, {
243
+ className: "[&>td]:px-4 [&>td]:py-4 [&>td]:align-top sm:[&>td]:px-6",
244
+ children: [
245
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
246
+ className: "whitespace-normal text-xs tabular-nums",
247
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventTimestamp, {
248
+ value: event.receivedAtMs,
249
+ formatter: dateTimeFormat
250
+ })
251
+ }),
252
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventTypeDetails, { event }) }),
253
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventIdentity, {
254
+ event,
255
+ eventsLocation
256
+ }) }),
257
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
258
+ className: "whitespace-normal text-xs",
259
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
260
+ className: "flex flex-col gap-2",
261
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
262
+ event.platform === "ios" ? "iOS" : "Android",
263
+ " ",
264
+ event.appVersion
265
+ ] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
266
+ className: "text-muted-foreground",
267
+ children: event.channel
268
+ })]
269
+ })
270
+ }),
271
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
272
+ className: "whitespace-normal text-xs",
273
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventBundleTransition, { event })
346
274
  })
347
- }),
348
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
349
- className: "whitespace-normal text-xs",
350
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventBundleTransition, { event })
351
- })
352
- ]
353
- }, event.id)) })]
354
- })
355
- })] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
356
- className: "px-6 pb-6 text-sm text-muted-foreground",
357
- children: hasPrevious || history.nextCursor ? "No events on this page" : title === "All events" ? "No events recorded yet" : "No matching reports in this period"
358
- }), history.data.length > 0 || hasPrevious || history.nextCursor ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsPagination, {
359
- hasPrevious,
360
- label: title,
361
- nextCursor: history.nextCursor,
362
- onNext,
363
- onPrevious,
364
- pageLength: history.data.length,
365
- pageNumber
366
- }) : null] }) : null
275
+ ]
276
+ }, event.id)) })]
277
+ })
278
+ })] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
279
+ className: "flex flex-wrap items-center justify-between gap-3 px-4 pb-4 sm:px-6 sm:pb-6",
280
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
281
+ className: "text-sm text-muted-foreground",
282
+ children: hasPrevious ? "No older events in this range." : range !== void 0 ? `No events in the last ${eventRanges[range].period}.` : title === "All events" ? "No events recorded yet" : "No matching reports in this period"
283
+ }), hasPrevious ? null : widen]
284
+ }),
285
+ range !== void 0 && history.nextCursor === null && (history.data.length > 0 || hasPrevious) ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
286
+ className: "flex flex-wrap items-center justify-between gap-3 border-t px-4 py-3 sm:px-6",
287
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
288
+ className: "text-sm text-muted-foreground",
289
+ children: "Start of range reached"
290
+ }), widen]
291
+ }) : null,
292
+ history.data.length > 0 || hasPrevious || history.nextCursor ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsPagination, {
293
+ hasPrevious,
294
+ label: title,
295
+ nextCursor: history.nextCursor,
296
+ onNext,
297
+ onPrevious,
298
+ pageLength: history.data.length,
299
+ pageNumber
300
+ }) : null
301
+ ] }) : null
367
302
  })]
368
303
  });
369
304
  }
370
- var getUserLabel$1 = (event) => event.userId ?? event.username ?? "—";
371
- var getLastKnownBundleId$1 = (event) => "lastKnownBundleId" in event ? event.lastKnownBundleId : event.toBundleId ?? event.fromBundleId;
372
- function InstallationHistoryCard({ error, history, isLoading, onNext, onPrevious, onRefresh, pageNumber, selectedEvent, selectedInstallId }) {
305
+ var getUserLabel$1 = (event) => event.userId ?? "—";
306
+ /** A download or a failed update leaves the installation on the bundle it ran. */
307
+ var getLastKnownBundleId$1 = (event) => "lastKnownBundleId" in event ? event.lastKnownBundleId : event.type === "UPDATE_DOWNLOADED" || event.type === "UPDATE_FAILED" ? event.fromBundleId : event.toBundleId;
308
+ function InstallationHistoryCard({ error, history, isLoading, onNext, onPrevious, onRefresh, pageNumber, retention = DEFAULT_INSIGHTS_RETENTION, selectedEvent, selectedInstallId }) {
373
309
  const dateTimeFormat = useInsightsTimeFormat();
374
310
  const lastKnownBundleId = selectedEvent ? getLastKnownBundleId$1(selectedEvent) : void 0;
311
+ const pendingBundleId = selectedEvent && "pendingBundleId" in selectedEvent ? selectedEvent.pendingBundleId : selectedEvent && "type" in selectedEvent && selectedEvent.type === "UPDATE_DOWNLOADED" ? selectedEvent.toBundleId : null;
375
312
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, {
376
313
  className: "@container min-h-0 min-w-0 shadow-sm",
377
314
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, {
378
315
  className: "p-4 sm:p-6",
379
316
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
380
317
  className: "flex flex-wrap items-center justify-between gap-3",
381
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
318
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
382
319
  className: "flex min-w-0 flex-col gap-1.5",
383
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
320
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
384
321
  className: "text-sm font-medium",
385
322
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: selectedInstallId !== void 0 ? "Installation history" : "Select an installation" })
386
- })
323
+ }), selectedInstallId !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardDescription, { children: [
324
+ "Bundle changes and update failures are kept for",
325
+ " ",
326
+ formatDays(retention.rawDays),
327
+ "; the latest report, for",
328
+ " ",
329
+ formatDays(retention.dailyDays),
330
+ " after the installation last reports."
331
+ ] }) : null]
387
332
  }), onRefresh && selectedInstallId !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
388
333
  className: "h-11 lg:h-8",
389
334
  size: "lg",
@@ -401,51 +346,68 @@ function InstallationHistoryCard({ error, history, isLoading, onNext, onPrevious
401
346
  children: [selectedInstallId !== void 0 && selectedEvent ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
402
347
  "aria-labelledby": "latest-installation-state",
403
348
  className: "px-4 pb-4 sm:px-6 sm:pb-6",
404
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
405
- className: "sr-only",
406
- id: "latest-installation-state",
407
- children: "Latest reported state"
408
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", {
409
- className: "grid grid-cols-2 gap-4 @[36rem]:grid-cols-3",
410
- children: [
411
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
412
- className: "col-span-2 min-w-0 @[36rem]:col-span-1",
413
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
414
- className: "text-xs text-muted-foreground",
415
- children: "User ID"
416
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
417
- className: "mt-1 text-sm font-medium wrap-anywhere",
418
- children: getUserLabel$1(selectedEvent)
419
- })]
420
- }),
421
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
422
- className: "min-w-0",
423
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
424
- className: "text-xs text-muted-foreground",
425
- children: "Install ID"
426
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
427
- className: "mt-1 font-mono text-xs",
428
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HashValueDisplay, {
429
- value: selectedInstallId,
430
- buttonClassName: "min-h-11 px-3 lg:min-h-0 lg:px-1.5"
431
- })
432
- })]
433
- }),
434
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
435
- className: "min-w-0",
436
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
437
- className: "text-xs text-muted-foreground",
438
- children: "Last known bundle"
439
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
440
- className: "mt-1 font-mono text-xs",
441
- children: lastKnownBundleId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HashValueDisplay, {
442
- value: lastKnownBundleId,
443
- buttonClassName: "min-h-11 px-3 lg:min-h-0 lg:px-1.5"
444
- }) : "—"
445
- })]
446
- })
447
- ]
448
- })]
349
+ children: [
350
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", {
351
+ className: "sr-only",
352
+ id: "latest-installation-state",
353
+ children: "Latest reported state"
354
+ }),
355
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", {
356
+ className: "grid grid-cols-2 gap-4 @[36rem]:grid-cols-3",
357
+ children: [
358
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
359
+ className: "col-span-2 min-w-0 @[36rem]:col-span-1",
360
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
361
+ className: "text-xs text-muted-foreground",
362
+ children: "User ID"
363
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
364
+ className: "mt-1 text-sm font-medium wrap-anywhere",
365
+ children: getUserLabel$1(selectedEvent)
366
+ })]
367
+ }),
368
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
369
+ className: "min-w-0",
370
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
371
+ className: "text-xs text-muted-foreground",
372
+ children: "Install ID"
373
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
374
+ className: "mt-1 font-mono text-xs",
375
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HashValueDisplay, {
376
+ value: selectedInstallId,
377
+ buttonClassName: "min-h-11 px-3 lg:min-h-0 lg:px-1.5"
378
+ })
379
+ })]
380
+ }),
381
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
382
+ className: "min-w-0",
383
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
384
+ className: "text-xs text-muted-foreground",
385
+ children: "Last known bundle"
386
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dd", {
387
+ className: "mt-1 flex min-w-0 flex-wrap items-center gap-2 font-mono text-xs",
388
+ children: [lastKnownBundleId ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HashValueDisplay, {
389
+ value: lastKnownBundleId,
390
+ buttonClassName: "min-h-11 px-3 lg:min-h-0 lg:px-1.5"
391
+ }) : "—", isBuiltinBundle(lastKnownBundleId, selectedEvent.minBundleId) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BuiltinBundleBadge, {}) : null]
392
+ })]
393
+ }),
394
+ pendingBundleId ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
395
+ className: "col-span-2 min-w-0",
396
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
397
+ className: "text-xs text-muted-foreground",
398
+ children: "Downloaded · Not launched yet"
399
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
400
+ className: "mt-1 text-xs",
401
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HashValueDisplay, { value: pendingBundleId })
402
+ })]
403
+ }) : null
404
+ ]
405
+ }),
406
+ selectedEvent.httpResponse ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
407
+ className: "mt-4",
408
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HttpResponseDetails, { event: selectedEvent })
409
+ }) : null
410
+ ]
449
411
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Separator$1, {})] }) : null, selectedInstallId !== void 0 ? isLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
450
412
  className: "flex flex-col gap-3 p-6",
451
413
  role: "status",
@@ -503,7 +465,7 @@ function InstallationHistoryCard({ error, history, isLoading, onNext, onPrevious
503
465
  formatter: dateTimeFormat
504
466
  })
505
467
  }),
506
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventTypeDetails, { type: event.type }) }),
468
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventTypeDetails, { event }) }),
507
469
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
508
470
  className: "whitespace-normal text-xs",
509
471
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -537,7 +499,7 @@ function InstallationHistoryCard({ error, history, isLoading, onNext, onPrevious
537
499
  })
538
500
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
539
501
  className: "p-6 text-sm text-muted-foreground",
540
- children: pageNumber > 1 || history?.nextCursor ? "No bundle changes on this page." : "No bundle changes recorded yet."
502
+ children: pageNumber > 1 ? "No older bundle changes." : "No bundle changes recorded yet."
541
503
  }), history && (pageNumber > 1 || history.nextCursor) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsPagination, {
542
504
  hasPrevious: pageNumber > 1,
543
505
  label: "Installation history",
@@ -551,7 +513,7 @@ function InstallationHistoryCard({ error, history, isLoading, onNext, onPrevious
551
513
  });
552
514
  }
553
515
  var getLastKnownBundleId = (event) => event.lastKnownBundleId;
554
- var getUserLabel = (event) => event.userId ?? event.username ?? "—";
516
+ var getUserLabel = (event) => event.userId ?? "—";
555
517
  function InstallationMatchesCard({ error, onNext, onPrevious, onSelect, pageNumber, results, selectedInstallId }) {
556
518
  const [expanded, setExpanded] = (0, import_react.useState)(false);
557
519
  const contentId = (0, import_react.useId)();
@@ -741,70 +703,6 @@ function InstallationResultsSkeleton() {
741
703
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, { className: "h-64 w-full lg:h-full" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, { className: "h-64 w-full lg:h-full" })]
742
704
  });
743
705
  }
744
- var readOverview = (input) => input;
745
- var readEventsPage = (input) => input;
746
- var readInstallationEventsPage = (input) => input;
747
- var readInstallationPage = (input) => input;
748
- var readInstallId = (input) => input;
749
- createServerFn({ method: "GET" }).validator(readOverview).handler(createSsrRpc("ff00311d412c8cdfa8ad5b0ba1eb6aa7471d0cc12170e6cc645deb91603d42dd"));
750
- var listInsightsEventsRpc = createServerFn({ method: "GET" }).validator(readEventsPage).handler(createSsrRpc("d4c50f40701055145f24873dc90f3c55a5494457a6a03a743339b2ac4545eb19"));
751
- var listInsightsInstallationEventsRpc = createServerFn({ method: "GET" }).validator(readInstallationEventsPage).handler(createSsrRpc("3c04bc6624be6dfdd80cf96819f9c6d0455e59a7bb4c0374b6afb0162ffd15b0"));
752
- var getInsightsInstallationRpc = createServerFn({ method: "GET" }).validator(readInstallId).handler(createSsrRpc("6726f1ed9eda1f0cb4c1f1ad1023faee435ddcfd0b7c55ef08ca7f2f7f577370"));
753
- var findInsightsInstallationsRpc = createServerFn({ method: "GET" }).validator(readInstallationPage).handler(createSsrRpc("735c501f6d5ea81a445ff2b6b2ea6a1b589e3c6f63a465a881822c80ae71e7d1"));
754
- var STALE_TIME_MS = 3e4;
755
- var queryKeys = {
756
- reportingInstallations: (input) => [
757
- "insights",
758
- "reporting-installations",
759
- input
760
- ],
761
- events: (input) => [
762
- "insights",
763
- "events",
764
- input
765
- ],
766
- installations: (input) => [
767
- "insights",
768
- "installations",
769
- input
770
- ],
771
- installation: (installId) => [
772
- "insights",
773
- "installation",
774
- installId
775
- ],
776
- installationEvents: (input) => [
777
- "insights",
778
- "installation-events",
779
- input
780
- ]
781
- };
782
- var useInsightsEventsQuery = (input, enabled) => useQuery({
783
- queryKey: queryKeys.events(input),
784
- queryFn: () => listInsightsEventsRpc({ data: input }),
785
- enabled,
786
- refetchOnWindowFocus: true,
787
- staleTime: STALE_TIME_MS
788
- });
789
- var useInsightsInstallationsQuery = (input, enabled) => useQuery({
790
- queryKey: queryKeys.installations(input),
791
- queryFn: () => findInsightsInstallationsRpc({ data: input }),
792
- enabled: enabled && input.identity.length > 0,
793
- staleTime: STALE_TIME_MS
794
- });
795
- var useInsightsInstallationQuery = (installId, enabled) => useQuery({
796
- queryKey: queryKeys.installation(installId),
797
- queryFn: () => getInsightsInstallationRpc({ data: { installId } }),
798
- enabled: enabled && installId.length > 0,
799
- staleTime: STALE_TIME_MS
800
- });
801
- var useInsightsInstallationEventsQuery = (input, enabled) => useQuery({
802
- queryKey: queryKeys.installationEvents(input),
803
- queryFn: () => listInsightsInstallationEventsRpc({ data: input }),
804
- enabled: enabled && input.installId.length > 0,
805
- refetchOnWindowFocus: true,
806
- staleTime: STALE_TIME_MS
807
- });
808
706
  var SEARCH_LIMIT = 20;
809
707
  var EVENT_LIMIT = 50;
810
708
  var freshBefore = () => Date.now();
@@ -816,25 +714,35 @@ var popCursor = (stack) => ({
816
714
  function InstallationsPage() {
817
715
  const search = Route.useSearch();
818
716
  const navigate = Route.useNavigate();
717
+ const retention = useInsightsRetention();
819
718
  const [draftQuery, setDraftQuery] = (0, import_react.useState)(search.query ?? "");
820
719
  const [initialEventsBefore] = (0, import_react.useState)(freshBefore);
821
720
  const [initialHistoryBefore] = (0, import_react.useState)(freshBefore);
822
- const [eventsBack, setEventsBack] = (0, import_react.useState)([]);
823
- const [searchBack, setSearchBack] = (0, import_react.useState)([]);
824
- const [historyBack, setHistoryBack] = (0, import_react.useState)([]);
721
+ const pagination = useLocation({ select: (location) => location.state.insightsPagination });
722
+ const eventsBack = pagination?.eventsBack ?? [];
723
+ const searchBack = pagination?.searchBack ?? [];
724
+ const historyBack = pagination?.historyBack ?? [];
825
725
  const query = search.query?.trim() ?? "";
826
726
  const hasSearchQuery = query.length > 0;
827
727
  const hasSelection = search.installId !== void 0;
828
728
  const hasLookup = hasSearchQuery || hasSelection;
829
729
  const eventsBefore = search.eventsBefore ?? initialEventsBefore;
730
+ const eventsRange = search.eventsRange ?? "7d";
830
731
  const historyBefore = search.historyBefore ?? initialHistoryBefore;
831
- const updateSearch = (next, replace = false) => {
732
+ const updateSearch = (next, replace = false, nextPagination = {}) => {
832
733
  navigate({
833
734
  to: "/installations",
834
735
  search: {
835
736
  ...search,
836
737
  ...next
837
738
  },
739
+ state: (previous) => ({
740
+ ...previous,
741
+ insightsPagination: {
742
+ ...previous.insightsPagination,
743
+ ...nextPagination
744
+ }
745
+ }),
838
746
  replace
839
747
  });
840
748
  };
@@ -852,7 +760,7 @@ function InstallationsPage() {
852
760
  search.historyBefore
853
761
  ]);
854
762
  const events = useInsightsEventsQuery({
855
- beforeReceivedAtMs: eventsBefore,
763
+ ...eventRangeBounds(eventsRange, eventsBefore),
856
764
  cursor: search.eventsCursor,
857
765
  limit: 20
858
766
  }, !hasLookup);
@@ -864,12 +772,11 @@ function InstallationsPage() {
864
772
  (0, import_react.useEffect)(() => {
865
773
  const firstInstallId = matches.data?.data[0]?.installId;
866
774
  if (!hasSearchQuery || hasSelection || firstInstallId === void 0) return;
867
- setHistoryBack([]);
868
775
  updateSearch({
869
776
  historyBefore: freshBefore(),
870
777
  historyCursor: void 0,
871
778
  installId: firstInstallId
872
- }, true);
779
+ }, true, { historyBack: [] });
873
780
  }, [
874
781
  hasSearchQuery,
875
782
  hasSelection,
@@ -887,7 +794,7 @@ function InstallationsPage() {
887
794
  const scrollRef = (0, import_react.useRef)(null);
888
795
  const scrollEntry = useElementScrollRestoration({
889
796
  id: scrollRestorationId,
890
- getKey: getInsightsScrollRestorationKey
797
+ getKey: installationsScrollRestorationKey
891
798
  });
892
799
  (0, import_react.useLayoutEffect)(() => {
893
800
  if (!hasLookup && !events.isLoading && scrollRef.current) scrollRef.current.scrollTop = scrollEntry?.scrollY ?? 0;
@@ -899,14 +806,15 @@ function InstallationsPage() {
899
806
  ]);
900
807
  const clearLookup = () => {
901
808
  setDraftQuery("");
902
- setHistoryBack([]);
903
- setSearchBack([]);
904
809
  updateSearch({
905
810
  historyBefore: void 0,
906
811
  historyCursor: void 0,
907
812
  installId: void 0,
908
813
  query: void 0,
909
814
  searchCursor: void 0
815
+ }, false, {
816
+ historyBack: [],
817
+ searchBack: []
910
818
  });
911
819
  };
912
820
  const installationLookup = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InstallationSearchPanel, {
@@ -919,14 +827,15 @@ function InstallationsPage() {
919
827
  clearLookup();
920
828
  return;
921
829
  }
922
- setHistoryBack([]);
923
- setSearchBack([]);
924
830
  updateSearch({
925
831
  historyBefore: void 0,
926
832
  historyCursor: void 0,
927
833
  installId: void 0,
928
834
  query: nextQuery,
929
835
  searchCursor: void 0
836
+ }, false, {
837
+ historyBack: [],
838
+ searchBack: []
930
839
  });
931
840
  }
932
841
  });
@@ -954,32 +863,40 @@ function InstallationsPage() {
954
863
  }), installationLookup]
955
864
  })
956
865
  }) : null, !hasLookup ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EventHistoryCard, {
866
+ description: `Downloads, launches, crashes, update failures, and other changes to what an installation runs, newest first, kept for ${formatDays(retention.rawDays)}. Launches that change nothing aren't listed.`,
957
867
  error: events.error,
958
868
  eventsLocation: {
959
869
  eventsBefore,
960
- eventsCursor: search.eventsCursor
870
+ eventsCursor: search.eventsCursor,
871
+ eventsRange: search.eventsRange
961
872
  },
962
873
  history: events.data,
963
874
  isFetching: events.isFetching,
964
875
  isLoading: events.isLoading,
965
876
  onNext: () => {
966
877
  if (!events.data?.nextCursor) return;
967
- setEventsBack(pushCursor(eventsBack, search.eventsCursor));
968
- updateSearch({ eventsCursor: events.data.nextCursor }, true);
878
+ updateSearch({ eventsCursor: events.data.nextCursor }, true, { eventsBack: pushCursor(eventsBack, search.eventsCursor) });
969
879
  },
970
880
  onPrevious: () => {
971
881
  const previous = popCursor(eventsBack);
972
- setEventsBack(previous.stack);
973
- updateSearch({ eventsCursor: previous.cursor }, true);
882
+ updateSearch({ eventsCursor: previous.cursor }, true, { eventsBack: previous.stack });
883
+ },
884
+ onRangeChange: (range) => {
885
+ updateSearch({
886
+ eventsBefore: freshBefore(),
887
+ eventsCursor: void 0,
888
+ eventsRange: range
889
+ }, false, { eventsBack: [] });
974
890
  },
975
891
  onRefresh: () => {
976
- setEventsBack([]);
977
892
  updateSearch({
978
893
  eventsBefore: freshBefore(),
979
894
  eventsCursor: void 0
980
- }, true);
895
+ }, true, { eventsBack: [] });
981
896
  },
982
897
  pageNumber: eventsBack.length + 1,
898
+ range: eventsRange,
899
+ rawDays: retention.rawDays,
983
900
  children: installationLookup
984
901
  }) : matches.isLoading && hasSearchQuery ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InstallationResultsSkeleton, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
985
902
  className: `grid min-h-0 min-w-0 items-stretch gap-4 sm:gap-6 ${hasSearchQuery ? "lg:min-h-96 lg:grid-cols-[minmax(18rem,20rem)_minmax(0,1fr)]" : "lg:grid-cols-1"}`,
@@ -987,27 +904,24 @@ function InstallationsPage() {
987
904
  error: matches.error,
988
905
  onNext: () => {
989
906
  if (!matches.data?.nextCursor) return;
990
- setSearchBack(pushCursor(searchBack, search.searchCursor));
991
907
  updateSearch({
992
908
  installId: void 0,
993
909
  searchCursor: matches.data.nextCursor
994
- }, true);
910
+ }, true, { searchBack: pushCursor(searchBack, search.searchCursor) });
995
911
  },
996
912
  onPrevious: () => {
997
913
  const previous = popCursor(searchBack);
998
- setSearchBack(previous.stack);
999
914
  updateSearch({
1000
915
  installId: void 0,
1001
916
  searchCursor: previous.cursor
1002
- }, true);
917
+ }, true, { searchBack: previous.stack });
1003
918
  },
1004
919
  onSelect: (installId) => {
1005
- setHistoryBack([]);
1006
920
  updateSearch({
1007
921
  historyBefore: freshBefore(),
1008
922
  historyCursor: void 0,
1009
923
  installId
1010
- });
924
+ }, false, { historyBack: [] });
1011
925
  },
1012
926
  pageNumber: searchBack.length + 1,
1013
927
  results: matches.data,
@@ -1018,22 +932,20 @@ function InstallationsPage() {
1018
932
  isLoading: history.isLoading || selectedInstallation.isLoading,
1019
933
  onNext: () => {
1020
934
  if (!history.data?.nextCursor) return;
1021
- setHistoryBack(pushCursor(historyBack, search.historyCursor));
1022
- updateSearch({ historyCursor: history.data.nextCursor }, true);
935
+ updateSearch({ historyCursor: history.data.nextCursor }, true, { historyBack: pushCursor(historyBack, search.historyCursor) });
1023
936
  },
1024
937
  onPrevious: () => {
1025
938
  const previous = popCursor(historyBack);
1026
- setHistoryBack(previous.stack);
1027
- updateSearch({ historyCursor: previous.cursor }, true);
939
+ updateSearch({ historyCursor: previous.cursor }, true, { historyBack: previous.stack });
1028
940
  },
1029
941
  onRefresh: () => {
1030
- setHistoryBack([]);
1031
942
  updateSearch({
1032
943
  historyBefore: freshBefore(),
1033
944
  historyCursor: void 0
1034
- }, true);
945
+ }, true, { historyBack: [] });
1035
946
  },
1036
947
  pageNumber: historyBack.length + 1,
948
+ retention,
1037
949
  selectedEvent,
1038
950
  selectedInstallId: search.installId
1039
951
  })]