@hot-updater/console 1.1.4 → 1.2.0-rc.1

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 (273) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/-native-builds-search-C-TGpFAm.js +1 -0
  3. package/.output/public/assets/{ConsoleFeatureUnavailable-C0KfsKWL.js → ConsoleFeatureUnavailable-CUtcXuY2.js} +1 -1
  4. package/.output/public/assets/EventDetails-Dl2RvPAk.js +1 -0
  5. package/.output/public/assets/HashValueDisplay-6lNRxDJX.js +1 -0
  6. package/.output/public/assets/InsightsPageHeader-DHhqY3DT.js +1 -0
  7. package/.output/public/assets/NotFoundPage-DZ3DxyRA.js +1 -0
  8. package/.output/public/assets/PlatformIcon-BBWQlWm9.js +1 -0
  9. package/.output/public/assets/RolloutPercentageBadge-Cxogpi8F.js +1 -0
  10. package/.output/public/assets/StoreSubmission-JpngSvHS.js +1 -0
  11. package/.output/public/assets/alert-dialog-BqYScr9y.js +1 -0
  12. package/.output/public/assets/api-P2g8dCNg.js +1 -0
  13. package/.output/public/assets/api-keys-DWQC2q6y.js +1 -0
  14. package/.output/public/assets/api-keys-FueRkF9q.js +1 -0
  15. package/.output/public/assets/arrow-left-g9cKqXuC.js +1 -0
  16. package/.output/public/assets/arrow-right-CNII8TYn.js +1 -0
  17. package/.output/public/assets/arrow-up-right-DK8Zdg40.js +1 -0
  18. package/.output/public/assets/badge-DWFcDWho.js +1 -0
  19. package/.output/public/assets/check-CXVR3s3X.js +1 -0
  20. package/.output/public/assets/chevron-right-BoUXo82O.js +1 -0
  21. package/.output/public/assets/circle-off-C7Muo0ss.js +1 -0
  22. package/.output/public/assets/{clipboard-DTkrlIMn.js → clipboard-DQbOcrL7.js} +1 -1
  23. package/.output/public/assets/console-features-api-DEXSwFtc.js +1 -0
  24. package/.output/public/assets/copy-DsuLj3oj.js +1 -0
  25. package/.output/public/assets/dialog-CNUPxNxH.js +1 -0
  26. package/.output/public/assets/{dist-dDj-R6uh.js → dist-CPlO6ko9.js} +1 -1
  27. package/.output/public/assets/download-Cf24LBde.js +1 -0
  28. package/.output/public/assets/{empty-Bf4DanOL.js → empty-B3Uwdd6k.js} +1 -1
  29. package/.output/public/assets/{field-GxF9SyUo.js → field-D-2-mnNh.js} +1 -1
  30. package/.output/public/assets/history-DqHlgSuV.js +1 -0
  31. package/.output/public/assets/index-BWU6owTG.js +10 -0
  32. package/.output/public/assets/{input-group-B4nrqIh0.js → input-group-D3OUBk4n.js} +1 -1
  33. package/.output/public/assets/insights-B-0odqpt.js +42 -0
  34. package/.output/public/assets/insights-BSVGfxSL.js +1 -0
  35. package/.output/public/assets/insights-NK5B6ReS.js +2 -0
  36. package/.output/public/assets/insights-api-BVCXJsoV.js +1 -0
  37. package/.output/public/assets/insights-search-DghCbEnk.js +1 -0
  38. package/.output/public/assets/insights-usage-rpc-CKQH0pUS.js +1 -0
  39. package/.output/public/assets/insights_.distribution-CJvgwcVZ.js +2 -0
  40. package/.output/public/assets/insights_.distribution-DblZM0mO.js +1 -0
  41. package/.output/public/assets/insights_.distribution-dvk6vYDM.js +1 -0
  42. package/.output/public/assets/installations-B674P5Z5.js +2 -0
  43. package/.output/public/assets/installations-BWxczZ2t.js +1 -0
  44. package/.output/public/assets/installations-Dv4kWQYz.js +1 -0
  45. package/.output/public/assets/{key-round-B4fI1psK.js → key-round-DwNKkHhy.js} +1 -1
  46. package/.output/public/assets/link-DTEyW70e.js +2 -0
  47. package/.output/public/assets/{list-Dtj7TtzV.js → list--NIee1FZ.js} +1 -1
  48. package/.output/public/assets/native-builds-BOC71grI.js +1 -0
  49. package/.output/public/assets/native-builds-BswZazmc.js +1 -0
  50. package/.output/public/assets/native-builds-c4BpOLAe.js +2 -0
  51. package/.output/public/assets/native-builds_._buildId-D_Spjl10.js +1 -0
  52. package/.output/public/assets/native-builds_._buildId-DtoXD8rz.js +2 -0
  53. package/.output/public/assets/plus-BReVKct-.js +1 -0
  54. package/.output/public/assets/preload-helper-B44EvKhG.js +1 -0
  55. package/.output/public/assets/{refresh-cw-DjIKjmrS.js → refresh-cw-B9HHjLej.js} +1 -1
  56. package/.output/public/assets/relativeTime-YQt84dYr.js +1 -0
  57. package/.output/public/assets/remote-config-B7ujqhLa.js +6 -0
  58. package/.output/public/assets/remote-config-WjpozBG5.js +1 -0
  59. package/.output/public/assets/remote-config-gXeH6PBW.js +1 -0
  60. package/.output/public/assets/rotate-cw-Cv2aVbYr.js +1 -0
  61. package/.output/public/assets/routes-BDdBIxYS.js +1 -0
  62. package/.output/public/assets/routes-CCD33Azv.js +2 -0
  63. package/.output/public/assets/search-BCel4Oy6.js +1 -0
  64. package/.output/public/assets/select-CBIU0_M1.js +1 -0
  65. package/.output/public/assets/{sidebar-BqX460IW.js → sidebar-Di9SN47G.js} +1 -1
  66. package/.output/public/assets/smartphone-CMaSy_ir.js +1 -0
  67. package/.output/public/assets/styles-Ccxthuz1.css +2 -0
  68. package/.output/public/assets/switch-BpdiHL_t.js +1 -0
  69. package/.output/public/assets/{table-ek1DmRHq.js → table-Bpy3SvSo.js} +1 -1
  70. package/.output/public/assets/{tabs-CgEH_fMT.js → tabs-Xmt7tZeG.js} +1 -1
  71. package/.output/public/assets/{undo-2-DxXx9Zvr.js → undo-2-CUX96_BG.js} +1 -1
  72. package/.output/public/assets/useCompositeListItem-JmyDfo3-.js +1 -0
  73. package/.output/public/assets/useInfiniteQuery-DX4WpBRG.js +1 -0
  74. package/.output/public/assets/useMutation-DbYw7boA.js +1 -0
  75. package/.output/public/assets/uuidv7-zXMtwR9Q.js +1 -0
  76. package/.output/public/assets/{valueToPercent-B44vDssN.js → valueToPercent-BLwGy_xK.js} +1 -1
  77. package/.output/server/{__23tanstack-start-server-fn-resolver-KpQ5Z_24.mjs → __23tanstack-start-server-fn-resolver-CygMPYHZ.mjs} +64 -40
  78. package/.output/server/_chunks/ssr-renderer.mjs +2 -2
  79. package/.output/server/_libs/@tanstack/react-router+[...].mjs +1 -1
  80. package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +1 -1
  81. package/.output/server/_libs/lucide-react.mjs +88 -1
  82. package/.output/server/_libs/uqr.mjs +858 -0
  83. package/.output/server/_ssr/-native-builds-search-CwNcoXf4.mjs +37 -0
  84. package/.output/server/_ssr/{BundleIdDisplay-CjSnY65J.mjs → BundleIdDisplay-DOPz4pUS.mjs} +2 -2
  85. package/.output/server/_ssr/{ConsoleFeatureUnavailable-CHxn9f-w.mjs → ConsoleFeatureUnavailable-Xb1JKqcc.mjs} +7 -7
  86. package/.output/server/_ssr/{EventDetails-l6dF54zp.mjs → EventDetails-D7MejFCN.mjs} +8 -8
  87. package/.output/server/_ssr/{HashValueDisplay-Zs7ABoOi.mjs → HashValueDisplay-Dd-wu5rY.mjs} +2 -2
  88. package/.output/server/_ssr/{InsightsPageHeader-ZlAlDxQy.mjs → InsightsPageHeader-CWf1n4Vt.mjs} +13 -11
  89. package/.output/server/_ssr/{NotFoundPage-u28ndvp1.mjs → NotFoundPage-C5rFdUpg.mjs} +2 -2
  90. package/.output/server/_ssr/PlatformIcon-CFLiTjh1.mjs +29 -0
  91. package/.output/server/_ssr/RolloutPercentageBadge-g0Bhfl3M.mjs +21 -0
  92. package/.output/server/_ssr/StoreSubmission-JZ2Zltak.mjs +139 -0
  93. package/.output/server/_ssr/{alert-dialog-B8AqlJwo.mjs → alert-dialog-CvNvTvIJ.mjs} +1 -1
  94. package/.output/server/_ssr/{api-C_0B7NXM.mjs → api-0vtwA5vY.mjs} +126 -7
  95. package/.output/server/_ssr/{api-keys-pRNvn2-9.mjs → api-keys-D5dyA4D1.mjs} +10 -10
  96. package/.output/server/_ssr/{api-keys-rpc-wecWs0nA.mjs → api-keys-rpc-BOIUHhDi.mjs} +5 -5
  97. package/.output/server/_ssr/{api-keys-CLH38u9B.mjs → api-keys-yFlQDwQF.mjs} +2 -2
  98. package/.output/server/_ssr/{api-rpc-DWN8eOHS.mjs → api-rpc-COeFOpYi.mjs} +79 -12
  99. package/.output/server/_ssr/{auth-UP0wXs4i.mjs → auth-Z-wLddzh.mjs} +1 -1
  100. package/.output/server/_ssr/{auth-rpc-CLRArbIl.mjs → auth-rpc-D1ss2GUI.mjs} +6 -6
  101. package/.output/server/_ssr/{auth.server-DR9zc0EU.mjs → auth.server-DYS1OJ6P.mjs} +771 -641
  102. package/.output/server/_ssr/{badge-BpT7r-ng.mjs → badge-CEdVRgyl.mjs} +1 -1
  103. package/.output/server/_ssr/{bundleActivity-0qFIcvqt.mjs → bundleActivity-MLrjNJCT.mjs} +1 -1
  104. package/.output/server/_ssr/{config-WVX4IxSR.mjs → config-CjIBFhJX.mjs} +1 -1
  105. package/.output/server/_ssr/config.server-NnMFjMFX.mjs +43 -0
  106. package/.output/server/_ssr/{console-access-aUpQs49I.mjs → console-access-33BNlH97.mjs} +3 -3
  107. package/.output/server/_ssr/{console-features-4xAGfZHw.mjs → console-features-BTV-XuhQ.mjs} +1 -1
  108. package/.output/server/_ssr/{console-features-api-DSSgCV3v.mjs → console-features-api-v1fSycue.mjs} +6 -6
  109. package/.output/server/_ssr/{console-features-rpc-D6kMlR2A.mjs → console-features-rpc-C7XNVqm0.mjs} +5 -5
  110. package/.output/server/_ssr/createCsrfMiddleware-BwHbC8n-.mjs +159 -0
  111. package/.output/server/_ssr/createMiddleware-C3ACsfuG.mjs +24 -0
  112. package/.output/server/_ssr/{createMiddleware-B1iPez7u.mjs → createServerFn-AQvBMBjJ.mjs} +2 -23
  113. package/.output/server/_ssr/{createServerRpc-BaDJLGBx.mjs → createServerRpc-BVvRVOz5.mjs} +2 -2
  114. package/.output/server/_ssr/{databaseConfig-C5SkAyUy.mjs → databaseConfig-B_Bg7qS5.mjs} +1 -1
  115. package/.output/server/_ssr/{databaseJsonValue-Csbuzc9Q.mjs → databaseJsonValue-kS7cvEtz.mjs} +1 -1
  116. package/.output/server/_ssr/{databaseRows-CPphvbag.mjs → databaseRows-B6H8Cmgq.mjs} +3 -3
  117. package/.output/server/_ssr/{dialog-B4ALf7NJ.mjs → dialog-C8CS8RMt.mjs} +1 -1
  118. package/.output/server/_ssr/{dist-CbQbBIw-.mjs → dist-TEpM_UAD.mjs} +125 -125
  119. package/.output/server/_ssr/{downloadBundle-94jPBGSO.mjs → downloadBundle-DCmr7vsj.mjs} +1 -1
  120. package/.output/server/_ssr/{empty-Bh1FEeYF.mjs → empty-CkdEAvCY.mjs} +2 -2
  121. package/.output/server/_ssr/{empty-plugin-adapters-CpCHi1TV.mjs → empty-plugin-adapters-zrZ0xs6n.mjs} +1 -1
  122. package/.output/server/_ssr/{failureReports-Bh22wois.mjs → failureReports-Cn_zU9S8.mjs} +3 -3
  123. package/.output/server/_ssr/{field-HKCaPH3e.mjs → field-CW08sZXd.mjs} +2 -2
  124. package/.output/server/_ssr/{getBundleChildren-DfxB2K8D.mjs → getBundleChildren-rtkEEJw5.mjs} +2 -2
  125. package/.output/server/_ssr/git-CTA8Aqr0.mjs +56 -0
  126. package/.output/server/_ssr/{input-group-xm3LzDuq.mjs → input-group-D-TpFPuG.mjs} +1 -1
  127. package/.output/server/_ssr/{insights-BKZpJ_K4.mjs → insights-CMyzPs8l.mjs} +28 -27
  128. package/.output/server/_ssr/{insights-CCyTACIw.mjs → insights-CYeBl8N9.mjs} +5 -5
  129. package/.output/server/_ssr/{insights-CNqWQLJR.mjs → insights-DAi9KknT.mjs} +2 -2
  130. package/.output/server/_ssr/{insights-api-DtRFz5X3.mjs → insights-api-BFARQ5ct.mjs} +6 -6
  131. package/.output/server/_ssr/{insights-errors-Iy-lBaM7.mjs → insights-errors-7BCwFybo.mjs} +2 -2
  132. package/.output/server/_ssr/{insights-failures-BJN3RfLu.mjs → insights-failures-B9VPkzZE.mjs} +2 -2
  133. package/.output/server/_ssr/{insights-failures-rpc-DLZ91uOG.mjs → insights-failures-rpc-Q4WNNJkU.mjs} +12 -12
  134. package/.output/server/_ssr/{insights-recovery-BUuQdlA3.mjs → insights-recovery-BtXVU3ro.mjs} +1 -1
  135. package/.output/server/_ssr/{insights-recovery-rpc-BQHUhPi7.mjs → insights-recovery-rpc-CY5RYJKa.mjs} +8 -8
  136. package/.output/server/_ssr/{insights-rpc-C6Vukyn7.mjs → insights-rpc-BO7_evvs.mjs} +5 -5
  137. package/.output/server/_ssr/{insights-search-CBYoxT7v.mjs → insights-search-DKfxgHD3.mjs} +5 -5
  138. package/.output/server/_ssr/{insights-usage-CHqvtehH.mjs → insights-usage-DiGnuxW8.mjs} +1 -1
  139. package/.output/server/_ssr/{insights-usage-rpc-BJ7a-xco.mjs → insights-usage-rpc-B4czku50.mjs} +8 -8
  140. package/.output/server/_ssr/{insights-usage-rpc-C-lNUIsD.mjs → insights-usage-rpc-CUCTFska.mjs} +5 -5
  141. package/.output/server/_ssr/{insightsUsage-COUG-_-U.mjs → insightsUsage-ClAmoUz8.mjs} +3 -3
  142. package/.output/server/_ssr/{insights_.distribution-DmLW8I8a.mjs → insights_.distribution-BDeUhZGj.mjs} +2 -2
  143. package/.output/server/_ssr/{insights_.distribution-CTwilMPm.mjs → insights_.distribution-BRrbZN1X.mjs} +5 -5
  144. package/.output/server/_ssr/{insights_.distribution-DztDyrBj.mjs → insights_.distribution-C2MXpzKd.mjs} +15 -14
  145. package/.output/server/_ssr/{installations-Bct7ag5y.mjs → installations-BVk7okiY.mjs} +4 -4
  146. package/.output/server/_ssr/{installations-B6MK5iA8.mjs → installations-BjLMgBoH.mjs} +2 -2
  147. package/.output/server/_ssr/{installations-_N4PtYFl.mjs → installations-DxGZEC5G.mjs} +12 -12
  148. package/.output/server/_ssr/{listReleases-BfUBlCHo.mjs → listReleases-D_GY00SQ.mjs} +1 -1
  149. package/.output/server/_ssr/native-builds-CSCgFB21.mjs +10 -0
  150. package/.output/server/_ssr/native-builds-CdlyAldW.mjs +569 -0
  151. package/.output/server/_ssr/native-builds-DhXL5zf_.mjs +137 -0
  152. package/.output/server/_ssr/native-builds_._buildId-CMp1h8dT.mjs +10 -0
  153. package/.output/server/_ssr/native-builds_._buildId-GHpGaYyE.mjs +813 -0
  154. package/.output/server/_ssr/nativeBuildQr-84cnFQPX.mjs +59 -0
  155. package/.output/server/_ssr/nativeBuilds-B_7BPjt_.mjs +133 -0
  156. package/.output/server/_ssr/{plugins-BaD1slHx.mjs → plugins-RIryUNWj.mjs} +6 -5
  157. package/.output/server/_ssr/qr-code-C7kNRIDX.mjs +22 -0
  158. package/.output/server/_ssr/{release-adoption-DuYJTGuX.mjs → release-adoption-DoAtNPED.mjs} +2 -2
  159. package/.output/server/_ssr/{release-adoption-rpc-CHl7G_Zy.mjs → release-adoption-rpc-BJXZvtoQ.mjs} +10 -10
  160. package/.output/server/_ssr/{releaseAdoption-B39cpvfo.mjs → releaseAdoption-a2byXMfz.mjs} +4 -4
  161. package/.output/server/_ssr/releaseCatalogCompiler-DLcean2k.mjs +364 -0
  162. package/.output/server/_ssr/{releaseManagement-DFMUnDF5.mjs → releaseManagement-DHUux2az.mjs} +1 -1
  163. package/.output/server/_ssr/{releaseReachability-bFsuElSS.mjs → releaseReachability-DZOK_dH-.mjs} +2 -2
  164. package/.output/server/_ssr/{remote-config-Mj05qVYZ.mjs → remote-config-DjsEl270.mjs} +20 -19
  165. package/.output/server/_ssr/{remote-config-10-obSZ0.mjs → remote-config-DlyyohL2.mjs} +2 -2
  166. package/.output/server/_ssr/{remote-config-Dj1eTYi4.mjs → remote-config-XdYuByHz.mjs} +2 -2
  167. package/.output/server/_ssr/{remote-config-rpc-lteqDSLn.mjs → remote-config-rpc-GMLPb-90.mjs} +6 -6
  168. package/.output/server/_ssr/request-guard-CPdRBuGW.mjs +108 -0
  169. package/.output/server/_ssr/{router-Dr4jjjhx.mjs → router-vpxd56RW.mjs} +317 -71
  170. package/.output/server/_ssr/{routes-BZbrY_qw.mjs → routes-DyEM4b3x.mjs} +14 -14
  171. package/.output/server/_ssr/{routes-B5KrCDwk.mjs → routes-dQe3XhiS.mjs} +99 -81
  172. package/.output/server/_ssr/{runtime.server-DsHqVqTr.mjs → runtime.server-BdMY1blX.mjs} +4 -4
  173. package/.output/server/_ssr/schema-ChlRtZIo.mjs +23 -0
  174. package/.output/server/_ssr/schema-migration-rpc-BfGzEK_o.mjs +65 -0
  175. package/.output/server/_ssr/{select-BtdGNSmp.mjs → select-DM1uwtk9.mjs} +3 -27
  176. package/.output/server/_ssr/{server-BxaHSwHh.mjs → server-BUUKNSPI.mjs} +7 -161
  177. package/.output/server/_ssr/{sidebar-CVsgosaD.mjs → sidebar-DB2YQlok.mjs} +4 -4
  178. package/.output/server/_ssr/ssr.mjs +1 -1
  179. package/.output/server/_ssr/start-BvDsQehg.mjs +49 -0
  180. package/.output/server/_ssr/{switch-BmARgkUP.mjs → switch-DLD58zLy.mjs} +2 -2
  181. package/.output/server/_ssr/{table-M5P3YUfY.mjs → table-P4TnAZhl.mjs} +1 -1
  182. package/.output/server/_ssr/{tabs-CrmfOlJj.mjs → tabs-B7ZeLicF.mjs} +2 -2
  183. package/.output/server/_ssr/{updateFailures-z1IQy_4q.mjs → updateFailures-n-tGv90S.mjs} +3 -3
  184. package/.output/server/_ssr/{uuidv7-C88s9jWF.mjs → uuidv7-BIF4nb_q.mjs} +2 -2
  185. package/.output/server/_ssr/{schema-BiAVyEj2.mjs → version-CQ98ZBpL-CWSkTT9J.mjs} +2 -22
  186. package/.output/server/_tanstack-start-manifest_v-C-KC63Zq.mjs +184 -0
  187. package/.output/server/index.mjs +432 -271
  188. package/lib/vite-internal.mjs +32 -1
  189. package/package.json +8 -7
  190. package/src/components/AppSidebar.tsx +12 -1
  191. package/src/components/ConsoleAccessPage.tsx +49 -3
  192. package/src/components/QrCode.tsx +35 -0
  193. package/src/components/SchemaMigrationRequired.tsx +139 -0
  194. package/src/components/features/insights/BuiltinBundle.tsx +5 -3
  195. package/src/components/features/native-builds/BuiltInBundleCard.tsx +163 -0
  196. package/src/components/features/native-builds/CommitLink.tsx +30 -0
  197. package/src/components/features/native-builds/CopyableText.tsx +48 -0
  198. package/src/components/features/native-builds/ImportBuild.tsx +91 -0
  199. package/src/components/features/native-builds/InstallCard.tsx +205 -0
  200. package/src/components/features/native-builds/NativeBuildDetailPage.tsx +175 -0
  201. package/src/components/features/native-builds/NativeBuildsPage.tsx +151 -0
  202. package/src/components/features/native-builds/NativeBuildsTable.tsx +426 -0
  203. package/src/components/features/native-builds/PatchesCard.tsx +222 -0
  204. package/src/components/features/native-builds/ReleaseNativeBuildLink.tsx +101 -0
  205. package/src/components/features/native-builds/ServedNowCard.tsx +214 -0
  206. package/src/components/features/native-builds/ShortHash.tsx +41 -0
  207. package/src/components/features/native-builds/StoreSubmission.tsx +73 -0
  208. package/src/components/features/releases/ReleaseEditorSheet.tsx +8 -0
  209. package/src/lib/api-rpc.ts +98 -0
  210. package/src/lib/api.ts +120 -0
  211. package/src/lib/native-builds.ts +162 -0
  212. package/src/lib/qr-code.ts +16 -0
  213. package/src/lib/schema-migration-api.ts +54 -0
  214. package/src/lib/schema-migration-rpc.ts +26 -0
  215. package/src/lib/schema-migration.ts +101 -0
  216. package/src/lib/server/config.server.ts +23 -14
  217. package/src/lib/server/console-runtime.server.ts +4 -6
  218. package/src/lib/server/local-console.ts +164 -0
  219. package/src/lib/server/nativeBuildQr.ts +73 -0
  220. package/src/lib/server/nativeBuilds.ts +288 -0
  221. package/src/lib/shell.ts +9 -0
  222. package/src/routeTree.gen.ts +88 -1
  223. package/src/router.tsx +11 -1
  224. package/src/routes/-native-builds-search.ts +51 -0
  225. package/src/routes/[_]hot-updater/native-builds/qr.ts +14 -0
  226. package/src/routes/__root.tsx +11 -1
  227. package/src/routes/api/native-builds/$buildId/download.ts +50 -0
  228. package/src/routes/native-builds.tsx +21 -0
  229. package/src/routes/native-builds_.$buildId.tsx +23 -0
  230. package/src/start.ts +33 -0
  231. package/src/virtual-modules.d.ts +18 -0
  232. package/src/vite-internal.ts +57 -1
  233. package/.output/public/assets/EventDetails-gbD_fCqc.js +0 -1
  234. package/.output/public/assets/HashValueDisplay-BGkDPaYi.js +0 -1
  235. package/.output/public/assets/InsightsPageHeader-BRw8XkJW.js +0 -1
  236. package/.output/public/assets/NotFoundPage-Cei6W2lm.js +0 -1
  237. package/.output/public/assets/alert-dialog-BtVg50WQ.js +0 -1
  238. package/.output/public/assets/api-DoicFJfd.js +0 -1
  239. package/.output/public/assets/api-keys-D81VHHNM.js +0 -1
  240. package/.output/public/assets/api-keys-Dia6i8K1.js +0 -1
  241. package/.output/public/assets/arrow-left-DsivSewE.js +0 -1
  242. package/.output/public/assets/arrow-up-right-B5aM0F7f.js +0 -1
  243. package/.output/public/assets/badge-Bqf3UDee.js +0 -1
  244. package/.output/public/assets/circle-off-BsbZQtsF.js +0 -1
  245. package/.output/public/assets/console-features-api-DPE4C06Y.js +0 -2
  246. package/.output/public/assets/dialog-CGKPxz3n.js +0 -1
  247. package/.output/public/assets/index-DrkdiRIn.js +0 -10
  248. package/.output/public/assets/insights-C-5t8wh2.js +0 -2
  249. package/.output/public/assets/insights-D_ngQdiz.js +0 -1
  250. package/.output/public/assets/insights-KigRBDgC.js +0 -42
  251. package/.output/public/assets/insights-api-1ZjVu3Sb.js +0 -1
  252. package/.output/public/assets/insights-search-aT8BVCci.js +0 -1
  253. package/.output/public/assets/insights-usage-rpc-DqTiXI1_.js +0 -1
  254. package/.output/public/assets/insights_.distribution-Bzl6RFBR.js +0 -2
  255. package/.output/public/assets/insights_.distribution-Cthgttqb.js +0 -1
  256. package/.output/public/assets/insights_.distribution-D2c2v1bu.js +0 -1
  257. package/.output/public/assets/installations-2Nx8Htf-.js +0 -1
  258. package/.output/public/assets/installations-BskJ1xQr.js +0 -2
  259. package/.output/public/assets/installations-K2iJ_r0h.js +0 -1
  260. package/.output/public/assets/remote-config-D9X3NiwV.js +0 -6
  261. package/.output/public/assets/remote-config-DzOOiBIO.js +0 -1
  262. package/.output/public/assets/remote-config-ikg7kak0.js +0 -1
  263. package/.output/public/assets/routes-9rb9P5Y7.js +0 -2
  264. package/.output/public/assets/routes-P7683vKQ.js +0 -1
  265. package/.output/public/assets/search-DuI1FBpg.js +0 -1
  266. package/.output/public/assets/select-M3H2gxCc.js +0 -1
  267. package/.output/public/assets/smartphone-CtsHuiIC.js +0 -1
  268. package/.output/public/assets/styles-CpiW_YdW.css +0 -2
  269. package/.output/public/assets/switch-By_vfm8I.js +0 -1
  270. package/.output/public/assets/useCompositeListItem-B-UkrDlu.js +0 -1
  271. package/.output/server/_ssr/config.server-DTdsG47T.mjs +0 -35
  272. package/.output/server/_ssr/start-B6ECIE_7.mjs +0 -4
  273. package/.output/server/_tanstack-start-manifest_v-_BY9hYTm.mjs +0 -136
@@ -0,0 +1,426 @@
1
+ import type { NativeBuildRow } from "@hot-updater/plugin-core";
2
+ import { Link, useNavigate } from "@tanstack/react-router";
3
+ import {
4
+ AlertTriangle,
5
+ ArrowUpRight,
6
+ ChevronLeft,
7
+ ChevronRight,
8
+ Download,
9
+ HardDriveDownload,
10
+ RefreshCw,
11
+ } from "lucide-react";
12
+
13
+ import { PlatformIcon } from "@/components/PlatformIcon";
14
+ import { TimestampDisplay } from "@/components/TimestampDisplay";
15
+ import {
16
+ Alert,
17
+ AlertAction,
18
+ AlertDescription,
19
+ AlertTitle,
20
+ } from "@/components/ui/alert";
21
+ import { Badge } from "@/components/ui/badge";
22
+ import { Button, buttonVariants } from "@/components/ui/button";
23
+ import { Skeleton } from "@/components/ui/skeleton";
24
+ import {
25
+ Table,
26
+ TableBody,
27
+ TableCell,
28
+ TableHead,
29
+ TableHeader,
30
+ TableRow,
31
+ } from "@/components/ui/table";
32
+ import {
33
+ formatByteSize,
34
+ nativeBuildArtifacts,
35
+ nativeBuildChannel,
36
+ nativeBuildDownloadPath,
37
+ nativeBuildFileName,
38
+ nativeBuildTarget,
39
+ platformLabel,
40
+ } from "@/lib/native-builds";
41
+ import type { NativeBuildListResult } from "@/lib/server/nativeBuilds";
42
+
43
+ import { CommitLink } from "./CommitLink";
44
+ import { CopyableText } from "./CopyableText";
45
+ import { IMPORT_COMMAND, IMPORT_GUIDE_URL } from "./ImportBuild";
46
+ import { ShortHash } from "./ShortHash";
47
+ import { StoreSubmissionBadge } from "./StoreSubmission";
48
+
49
+ export const NATIVE_BUILD_GUIDE_URL =
50
+ "https://hot-updater.dev/docs/guides/native-build#register-a-build";
51
+
52
+ const COLUMNS = 6;
53
+
54
+ function EmptyRow({
55
+ channel,
56
+ paged,
57
+ onClearChannel,
58
+ onNewest,
59
+ }: {
60
+ readonly channel: string | undefined;
61
+ readonly paged: boolean;
62
+ readonly onClearChannel: () => void;
63
+ readonly onNewest: () => void;
64
+ }) {
65
+ return (
66
+ <TableRow>
67
+ <TableCell
68
+ className="h-44 text-center text-muted-foreground"
69
+ colSpan={COLUMNS}
70
+ >
71
+ <div className="mx-auto flex max-w-sm flex-col items-center gap-2 whitespace-normal">
72
+ <HardDriveDownload aria-hidden="true" className="size-5" />
73
+ {paged ? (
74
+ <>
75
+ <p className="font-medium text-foreground">
76
+ No more native builds
77
+ </p>
78
+ <Button
79
+ className="mt-1 min-h-11 sm:min-h-8"
80
+ onClick={onNewest}
81
+ variant="outline"
82
+ >
83
+ Show the newest builds
84
+ </Button>
85
+ </>
86
+ ) : channel !== undefined ? (
87
+ <>
88
+ <p className="font-medium text-foreground">
89
+ No native build embeds <span translate="no">{channel}</span>
90
+ </p>
91
+ <p>
92
+ A build embeds the channel it was built on. Build one on this
93
+ channel, or list every channel's builds.
94
+ </p>
95
+ <Button
96
+ className="mt-1 min-h-11 sm:min-h-8"
97
+ onClick={onClearChannel}
98
+ variant="outline"
99
+ >
100
+ Show all channels
101
+ </Button>
102
+ </>
103
+ ) : (
104
+ <>
105
+ <p className="font-medium text-foreground">No native builds</p>
106
+ <p>
107
+ Build a release app with{" "}
108
+ <code className="font-mono text-xs">
109
+ hot-updater native-build android
110
+ </code>{" "}
111
+ or <code className="font-mono text-xs">native-build ios</code>,
112
+ which tracks it here, or import one built elsewhere:
113
+ </p>
114
+ <div className="w-full text-left">
115
+ <CopyableText
116
+ label="the import command"
117
+ value={IMPORT_COMMAND}
118
+ wrap
119
+ />
120
+ </div>
121
+ <a
122
+ className={buttonVariants({
123
+ className: "mt-1 min-h-11 sm:min-h-8",
124
+ variant: "outline",
125
+ })}
126
+ href={NATIVE_BUILD_GUIDE_URL}
127
+ rel="noreferrer"
128
+ target="_blank"
129
+ >
130
+ Native build guide
131
+ <ArrowUpRight data-icon="inline-end" />
132
+ </a>
133
+ <a
134
+ className={buttonVariants({
135
+ className: "min-h-11 sm:min-h-8",
136
+ variant: "outline",
137
+ })}
138
+ href={IMPORT_GUIDE_URL}
139
+ rel="noreferrer"
140
+ target="_blank"
141
+ >
142
+ Import guide
143
+ <ArrowUpRight data-icon="inline-end" />
144
+ </a>
145
+ </>
146
+ )}
147
+ </div>
148
+ </TableCell>
149
+ </TableRow>
150
+ );
151
+ }
152
+
153
+ function LoadingRows() {
154
+ return Array.from({ length: 3 }, (_, index) => (
155
+ <TableRow key={index}>
156
+ <TableCell className="space-y-2 py-3">
157
+ {index === 0 ? (
158
+ <span className="sr-only">Loading native builds</span>
159
+ ) : null}
160
+ <Skeleton className="h-3.5 w-40" />
161
+ <Skeleton className="h-3 w-24" />
162
+ </TableCell>
163
+ <TableCell className="hidden md:table-cell">
164
+ <Skeleton className="h-5 w-20" />
165
+ </TableCell>
166
+ <TableCell className="hidden xl:table-cell">
167
+ <Skeleton className="h-3.5 w-28" />
168
+ </TableCell>
169
+ <TableCell className="hidden xl:table-cell">
170
+ <Skeleton className="h-3.5 w-14" />
171
+ </TableCell>
172
+ <TableCell className="hidden sm:table-cell">
173
+ <Skeleton className="h-3.5 w-20" />
174
+ </TableCell>
175
+ <TableCell>
176
+ <Skeleton className="ml-auto h-6 w-16" />
177
+ </TableCell>
178
+ </TableRow>
179
+ ));
180
+ }
181
+
182
+ function BuildRow({
183
+ build,
184
+ onChannel,
185
+ }: {
186
+ readonly build: NativeBuildRow;
187
+ readonly onChannel: (channel: string) => void;
188
+ }) {
189
+ const navigate = useNavigate();
190
+ const target = nativeBuildTarget(build);
191
+ const channel = nativeBuildChannel(build);
192
+ const title = `${platformLabel(build.platform)} ${nativeBuildArtifacts[build.artifact_kind].label}`;
193
+ return (
194
+ <TableRow
195
+ className="cursor-pointer"
196
+ onClick={() =>
197
+ void navigate({
198
+ to: "/native-builds/$buildId",
199
+ params: { buildId: build.id },
200
+ })
201
+ }
202
+ >
203
+ <TableCell className="py-3 whitespace-normal">
204
+ <div className="flex min-w-0 flex-col gap-1">
205
+ <div className="flex flex-wrap items-center gap-1.5">
206
+ <PlatformIcon
207
+ className="size-3.5 shrink-0 text-muted-foreground"
208
+ platform={build.platform}
209
+ />
210
+ <Link
211
+ className="font-medium underline-offset-4 hover:underline"
212
+ onClick={(event) => event.stopPropagation()}
213
+ params={{ buildId: build.id }}
214
+ to="/native-builds/$buildId"
215
+ >
216
+ {title}
217
+ </Link>
218
+ <span className="text-xs text-muted-foreground tabular-nums">
219
+ {formatByteSize(build.byte_size)}
220
+ </span>
221
+ <StoreSubmissionBadge build={build} withTime />
222
+ </div>
223
+ <div className="flex min-w-0 flex-wrap items-center gap-x-1.5 text-xs text-muted-foreground">
224
+ <span>{target.label}</span>
225
+ {build.fingerprint_hash === null ? (
226
+ <span className="font-mono text-foreground" translate="no">
227
+ {target.value}
228
+ </span>
229
+ ) : (
230
+ <ShortHash
231
+ label="fingerprint"
232
+ length={12}
233
+ value={build.fingerprint_hash}
234
+ />
235
+ )}
236
+ {!build.build_number ? null : (
237
+ <span className="tabular-nums" translate="no">
238
+ · build {build.build_number}
239
+ </span>
240
+ )}
241
+ <span className="md:hidden" translate="no">
242
+ · {channel}
243
+ </span>
244
+ {build.git_commit_hash === null ? null : (
245
+ <span className="inline-flex items-center gap-1 xl:hidden">
246
+ · commit <CommitLink hash={build.git_commit_hash} />
247
+ </span>
248
+ )}
249
+ </div>
250
+ {/* Below xl the column hides, so the whole ID shows here. */}
251
+ <div className="text-xs text-muted-foreground xl:hidden">
252
+ Built-in bundle{" "}
253
+ <span
254
+ className="font-mono [overflow-wrap:anywhere] text-foreground"
255
+ translate="no"
256
+ >
257
+ {build.min_bundle_id}
258
+ </span>
259
+ </div>
260
+ </div>
261
+ </TableCell>
262
+ <TableCell className="hidden md:table-cell">
263
+ <button
264
+ aria-label={`Show the builds that embed ${channel}`}
265
+ className="rounded-md text-left focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none"
266
+ onClick={(event) => {
267
+ event.stopPropagation();
268
+ onChannel(channel);
269
+ }}
270
+ type="button"
271
+ >
272
+ <Badge className="whitespace-nowrap" translate="no" variant="outline">
273
+ {channel}
274
+ </Badge>
275
+ </button>
276
+ </TableCell>
277
+ <TableCell className="hidden xl:table-cell">
278
+ <span
279
+ className="font-mono text-xs text-muted-foreground"
280
+ translate="no"
281
+ >
282
+ {build.min_bundle_id}
283
+ </span>
284
+ </TableCell>
285
+ <TableCell className="hidden xl:table-cell">
286
+ <CommitLink hash={build.git_commit_hash} />
287
+ </TableCell>
288
+ <TableCell className="hidden sm:table-cell">
289
+ <TimestampDisplay uuid={build.id} />
290
+ </TableCell>
291
+ <TableCell className="text-right">
292
+ <a
293
+ aria-label={`Download ${nativeBuildFileName(build)}`}
294
+ className={buttonVariants({
295
+ className: "min-h-11 sm:min-h-7",
296
+ size: "sm",
297
+ variant: "outline",
298
+ })}
299
+ download
300
+ href={nativeBuildDownloadPath(build.id)}
301
+ onClick={(event) => event.stopPropagation()}
302
+ >
303
+ <Download data-icon="inline-start" />
304
+ Download
305
+ </a>
306
+ </TableCell>
307
+ </TableRow>
308
+ );
309
+ }
310
+
311
+ /**
312
+ * The registered native builds, newest first, one page at a time. A row
313
+ * opens the build's page; its channel filters the list by that channel.
314
+ */
315
+ export function NativeBuildsTable({
316
+ builds,
317
+ channel,
318
+ paged,
319
+ onChannel,
320
+ onPage,
321
+ }: {
322
+ readonly builds: {
323
+ readonly data: NativeBuildListResult | undefined;
324
+ readonly isError: boolean;
325
+ readonly isLoading: boolean;
326
+ readonly isPlaceholderData: boolean;
327
+ readonly refetch: () => unknown;
328
+ };
329
+ /** The channel the list is filtered by. */
330
+ readonly channel: string | undefined;
331
+ /** Whether the list shows a page other than the newest. */
332
+ readonly paged: boolean;
333
+ readonly onChannel: (channel: string | undefined) => void;
334
+ readonly onPage: (page: { before?: string; after?: string }) => void;
335
+ }) {
336
+ const rows = builds.data?.data;
337
+ const { next, previous } = builds.data ?? {};
338
+
339
+ if (builds.isError) {
340
+ return (
341
+ <div className="p-4">
342
+ <Alert variant="destructive">
343
+ <AlertTriangle />
344
+ <AlertTitle>Native builds couldn't be loaded</AlertTitle>
345
+ <AlertDescription>
346
+ Check your connection and try again.
347
+ </AlertDescription>
348
+ <AlertAction>
349
+ <Button
350
+ onClick={() => void builds.refetch()}
351
+ size="xs"
352
+ variant="outline"
353
+ >
354
+ <RefreshCw data-icon="inline-start" />
355
+ Retry
356
+ </Button>
357
+ </AlertAction>
358
+ </Alert>
359
+ </div>
360
+ );
361
+ }
362
+
363
+ return (
364
+ <>
365
+ <Table aria-busy={builds.isPlaceholderData} aria-label="Native builds">
366
+ <TableHeader>
367
+ <TableRow>
368
+ <TableHead>Build</TableHead>
369
+ <TableHead className="hidden md:table-cell">Channel</TableHead>
370
+ <TableHead className="hidden xl:table-cell">
371
+ Built-in bundle
372
+ </TableHead>
373
+ <TableHead className="hidden xl:table-cell">Commit</TableHead>
374
+ <TableHead className="hidden sm:table-cell">Created</TableHead>
375
+ <TableHead className="text-right">
376
+ <span className="sr-only">Actions</span>
377
+ </TableHead>
378
+ </TableRow>
379
+ </TableHeader>
380
+ <TableBody>
381
+ {builds.isLoading ? (
382
+ <LoadingRows />
383
+ ) : rows?.length === 0 ? (
384
+ <EmptyRow
385
+ channel={channel}
386
+ onClearChannel={() => onChannel(undefined)}
387
+ onNewest={() => onPage({})}
388
+ paged={paged}
389
+ />
390
+ ) : (
391
+ rows?.map((build) => (
392
+ <BuildRow build={build} key={build.id} onChannel={onChannel} />
393
+ ))
394
+ )}
395
+ </TableBody>
396
+ </Table>
397
+ {next !== undefined || previous !== undefined ? (
398
+ <nav
399
+ aria-label="Native build pages"
400
+ className="flex items-center justify-end gap-2 border-t px-4 py-2"
401
+ >
402
+ <Button
403
+ className="min-h-11 sm:min-h-7"
404
+ disabled={previous === undefined || builds.isPlaceholderData}
405
+ onClick={() => onPage({ after: previous })}
406
+ size="sm"
407
+ variant="ghost"
408
+ >
409
+ <ChevronLeft data-icon="inline-start" />
410
+ Newer
411
+ </Button>
412
+ <Button
413
+ className="min-h-11 sm:min-h-7"
414
+ disabled={next === undefined || builds.isPlaceholderData}
415
+ onClick={() => onPage({ before: next })}
416
+ size="sm"
417
+ variant="ghost"
418
+ >
419
+ Older
420
+ <ChevronRight data-icon="inline-end" />
421
+ </Button>
422
+ </nav>
423
+ ) : null}
424
+ </>
425
+ );
426
+ }
@@ -0,0 +1,222 @@
1
+ import { Link } from "@tanstack/react-router";
2
+ import {
3
+ AlertTriangle,
4
+ ArrowUpRight,
5
+ ChevronLeft,
6
+ ChevronRight,
7
+ GitBranch,
8
+ RefreshCw,
9
+ } from "lucide-react";
10
+
11
+ import { TimestampDisplay } from "@/components/TimestampDisplay";
12
+ import {
13
+ Alert,
14
+ AlertAction,
15
+ AlertDescription,
16
+ AlertTitle,
17
+ } from "@/components/ui/alert";
18
+ import { Button, buttonVariants } from "@/components/ui/button";
19
+ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
20
+ import {
21
+ Empty,
22
+ EmptyContent,
23
+ EmptyDescription,
24
+ EmptyHeader,
25
+ EmptyMedia,
26
+ EmptyTitle,
27
+ } from "@/components/ui/empty";
28
+ import { Skeleton } from "@/components/ui/skeleton";
29
+ import {
30
+ Table,
31
+ TableBody,
32
+ TableCell,
33
+ TableHead,
34
+ TableHeader,
35
+ TableRow,
36
+ } from "@/components/ui/table";
37
+ import { type KeysetPage, useNativeBuildPatchesQuery } from "@/lib/api";
38
+ import { formatByteSize } from "@/lib/native-builds";
39
+ import type {
40
+ NativeBuildDetail,
41
+ NativeBuildPatchPage,
42
+ } from "@/lib/server/nativeBuilds";
43
+
44
+ const BUNDLE_DIFFING_GUIDE_URL =
45
+ "https://hot-updater.dev/docs/guides/bundle-diffing#first-ota-update";
46
+
47
+ /**
48
+ * The bundles that patch from the build's built-in bundle, newest first, a
49
+ * page at a time: the newest page comes with the build's page, and others
50
+ * are read as they are asked for.
51
+ */
52
+ export function PatchesCard({
53
+ detail,
54
+ page,
55
+ onPage,
56
+ }: {
57
+ readonly detail: NativeBuildDetail;
58
+ readonly page: KeysetPage;
59
+ readonly onPage: (page: KeysetPage) => void;
60
+ }) {
61
+ const paged = page.before !== undefined || page.after !== undefined;
62
+ const query = useNativeBuildPatchesQuery(
63
+ detail.build.min_bundle_id,
64
+ page,
65
+ paged,
66
+ );
67
+ const patches: NativeBuildPatchPage | undefined = paged
68
+ ? query.data
69
+ : detail.patches;
70
+ const { next, previous } = patches ?? {};
71
+
72
+ return (
73
+ <Card className="overflow-hidden shadow-sm" id="patches">
74
+ <CardHeader className="border-b px-4 py-3">
75
+ <CardTitle className="text-sm">
76
+ <h2>Patches from this build</h2>
77
+ </CardTitle>
78
+ </CardHeader>
79
+ <CardContent className="p-0">
80
+ {paged && query.isError ? (
81
+ <div className="p-4">
82
+ <Alert variant="destructive">
83
+ <AlertTriangle />
84
+ <AlertTitle>Patches couldn't be loaded</AlertTitle>
85
+ <AlertDescription>{query.error.message}</AlertDescription>
86
+ <AlertAction>
87
+ <Button
88
+ onClick={() => void query.refetch()}
89
+ size="xs"
90
+ variant="outline"
91
+ >
92
+ <RefreshCw data-icon="inline-start" />
93
+ Retry
94
+ </Button>
95
+ </AlertAction>
96
+ </Alert>
97
+ </div>
98
+ ) : patches === undefined ? (
99
+ <div className="flex flex-col gap-2 p-4">
100
+ <span className="sr-only">Loading patches</span>
101
+ <Skeleton className="h-4 w-full" />
102
+ <Skeleton className="h-4 w-2/3" />
103
+ </div>
104
+ ) : patches.data.length === 0 ? (
105
+ paged ? (
106
+ <Empty className="py-10">
107
+ <EmptyHeader>
108
+ <EmptyTitle>No more patches</EmptyTitle>
109
+ </EmptyHeader>
110
+ <Button
111
+ className="min-h-11 sm:min-h-8"
112
+ onClick={() => onPage({})}
113
+ variant="outline"
114
+ >
115
+ Show the newest patches
116
+ </Button>
117
+ </Empty>
118
+ ) : (
119
+ <Empty className="py-10">
120
+ <EmptyHeader>
121
+ <EmptyMedia variant="icon">
122
+ <GitBranch />
123
+ </EmptyMedia>
124
+ <EmptyTitle>No patches from this build</EmptyTitle>
125
+ <EmptyDescription>
126
+ A deploy adds a patch from this build's bundle while it is its
127
+ scope's newest build and the deploy config turns patches on,
128
+ with <code className="font-mono">patch</code> in{" "}
129
+ <code className="font-mono">hot-updater.config.ts</code>.
130
+ </EmptyDescription>
131
+ </EmptyHeader>
132
+ <EmptyContent>
133
+ <a
134
+ className={buttonVariants({
135
+ className: "min-h-11 sm:min-h-8",
136
+ variant: "outline",
137
+ })}
138
+ href={BUNDLE_DIFFING_GUIDE_URL}
139
+ rel="noreferrer"
140
+ target="_blank"
141
+ >
142
+ Bundle diffing guide
143
+ <ArrowUpRight data-icon="inline-end" />
144
+ </a>
145
+ </EmptyContent>
146
+ </Empty>
147
+ )
148
+ ) : (
149
+ <Table
150
+ aria-busy={paged && query.isPlaceholderData}
151
+ aria-label="Patches from this build"
152
+ className="table-fixed"
153
+ >
154
+ <TableHeader>
155
+ <TableRow>
156
+ <TableHead>Target bundle</TableHead>
157
+ <TableHead className="w-28">Patch size</TableHead>
158
+ <TableHead className="hidden w-32 sm:table-cell">
159
+ Created
160
+ </TableHead>
161
+ </TableRow>
162
+ </TableHeader>
163
+ <TableBody>
164
+ {patches.data.map((patch) => (
165
+ <TableRow key={patch.bundleId}>
166
+ <TableCell className="py-3 whitespace-normal">
167
+ <Link
168
+ className="block font-mono text-xs [overflow-wrap:anywhere] underline-offset-4 hover:underline"
169
+ search={{ bundleId: patch.bundleId }}
170
+ title={patch.bundleId}
171
+ to="/"
172
+ translate="no"
173
+ >
174
+ {patch.bundleId}
175
+ </Link>
176
+ </TableCell>
177
+ <TableCell className="text-xs tabular-nums">
178
+ {formatByteSize(patch.byteSize)}
179
+ </TableCell>
180
+ <TableCell className="hidden sm:table-cell">
181
+ <TimestampDisplay uuid={patch.bundleId} />
182
+ </TableCell>
183
+ </TableRow>
184
+ ))}
185
+ </TableBody>
186
+ </Table>
187
+ )}
188
+ {next !== undefined || previous !== undefined ? (
189
+ <nav
190
+ aria-label="Patch pages"
191
+ className="flex items-center justify-end gap-2 border-t px-4 py-2"
192
+ >
193
+ <Button
194
+ className="min-h-11 sm:min-h-7"
195
+ disabled={
196
+ previous === undefined || (paged && query.isPlaceholderData)
197
+ }
198
+ onClick={() => onPage({ after: previous })}
199
+ size="sm"
200
+ variant="ghost"
201
+ >
202
+ <ChevronLeft data-icon="inline-start" />
203
+ Newer
204
+ </Button>
205
+ <Button
206
+ className="min-h-11 sm:min-h-7"
207
+ disabled={
208
+ next === undefined || (paged && query.isPlaceholderData)
209
+ }
210
+ onClick={() => onPage({ before: next })}
211
+ size="sm"
212
+ variant="ghost"
213
+ >
214
+ Older
215
+ <ChevronRight data-icon="inline-end" />
216
+ </Button>
217
+ </nav>
218
+ ) : null}
219
+ </CardContent>
220
+ </Card>
221
+ );
222
+ }