@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,36 +1,29 @@
1
1
  import { i as __toESM } from "../_runtime.mjs";
2
- import { $ as DialogBackdrop, G as DialogRoot, J as DialogTitle, Q as DialogClose, X as DialogPopup, Y as DialogPortal, Z as DialogDescription, a as SliderTrack, ht as require_react, i as SliderThumb, mt as require_jsx_runtime, n as SwitchRoot, o as SliderControl, r as SliderIndicator, s as SliderRoot, t as SwitchThumb } from "../_libs/@base-ui/react+[...].mjs";
3
- import { D as Download, E as ExternalLink, F as Check, M as ChevronRight, N as ChevronLeft, P as ChevronDown, R as ArrowRight, T as FingerprintPattern, a as Tag, b as LoaderCircle, d as RotateCcw, h as Package, i as Tags, k as CircleOff, n as TriangleAlert, p as Plus, r as Trash2, t as X, v as Minus, w as Funnel, x as List } from "../_libs/lucide-react.mjs";
4
- import { C as cn, S as buttonVariants, T as useIsMobile, _ as Skeleton, g as SidebarTrigger, n as Input, r as Separator$1, t as Button$1 } from "./createSsrRpc-CdlfejmI.mjs";
5
- import { m as Link } from "../_libs/@tanstack/react-router+[...].mjs";
6
- import { n as useQuery } from "../_libs/tanstack__react-query.mjs";
7
- import { a as Badge, c as CardDescription, d as CardTitle, i as AlertTitle, o as Card, r as AlertDescription, s as CardContent, t as Alert, u as CardHeader } from "./card-Bemj0dpY.mjs";
8
- import { _ as DialogTrigger, a as AlertDialogDescription, d as Dialog$1, f as DialogContent, g as DialogTitle$1, h as DialogHeader, i as AlertDialogContent, l as AlertDialogTitle, m as DialogFooter, n as AlertDialogAction, o as AlertDialogFooter, p as DialogDescription$1, r as AlertDialogCancel, s as AlertDialogHeader, t as AlertDialog$1 } from "./dialog-CKvQ4VIE.mjs";
9
- import { a as FieldLabel, i as FieldGroup, n as FieldDescription, o as Label, r as FieldError, 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";
2
+ import { _t as require_react, a as SliderIndicator, c as SliderControl, gt as require_jsx_runtime, l as SliderRoot, o as SliderThumb, s as SliderTrack } from "../_libs/@base-ui/react+[...].mjs";
3
+ import { C as Minus, E as List, F as Download, G as Check, H as ChevronRight, M as FingerprintPattern, P as ExternalLink, R as CircleOff, T as LoaderCircle, U as ChevronLeft, W as ChevronDown, Z as ArrowRight, _ as Plus, a as Trash2, b as Package, h as RotateCcw, i as TriangleAlert, j as Funnel, o as Tags, s as Tag, t as X } from "../_libs/lucide-react.mjs";
4
+ import { C as Skeleton, O as buttonVariants, S as SidebarTrigger, a as SheetContent, c as SheetTitle, i as Sheet, j as useIsMobile, k as cn, n as Input, o as SheetDescription, r as Separator$1, s as SheetHeader, t as Button$1 } from "./sidebar-DJcErBMo.mjs";
5
+ import { a as Badge, c as CardDescription, d as CardTitle, f as Field, g as FieldLabel, h as FieldGroup, i as AlertTitle, m as FieldError, o as Card, p as FieldDescription, r as AlertDescription, s as CardContent, t as Alert, u as CardHeader, y as Label } from "./field-asw83X0v.mjs";
6
+ import { a as AlertDialogDescription, i as AlertDialogContent, l as AlertDialogTitle, n as AlertDialogAction, o as AlertDialogFooter, r as AlertDialogCancel, s as AlertDialogHeader, t as AlertDialog$1 } from "./alert-dialog-C43Doa0I.mjs";
7
+ import { a as DialogHeader, i as DialogFooter, n as DialogContent, o as DialogTitle, r as DialogDescription, s as DialogTrigger, t as Dialog$1 } from "./dialog-BbYDMjdC.mjs";
8
+ import { a as TableHeader, i as TableHead, n as TableBody, o as TableRow, r as TableCell, t as Table } from "./table-37Dd23TN.mjs";
11
9
  import { n as toast } from "../_libs/sonner.mjs";
12
- import { C as normalizeCohortValue, S as isValidCohort, f as getNumericCohortRolloutPosition, g as getPatchFileHash, h as getPatchBaseFileHash, m as getPatchBaseBundleId, r as NUMERIC_COHORT_SIZE, t as INVALID_COHORT_ERROR_MESSAGE, w as normalizeRolloutCohortCount } from "./dist-CyzPaI5v.mjs";
13
- import { r as extractTimestampFromUUIDv7, t as createUUIDv7 } from "./uuidv7-D0QFkPL_.mjs";
14
- import { a as Area, i as XAxis, r as YAxis, s as CartesianGrid, t as AreaChart } from "../_libs/recharts+[...].mjs";
15
- import { _ as usePromoteReleaseMutation, a as ChartTooltipContent, b as useReleasesQuery, c as useBundleChildCountsQuery, d as useChannelsQuery, f as useConfigQuery, g as usePreflightReleaseMutation, h as useDeleteReleaseMutation, i as ChartTooltip, l as useBundleChildrenQuery, m as useDeleteChannelMutation, n as ChartLegend, o as getBundleActivityRpc, p as useCreateChannelMutation, r as ChartLegendContent, s as getRecoveryReportRpc, t as ChartContainer, u as useBundleQuery, v as useReleaseCatalogDiagnosticsQuery, x as useUpdateReleaseMutation, y as useReleaseQuery } from "./api-BfCgYlj5.mjs";
16
- import { a as SelectItem, i as SelectGroup, n as Select$1, o as SelectTrigger, r as SelectContent, s as SelectValue, t as PlatformIcon } from "./select-DD2szs3Y.mjs";
17
- import { a as InputGroupText, i as InputGroupInput, n as InputGroupAddon, o as Textarea, t as InputGroup } from "./input-group-BrGSjz4S.mjs";
18
- import { t as HashValueDisplay } from "./HashValueDisplay-CyMmr0O9.mjs";
19
- import { n as updateReleaseFilters, t as Route } from "./routes-Dru3IRj0.mjs";
10
+ import { h as Link } from "../_libs/@tanstack/react-router+[...].mjs";
11
+ import { E as normalizeRolloutCohortCount, T as normalizeCohortValue, _ as getPatchBaseBundleId, h as getNumericCohortRolloutPosition, i as NUMERIC_COHORT_SIZE, t as INVALID_COHORT_ERROR_MESSAGE, v as getPatchBaseFileHash, w as isValidCohort, y as getPatchFileHash } from "./dist-CbQbBIw-.mjs";
12
+ import { r as extractTimestampFromUUIDv7 } from "./uuidv7-C88s9jWF.mjs";
13
+ import { n as normalizeRange } from "../_libs/verkit.mjs";
14
+ import { a as SelectItem, i as SelectGroup, n as Select$1, o as SelectTrigger, r as SelectContent, s as SelectValue, t as PlatformIcon } from "./select-t3iXRwc9.mjs";
15
+ import { a as InputGroupText, i as InputGroupInput, n as InputGroupAddon, o as Textarea, t as InputGroup } from "./input-group-CuYJHosb.mjs";
16
+ import { a as useConfigQuery, c as useDeleteReleaseMutation, d as useReleaseCatalogDiagnosticsQuery, f as useReleaseQuery, i as useChannelsQuery, l as usePreflightReleaseMutation, m as useUpdateReleaseMutation, n as useBundleChildrenQuery, o as useCreateChannelMutation, p as useReleasesQuery, r as useBundleQuery, s as useDeleteChannelMutation, t as useBundleChildCountsQuery, u as usePromoteReleaseMutation } from "./api-oZjRn9tP.mjs";
17
+ import { t as BundleIdDisplay } from "./BundleIdDisplay-x94o9rlU.mjs";
18
+ import { t as HashValueDisplay } from "./HashValueDisplay-n1GholGS.mjs";
19
+ import { n as useDialogTarget, t as Switch$1 } from "./switch-E-btwMGt.mjs";
20
20
  import { n as require_dayjs_min, t as require_relativeTime } from "../_libs/dayjs.mjs";
21
- import { t as normalizeRange } from "../_libs/verkit.mjs";
22
- //#region node_modules/.nitro/vite/services/ssr/assets/routes-DY-vqU6R.js
21
+ import { a as updateReleaseFilters, i as releaseFilterOf, n as Route, r as hasReleaseFilters, s as useReleaseColumns, t as ReleaseSections } from "./routes-V8sDybGf.mjs";
22
+ //#region node_modules/.nitro/vite/services/ssr/assets/routes-DgvnFqDy.js
23
23
  var import_react = /* @__PURE__ */ __toESM(require_react());
24
24
  var import_jsx_runtime = require_jsx_runtime();
25
25
  var import_dayjs_min = /* @__PURE__ */ __toESM(require_dayjs_min());
26
26
  var import_relativeTime = /* @__PURE__ */ __toESM(require_relativeTime());
27
- function BundleIdDisplay({ bundleId, className }) {
28
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
29
- translate: "no",
30
- className: cn("break-all font-mono text-xs tabular-nums", className),
31
- children: bundleId
32
- });
33
- }
34
27
  var channelColors = {
35
28
  production: "bg-green-500/10 text-green-700 dark:text-green-400 border-green-500/20",
36
29
  dev: "bg-blue-500/10 text-blue-700 dark:text-blue-400 border-blue-500/20",
@@ -259,190 +252,10 @@ function BundleChildrenPanel({ panelId, bundle, bundles, loading, onDetailClick
259
252
  })
260
253
  });
261
254
  }
262
- var config = {
263
- active: {
264
- label: "Active",
265
- color: "var(--chart-2)"
266
- },
267
- recoveredInstallations: {
268
- label: "Rollback",
269
- color: "var(--muted-foreground)"
270
- }
271
- };
272
- var formatDate = (ms) => new Intl.DateTimeFormat("en", {
273
- month: "short",
274
- day: "numeric",
275
- hour: "numeric",
276
- timeZone: "UTC"
277
- }).format(ms);
278
- function BundleActivityChart({ series }) {
279
- if (!series) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
280
- className: "flex h-16 items-center justify-center border-t text-xs text-muted-foreground sm:h-20",
281
- children: "No reports in 24 hours. Check again after the app reports activity."
282
- });
283
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
284
- className: "border-t pt-3",
285
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartContainer, {
286
- "aria-label": "Bundle activity over 24 hours, UTC",
287
- className: "h-32 w-full aspect-auto sm:h-40",
288
- config,
289
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AreaChart, {
290
- accessibilityLayer: true,
291
- data: series.points,
292
- margin: {
293
- left: -16,
294
- right: 4,
295
- top: 4
296
- },
297
- children: [
298
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CartesianGrid, { vertical: false }),
299
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XAxis, {
300
- axisLine: false,
301
- dataKey: "startMs",
302
- minTickGap: 28,
303
- tickFormatter: formatDate,
304
- tickLine: false
305
- }),
306
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(YAxis, {
307
- allowDecimals: false,
308
- axisLine: false,
309
- tickLine: false,
310
- width: 40
311
- }),
312
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartLegend, { content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartLegendContent, {}) }),
313
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltipContent, { labelFormatter: (_, payload) => `${formatDate(payload[0]?.payload.startMs)} · UTC` }) }),
314
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Area, {
315
- dataKey: "active",
316
- dot: { r: 2 },
317
- fill: "var(--color-active)",
318
- fillOpacity: .12,
319
- isAnimationActive: false,
320
- stroke: "var(--color-active)",
321
- strokeWidth: 2,
322
- type: "linear"
323
- }),
324
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Area, {
325
- dataKey: "recoveredInstallations",
326
- fill: "var(--color-recoveredInstallations)",
327
- fillOpacity: .04,
328
- isAnimationActive: false,
329
- stroke: "var(--color-recoveredInstallations)",
330
- strokeWidth: 1.5,
331
- type: "linear"
332
- })
333
- ]
334
- })
335
- })
336
- });
337
- }
338
- function BundleMovementSummary({ report, loading = false }) {
339
- if (!report) return loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, {
340
- "aria-label": "Loading bundle activity",
341
- className: "h-4 w-32"
342
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
343
- "aria-label": "30-day bundle activity unavailable",
344
- className: "text-sm text-muted-foreground",
345
- children: "—"
346
- });
347
- const series = report.series[0];
348
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
349
- role: "group",
350
- "aria-label": "Bundle activity over 30 days",
351
- title: report.truncated ? "Partial history. Counts include only the available reports." : "Active: last observed ID per installation. Rollbacks: distinct installations recovered from this ID in 30 days.",
352
- className: "flex min-w-[140px] items-baseline gap-3 whitespace-nowrap",
353
- children: [
354
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
355
- className: "flex items-baseline gap-1.5",
356
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
357
- className: "text-xs text-muted-foreground",
358
- children: "Active"
359
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
360
- className: "text-sm font-medium tabular-nums",
361
- children: series?.activeInstallations ?? 0
362
- })]
363
- }),
364
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
365
- className: "flex items-baseline gap-1.5",
366
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
367
- className: "text-xs text-muted-foreground",
368
- children: "Rollback"
369
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
370
- className: "text-sm font-medium tabular-nums",
371
- children: series?.recoveredInstallations ?? 0
372
- })]
373
- }),
374
- report.truncated ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
375
- className: "text-xs text-muted-foreground",
376
- children: "Partial"
377
- }) : null
378
- ]
379
- });
380
- }
381
- function BundleInsightsSummary({ input }) {
382
- const activityInput = {
383
- ...input,
384
- window: "24h"
385
- };
386
- const query = useQuery({
387
- queryKey: ["rollout-activity", activityInput],
388
- queryFn: () => getRecoveryReportRpc({ data: activityInput }),
389
- staleTime: 3e4
390
- });
391
- const report = query.data;
392
- const series = report?.series[0];
393
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, {
394
- className: "px-4 pt-4 pb-3",
395
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
396
- className: "text-sm font-medium",
397
- children: "Activity · 24 hours"
398
- })
399
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, {
400
- className: "flex flex-col gap-3 px-4 pb-4",
401
- children: query.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, {
402
- "aria-label": "Loading bundle activity",
403
- className: "h-32 w-full"
404
- }) : query.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
405
- className: "flex items-center justify-between gap-3 text-sm text-muted-foreground",
406
- children: ["Insights unavailable", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
407
- variant: "outline",
408
- size: "sm",
409
- onClick: () => void query.refetch(),
410
- children: "Retry"
411
- })]
412
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
413
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", {
414
- className: "grid grid-cols-2 divide-x divide-border/70",
415
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
416
- className: "pr-4",
417
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
418
- className: "text-xs text-muted-foreground",
419
- children: "Active"
420
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
421
- className: "mt-1 text-xl font-semibold tabular-nums",
422
- children: series?.activeInstallations ?? 0
423
- })]
424
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
425
- className: "pl-4",
426
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
427
- className: "text-xs text-muted-foreground",
428
- children: "Rollback · 24h"
429
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
430
- className: "mt-1 text-xl font-semibold tabular-nums",
431
- children: series?.recoveredInstallations ?? 0
432
- })]
433
- })]
434
- }),
435
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BundleActivityChart, { series }),
436
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
437
- className: "text-xs text-muted-foreground",
438
- children: ["Last observed active installations · hourly rollbacks", report?.truncated ? " · Partial history" : ""]
439
- })
440
- ] })
441
- })] });
442
- }
443
255
  function ChannelManagementDialog({ open, onOpenChange }) {
444
256
  const [channelName, setChannelName] = (0, import_react.useState)("");
445
257
  const [channelToDelete, setChannelToDelete] = (0, import_react.useState)(null);
258
+ const shownChannelToDelete = useDialogTarget(channelToDelete);
446
259
  const { data: channels = [], isPending: isLoadingChannels } = useChannelsQuery();
447
260
  const createChannel = useCreateChannelMutation();
448
261
  const deleteChannel = useDeleteChannelMutation();
@@ -451,13 +264,7 @@ function ChannelManagementDialog({ open, onOpenChange }) {
451
264
  event.preventDefault();
452
265
  if (!normalizedName || createChannel.isPending) return;
453
266
  try {
454
- const result = await createChannel.mutateAsync({
455
- row: {
456
- id: createUUIDv7(),
457
- name: normalizedName
458
- },
459
- onConflict: "returnExisting"
460
- });
267
+ const result = await createChannel.mutateAsync({ name: normalizedName });
461
268
  setChannelName("");
462
269
  if (result.inserted) toast.success(`Channel ${result.row.name} created`);
463
270
  else toast.info(`Channel ${result.row.name} already exists`);
@@ -485,10 +292,10 @@ function ChannelManagementDialog({ open, onOpenChange }) {
485
292
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogContent, {
486
293
  className: "sm:max-w-lg",
487
294
  children: [
488
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogTitle$1, {
295
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogTitle, {
489
296
  className: "flex items-center gap-2",
490
297
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { className: "size-4 text-muted-foreground" }), "Channels"]
491
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription$1, { children: "Create deployment channels and remove them when no bundle uses them. Empty channels remain available until you delete them." })] }),
298
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription, { children: "Create deployment channels and remove them when no bundle uses them. Empty channels remain available until you delete them." })] }),
492
299
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("form", {
493
300
  onSubmit: handleCreate,
494
301
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FieldGroup, {
@@ -565,7 +372,7 @@ function ChannelManagementDialog({ open, onOpenChange }) {
565
372
  },
566
373
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogContent, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogTitle, { children: [
567
374
  "Delete ",
568
- channelToDelete?.name,
375
+ shownChannelToDelete?.name,
569
376
  "?"
570
377
  ] }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogDescription, { children: "Only empty channels can be removed. The server checks this when you delete it, and the channel can be created again later with a new ID." })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertDialogCancel, {
571
378
  disabled: deleteChannel.isPending,
@@ -623,7 +430,7 @@ function BundleMetadata({ bundle, release }) {
623
430
  const hbcPatchBaseFileHash = bundle ? getPatchBaseFileHash(bundle) : null;
624
431
  const gitCommitUrl = bundle?.gitCommitHash && isFetched ? getCommitUrl(configData?.console.gitUrl, bundle.gitCommitHash) : null;
625
432
  const target = release.strategy === "APP_VERSION" ? release.target_app_version : release.fingerprint_hash;
626
- if (!(target || bundle?.gitCommitHash || bundle?.fileHash || hbcPatchBaseFileHash || hbcPatchFileHash)) return null;
433
+ if (!(target || bundle?.gitCommitHash || bundle?.manifestFileHash || hbcPatchBaseFileHash || hbcPatchFileHash)) return null;
627
434
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, {
628
435
  className: "p-4 pb-3",
629
436
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
@@ -661,11 +468,11 @@ function BundleMetadata({ bundle, release }) {
661
468
  }) : null]
662
469
  })
663
470
  }) : null,
664
- bundle?.fileHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Row, {
665
- label: "Bundle hash",
471
+ bundle?.manifestFileHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Row, {
472
+ label: "Manifest hash",
666
473
  value: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HashValueDisplay, {
667
474
  maxLength: 16,
668
- value: bundle.fileHash
475
+ value: bundle.manifestFileHash
669
476
  })
670
477
  }) : null,
671
478
  hbcPatchBaseFileHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Row, {
@@ -779,7 +586,7 @@ function RolloutCohortsDialog({ releaseId, rolloutCohortCount, targetCohorts })
779
586
  children: [
780
587
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, {
781
588
  className: "shrink-0 border-b border-border/70 px-4 py-4",
782
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle$1, { children: "Rolled out cohorts" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogDescription$1, { children: [
589
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, { children: "Rolled out cohorts" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogDescription, { children: [
783
590
  rolloutPercentage,
784
591
  "% includes ",
785
592
  selectedCount,
@@ -800,7 +607,7 @@ function RolloutCohortsDialog({ releaseId, rolloutCohortCount, targetCohorts })
800
607
  })
801
608
  ]
802
609
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
803
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle$1, { children: "Rolled out cohorts" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogDescription$1, { children: [
610
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, { children: "Rolled out cohorts" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogDescription, { children: [
804
611
  rolloutPercentage,
805
612
  "% includes ",
806
613
  selectedCount,
@@ -815,66 +622,6 @@ function RolloutCohortsDialog({ releaseId, rolloutCohortCount, targetCohorts })
815
622
  ] })
816
623
  })] });
817
624
  }
818
- function Sheet({ ...props }) {
819
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogRoot, {
820
- "data-slot": "sheet",
821
- ...props
822
- });
823
- }
824
- function SheetPortal({ ...props }) {
825
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogPortal, {
826
- "data-slot": "sheet-portal",
827
- ...props
828
- });
829
- }
830
- function SheetOverlay({ className, ...props }) {
831
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogBackdrop, {
832
- "data-slot": "sheet-overlay",
833
- className: cn("fixed inset-0 z-50 bg-black/80 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs", className),
834
- ...props
835
- });
836
- }
837
- function SheetContent({ className, children, side = "right", showCloseButton = true, ...props }) {
838
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SheetPortal, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SheetOverlay, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogPopup, {
839
- "data-slot": "sheet-content",
840
- "data-side": side,
841
- className: cn("fixed z-50 flex flex-col bg-background bg-clip-padding text-xs/relaxed shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm", className),
842
- ...props,
843
- children: [children, showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogClose, {
844
- "data-slot": "sheet-close",
845
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
846
- variant: "ghost",
847
- className: "absolute top-4 right-4",
848
- size: "icon-sm"
849
- }),
850
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
851
- className: "sr-only",
852
- children: "Close"
853
- })]
854
- })]
855
- })] });
856
- }
857
- function SheetHeader({ className, ...props }) {
858
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
859
- "data-slot": "sheet-header",
860
- className: cn("flex flex-col gap-1.5 p-6", className),
861
- ...props
862
- });
863
- }
864
- function SheetTitle({ className, ...props }) {
865
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, {
866
- "data-slot": "sheet-title",
867
- className: cn("text-sm font-medium text-foreground", className),
868
- ...props
869
- });
870
- }
871
- function SheetDescription({ className, ...props }) {
872
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription, {
873
- "data-slot": "sheet-description",
874
- className: cn("text-xs/relaxed text-muted-foreground", className),
875
- ...props
876
- });
877
- }
878
625
  function Slider$1({ className, defaultValue, value, min = 0, max = 100, ...props }) {
879
626
  const _values = Array.isArray(value) ? value : value !== void 0 ? [value] : Array.isArray(defaultValue) ? defaultValue : defaultValue !== void 0 ? [defaultValue] : [min];
880
627
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SliderRoot, {
@@ -902,17 +649,6 @@ function Slider$1({ className, defaultValue, value, min = 0, max = 100, ...props
902
649
  })
903
650
  });
904
651
  }
905
- function Switch$1({ className, ...props }) {
906
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwitchRoot, {
907
- "data-slot": "switch",
908
- className: cn("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background data-checked:bg-primary data-unchecked:bg-input data-disabled:cursor-not-allowed data-disabled:opacity-50", className),
909
- ...props,
910
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwitchThumb, {
911
- "data-slot": "switch-thumb",
912
- className: "pointer-events-none block size-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-checked:translate-x-4 data-unchecked:translate-x-0"
913
- })
914
- });
915
- }
916
652
  var promoteActionItems = [{
917
653
  label: "Move bundle",
918
654
  value: "move"
@@ -995,7 +731,7 @@ function RolloutPercentageInput({ value, onChange }) {
995
731
  })]
996
732
  });
997
733
  }
998
- function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
734
+ function ReleaseEditorSheet({ channels, onOpenChange, onShowScope, open, releaseId }) {
999
735
  const releaseQuery = useReleaseQuery(releaseId);
1000
736
  const release = releaseQuery.data;
1001
737
  const bundleQuery = useBundleQuery(release?.bundle_id ?? "");
@@ -1133,7 +869,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1133
869
  maxLength: 18
1134
870
  }), !release.bundle_id ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
1135
871
  className: "text-xs text-foreground",
1136
- children: "Built-in app"
872
+ children: "Built-in bundle"
1137
873
  }) : null]
1138
874
  })]
1139
875
  }),
@@ -1174,10 +910,11 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1174
910
  }) : null, release && draft ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1175
911
  className: "flex flex-col gap-6 px-4 pb-4 sm:px-6 sm:pb-6",
1176
912
  children: [
1177
- channelName ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BundleInsightsSummary, { input: {
913
+ channelName ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReleaseSections, { release: {
1178
914
  platform: release.platform,
1179
915
  channel: channelName,
1180
- releaseId: release.id
916
+ releaseId: release.id,
917
+ builtIn: !release.bundle_id
1181
918
  } }) : null,
1182
919
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
1183
920
  "aria-labelledby": "delivery-settings-heading",
@@ -1342,7 +1079,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1342
1079
  }),
1343
1080
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1344
1081
  className: "w-full",
1345
- disabled: release.kind !== "BUNDLE" || busy,
1082
+ disabled: !release.bundle_id || busy,
1346
1083
  onClick: () => setShowPromote(true),
1347
1084
  size: "sm",
1348
1085
  variant: "outline",
@@ -1357,7 +1094,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1357
1094
  },
1358
1095
  size: "sm",
1359
1096
  variant: "outline",
1360
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { "data-icon": "inline-start" }), "Download bundle"]
1097
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { "data-icon": "inline-start" }), "Download manifest"]
1361
1098
  }) : null,
1362
1099
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1363
1100
  className: "w-full",
@@ -1396,7 +1133,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1396
1133
  className: "sm:col-span-2",
1397
1134
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Artifact ID" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
1398
1135
  className: "mt-1 break-all font-mono text-foreground",
1399
- children: release.bundle_id ?? "Built-in app"
1136
+ children: release.bundle_id ?? "Built-in bundle"
1400
1137
  })]
1401
1138
  }),
1402
1139
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Revision" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
@@ -1420,10 +1157,20 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1420
1157
  })] }),
1421
1158
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1422
1159
  className: "sm:col-span-2",
1423
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Scope key" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
1424
- className: "mt-1 break-all font-mono text-foreground",
1425
- children: release.scope_key
1426
- })]
1160
+ children: [
1161
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Scope key" }),
1162
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
1163
+ className: "mt-1 break-all font-mono text-foreground",
1164
+ children: release.scope_key
1165
+ }),
1166
+ onShowScope ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1167
+ className: "mt-1 h-auto px-0 text-xs",
1168
+ onClick: () => onShowScope(release.scope_key),
1169
+ size: "sm",
1170
+ variant: "link",
1171
+ children: "Show bundles for this target"
1172
+ }) : null
1173
+ ]
1427
1174
  })
1428
1175
  ]
1429
1176
  }),
@@ -1482,7 +1229,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1482
1229
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogContent, {
1483
1230
  showCloseButton: !promote.isPending,
1484
1231
  children: [
1485
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle$1, { children: "Promote to Channel" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription$1, { children: "Choose how to promote this Bundle, then select the target channel." })] }),
1232
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, { children: "Promote to Channel" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription, { children: "Choose how to promote this Bundle, then select the target channel." })] }),
1486
1233
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1487
1234
  className: "space-y-4 py-4",
1488
1235
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -1587,28 +1334,26 @@ function RolloutPercentageBadge({ percentage, className }) {
1587
1334
  ]
1588
1335
  });
1589
1336
  }
1590
- function useBundleActivityQuery(inputs) {
1591
- const sorted = [...inputs].sort((a, b) => a.releaseId.localeCompare(b.releaseId));
1592
- return useQuery({
1593
- queryKey: ["bundle-activity", sorted],
1594
- queryFn: () => getBundleActivityRpc({ data: sorted }),
1595
- enabled: sorted.length > 0,
1596
- staleTime: 3e4
1597
- });
1598
- }
1599
1337
  var PAGE_SIZE = 20;
1600
- var platformFilterItems = [
1338
+ var platformFilterItems = [{
1339
+ label: "iOS",
1340
+ value: "ios"
1341
+ }, {
1342
+ label: "Android",
1343
+ value: "android"
1344
+ }];
1345
+ var statusFilterItems = [
1601
1346
  {
1602
- label: "All Platforms",
1347
+ label: "Any Status",
1603
1348
  value: "all"
1604
1349
  },
1605
1350
  {
1606
- label: "iOS",
1607
- value: "ios"
1351
+ label: "Enabled",
1352
+ value: "enabled"
1608
1353
  },
1609
1354
  {
1610
- label: "Android",
1611
- value: "android"
1355
+ label: "Disabled",
1356
+ value: "disabled"
1612
1357
  }
1613
1358
  ];
1614
1359
  var dateFormatter = new Intl.DateTimeFormat(void 0, {
@@ -1616,9 +1361,17 @@ var dateFormatter = new Intl.DateTimeFormat(void 0, {
1616
1361
  timeStyle: "short"
1617
1362
  });
1618
1363
  var tableDateFormatter = new Intl.DateTimeFormat(void 0, { dateStyle: "medium" });
1364
+ /**
1365
+ * Opens a bundle from a click anywhere on its row or card, except on a
1366
+ * control inside it, which keeps its own action.
1367
+ */
1368
+ var openOutsideControls = (open) => (event) => {
1369
+ if (event.target instanceof Element && event.target.closest("button, a, input, select, textarea")) return;
1370
+ open();
1371
+ };
1619
1372
  function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, search }) {
1620
- const [targetAppVersion, setTargetAppVersion] = (0, import_react.useState)(search.targetAppVersion ?? "");
1621
- const hasFilters = Boolean(search.bundleId || search.channelId || search.enabled !== void 0 || search.platform || search.targetAppVersion);
1373
+ const hasFilters = hasReleaseFilters(search);
1374
+ const channelSelected = search.channelId !== void 0;
1622
1375
  const channelFilterItems = [{
1623
1376
  label: "All Channels",
1624
1377
  value: "all"
@@ -1626,12 +1379,6 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1626
1379
  label: channel.name,
1627
1380
  value: channel.id
1628
1381
  }))];
1629
- const applyTargetAppVersion = () => {
1630
- onChange({ targetAppVersion: targetAppVersion.trim() || void 0 });
1631
- };
1632
- (0, import_react.useEffect)(() => {
1633
- setTargetAppVersion(search.targetAppVersion ?? "");
1634
- }, [search.targetAppVersion]);
1635
1382
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
1636
1383
  className: "sticky top-0 z-10 flex shrink-0 flex-wrap items-center gap-2 border-b bg-background px-3 py-3 sm:h-12 sm:flex-nowrap sm:bg-card/70 sm:px-4 sm:py-0 sm:backdrop-blur-sm",
1637
1384
  children: [
@@ -1647,40 +1394,6 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1647
1394
  children: "Filters"
1648
1395
  })]
1649
1396
  }),
1650
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1651
- items: platformFilterItems,
1652
- onValueChange: (value) => onChange({ platform: value === "all" ? void 0 : value }),
1653
- value: search.platform ?? "all",
1654
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
1655
- "aria-label": "Platform",
1656
- className: "h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]",
1657
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {})
1658
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [
1659
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1660
- value: "all",
1661
- children: "All Platforms"
1662
- }),
1663
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1664
- value: "ios",
1665
- children: "iOS"
1666
- }),
1667
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1668
- value: "android",
1669
- children: "Android"
1670
- })
1671
- ] }) })]
1672
- }),
1673
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Input, {
1674
- "aria-label": "Target app version",
1675
- className: "h-8 w-full min-w-[132px] text-xs sm:w-[160px]",
1676
- onBlur: applyTargetAppVersion,
1677
- onChange: (event) => setTargetAppVersion(event.target.value),
1678
- onKeyDown: (event) => {
1679
- if (event.key === "Enter") applyTargetAppVersion();
1680
- },
1681
- placeholder: "Target version",
1682
- value: targetAppVersion
1683
- }),
1684
1397
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1685
1398
  items: channelFilterItems,
1686
1399
  onValueChange: (value) => onChange({ channelId: value === null || value === "all" ? void 0 : value }),
@@ -1697,6 +1410,48 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1697
1410
  children: channel.name
1698
1411
  }, channel.id))] }) })]
1699
1412
  }),
1413
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1414
+ disabled: !channelSelected,
1415
+ items: platformFilterItems,
1416
+ onValueChange: (value) => onChange({ platform: value === "android" ? "android" : "ios" }),
1417
+ value: search.platform ?? "ios",
1418
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
1419
+ "aria-label": "Platform",
1420
+ className: "h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]",
1421
+ title: channelSelected ? void 0 : "Choose a channel first",
1422
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {})
1423
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1424
+ value: "ios",
1425
+ children: "iOS"
1426
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1427
+ value: "android",
1428
+ children: "Android"
1429
+ })] }) })]
1430
+ }),
1431
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1432
+ disabled: !channelSelected && search.scopeKey === void 0,
1433
+ items: statusFilterItems,
1434
+ onValueChange: (value) => onChange({ enabled: value === "enabled" ? true : value === "disabled" ? false : void 0 }),
1435
+ value: search.enabled === void 0 ? "all" : search.enabled ? "enabled" : "disabled",
1436
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
1437
+ "aria-label": "Status",
1438
+ className: "h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]",
1439
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {})
1440
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [
1441
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1442
+ value: "all",
1443
+ children: "Any Status"
1444
+ }),
1445
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1446
+ value: "enabled",
1447
+ children: "Enabled"
1448
+ }),
1449
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1450
+ value: "disabled",
1451
+ children: "Disabled"
1452
+ })
1453
+ ] }) })]
1454
+ }),
1700
1455
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1701
1456
  "aria-label": "Manage channels",
1702
1457
  onClick: onManageChannels,
@@ -1716,6 +1471,17 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1716
1471
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "size-3" })
1717
1472
  })]
1718
1473
  }) : null,
1474
+ search.scopeKey ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge, {
1475
+ className: "max-w-48 gap-1",
1476
+ variant: "secondary",
1477
+ children: ["Target filter", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
1478
+ "aria-label": "Clear target filter",
1479
+ className: "rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1480
+ onClick: () => onChange({ scopeKey: void 0 }),
1481
+ type: "button",
1482
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "size-3" })
1483
+ })]
1484
+ }) : null,
1719
1485
  hasFilters ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
1720
1486
  className: "h-8 px-2 text-xs text-muted-foreground hover:text-foreground sm:ml-auto",
1721
1487
  onClick: onClear,
@@ -1757,7 +1523,7 @@ function BundleEntry({ expanded, onOpen, onToggleExpand, release }) {
1757
1523
  fullOnMobile: true
1758
1524
  }), !release.bundle_id ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
1759
1525
  className: "inline-flex items-center gap-1.5 text-sm",
1760
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RotateCcw, { className: "size-3.5" }), " Built-in app"]
1526
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RotateCcw, { className: "size-3.5" }), " Built-in bundle"]
1761
1527
  }) : null]
1762
1528
  }),
1763
1529
  operationLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
@@ -1766,9 +1532,9 @@ function BundleEntry({ expanded, onOpen, onToggleExpand, release }) {
1766
1532
  children: operationLabel
1767
1533
  }) : null,
1768
1534
  release.currentlyUnreachable ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
1769
- "aria-label": "Currently unreachable. No catalog segment or cohort selects this bundle first.",
1535
+ "aria-label": "Unreachable: no device gets this bundle with the current delivery settings.",
1770
1536
  className: "inline-flex shrink-0 items-center gap-1 text-xs text-muted-foreground",
1771
- title: "No catalog segment or cohort selects this bundle first with the current delivery settings.",
1537
+ title: "No device gets this bundle with the current delivery settings.",
1772
1538
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleOff, { className: "size-3.5" }), "Unreachable"]
1773
1539
  }) : null
1774
1540
  ]
@@ -1813,26 +1579,25 @@ function BundlesPage() {
1813
1579
  const releasesQuery = useReleasesQuery({
1814
1580
  afterReleaseId: search.afterReleaseId,
1815
1581
  beforeReleaseId: search.beforeReleaseId,
1816
- bundleId: search.bundleId,
1817
- channelId: search.channelId,
1818
- enabled: search.enabled,
1819
- limit: PAGE_SIZE,
1820
- page: search.page,
1821
- platform: search.platform,
1822
- targetAppVersion: search.targetAppVersion
1582
+ filter: releaseFilterOf(search),
1583
+ limit: PAGE_SIZE
1823
1584
  });
1824
1585
  const channels = useChannelsQuery().data ?? [];
1825
1586
  const releases = releasesQuery.data?.data ?? [];
1826
1587
  const patchCountsByBundleId = useBundleChildCountsQuery(Array.from(new Set(releases.flatMap((release) => release.bundle_id ? [release.bundle_id] : [])))).data ?? {};
1827
- const pagination = releasesQuery.data?.pagination;
1828
- const activityQuery = useBundleActivityQuery(releases.flatMap((release) => {
1588
+ const nextCursor = releasesQuery.data?.next;
1589
+ const previousCursor = releasesQuery.data?.previous;
1590
+ const slotReleases = releases.flatMap((release) => {
1829
1591
  const channel = channels.find((item) => item.id === release.channel_id)?.name;
1830
1592
  return channel ? [{
1831
1593
  releaseId: release.id,
1832
1594
  platform: release.platform,
1833
- channel
1595
+ channel,
1596
+ builtIn: !release.bundle_id
1834
1597
  }] : [];
1835
- }));
1598
+ });
1599
+ const featureColumns = useReleaseColumns();
1600
+ const columnCount = 10 + featureColumns.length;
1836
1601
  const channelNames = new Map(channels.map((channel) => [channel.id, channel.name]));
1837
1602
  (0, import_react.useEffect)(() => {
1838
1603
  if (expandedReleaseId && !releases.some((release) => release.id === expandedReleaseId)) setExpandedReleaseId(void 0);
@@ -1855,26 +1620,25 @@ function BundlesPage() {
1855
1620
  }
1856
1621
  changeFilters({ bundleId: bundle.id });
1857
1622
  };
1858
- const currentPage = pagination?.currentPage ?? 1;
1859
- const startEntry = releases.length === 0 ? 0 : (currentPage - 1) * PAGE_SIZE + 1;
1860
- const endEntry = startEntry === 0 ? 0 : startEntry + releases.length - 1;
1861
- const previousPage = currentPage - 1;
1862
- const firstReleaseId = releases[0]?.id;
1863
- const lastReleaseId = releases.at(-1)?.id;
1864
- const previousSearch = pagination?.hasPreviousPage && firstReleaseId ? {
1623
+ const onLaterPage = search.afterReleaseId !== void 0 || search.beforeReleaseId !== void 0;
1624
+ const previousSearch = previousCursor ? {
1865
1625
  ...search,
1866
- afterReleaseId: firstReleaseId,
1626
+ afterReleaseId: previousCursor,
1867
1627
  beforeReleaseId: void 0,
1868
- page: previousPage > 1 ? previousPage : void 0,
1869
1628
  releaseId: void 0
1870
1629
  } : null;
1871
- const nextSearch = pagination?.hasNextPage && lastReleaseId ? {
1630
+ const nextSearch = nextCursor ? {
1872
1631
  ...search,
1873
1632
  afterReleaseId: void 0,
1874
- beforeReleaseId: lastReleaseId,
1875
- page: currentPage + 1,
1633
+ beforeReleaseId: nextCursor,
1876
1634
  releaseId: void 0
1877
1635
  } : null;
1636
+ const newestSearch = {
1637
+ ...search,
1638
+ afterReleaseId: void 0,
1639
+ beforeReleaseId: void 0,
1640
+ releaseId: void 0
1641
+ };
1878
1642
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1879
1643
  className: "flex h-svh min-h-0 min-w-0 flex-col",
1880
1644
  children: [
@@ -1907,7 +1671,13 @@ function BundlesPage() {
1907
1671
  const isExpanded = expandedReleaseId === release.id;
1908
1672
  const panelId = `bundle-lineage-panel-${release.id}`;
1909
1673
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", {
1910
- className: cn("flex flex-col gap-4 border-b p-4 last:border-b-0", release.currentlyUnreachable && "bg-muted/35 saturate-50 transition-[background-color,filter] focus-within:saturate-100 motion-reduce:transition-none", isExpanded && "border-b-0 bg-primary/5"),
1674
+ "aria-label": `Bundle ${release.id}`,
1675
+ className: cn("flex cursor-pointer touch-manipulation flex-col gap-4 border-b p-4 transition-[background-color,filter] last:border-b-0 hover:bg-muted/10 active:bg-muted/20 motion-reduce:transition-none data-[state=selected]:bg-muted/15", release.currentlyUnreachable && "bg-muted/35 saturate-50 hover:bg-muted/50 hover:saturate-100 focus-within:saturate-100", isExpanded && "border-b-0 bg-primary/5"),
1676
+ "data-state": search.releaseId === release.id ? "selected" : void 0,
1677
+ onClick: openOutsideControls(() => go({
1678
+ ...search,
1679
+ releaseId: release.id
1680
+ }, false)),
1911
1681
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1912
1682
  className: "flex items-start justify-between gap-3",
1913
1683
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BundleEntry, {
@@ -1968,16 +1738,16 @@ function BundlesPage() {
1968
1738
  children: patchCount === void 0 ? "Checking" : patchCount > 0 ? `${patchCount} ${patchCount === 1 ? "patch" : "patches"}` : "—"
1969
1739
  })]
1970
1740
  }),
1971
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1741
+ featureColumns.map(({ Cell, feature, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1972
1742
  className: "col-span-2 rounded-md bg-muted/40 p-3",
1973
1743
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
1974
1744
  className: "mb-2 text-muted-foreground",
1975
- children: "Activity · 30d"
1976
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BundleMovementSummary, {
1977
- report: activityQuery.data?.[release.id],
1978
- loading: activityQuery.isFetching
1745
+ children: label
1746
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cell, {
1747
+ releaseId: release.id,
1748
+ releases: slotReleases
1979
1749
  }) })]
1980
- }),
1750
+ }, feature)),
1981
1751
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1982
1752
  className: "col-span-2 flex flex-wrap items-center gap-2 rounded-md bg-muted/40 p-3",
1983
1753
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReleaseStateBadge, { release }), release.should_force_update ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
@@ -1986,7 +1756,7 @@ function BundlesPage() {
1986
1756
  }) : null]
1987
1757
  }),
1988
1758
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1989
- className: "col-span-2 grid gap-2 rounded-md border bg-background/80 p-3",
1759
+ className: "col-span-2 grid grid-cols-1 gap-2 rounded-md border bg-background/80 p-3",
1990
1760
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1991
1761
  className: "flex items-start justify-between gap-3",
1992
1762
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
@@ -2016,7 +1786,7 @@ function BundlesPage() {
2016
1786
  }) : null] }, release.id);
2017
1787
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
2018
1788
  className: "p-8 text-center text-sm text-muted-foreground",
2019
- children: search.bundleId || search.channelId || search.enabled !== void 0 || search.platform || search.targetAppVersion ? "No bundles match these filters." : "No bundles yet. Deploy an update to see it here."
1789
+ children: onLaterPage ? "No more bundles on this side." : hasReleaseFilters(search) ? "No bundles match these filters." : "No bundles yet. Deploy an update to see it here."
2020
1790
  })
2021
1791
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table, {
2022
1792
  className: "min-w-max",
@@ -2033,13 +1803,13 @@ function BundlesPage() {
2033
1803
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Enabled" }),
2034
1804
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Force update" }),
2035
1805
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Rollout" }),
2036
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Activity · 30d" }),
1806
+ featureColumns.map(({ feature, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: label }, feature)),
2037
1807
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Message" }),
2038
1808
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Created" })
2039
1809
  ]
2040
1810
  })
2041
1811
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableBody, { children: [releasesQuery.isPending ? Array.from({ length: 7 }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2042
- colSpan: 11,
1812
+ colSpan: columnCount,
2043
1813
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, { className: "h-8 w-full" })
2044
1814
  }) }, index)) : releases.map((release) => {
2045
1815
  const isExpanded = expandedReleaseId === release.id;
@@ -2048,13 +1818,10 @@ function BundlesPage() {
2048
1818
  "aria-label": `Open bundle ${release.id}`,
2049
1819
  className: cn("cursor-pointer transition-[background-color,filter] hover:bg-muted/10 focus-within:bg-muted/15 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring motion-reduce:transition-none data-[state=selected]:bg-muted/15 [&>td]:py-3", release.currentlyUnreachable && "bg-muted/35 saturate-50 hover:bg-muted/50 hover:saturate-100 focus-within:saturate-100", isExpanded && "bg-primary/5"),
2050
1820
  "data-state": search.releaseId === release.id ? "selected" : void 0,
2051
- onClick: (event) => {
2052
- if (event.target instanceof Element && event.target.closest("button, a, input, select, textarea")) return;
2053
- go({
2054
- ...search,
2055
- releaseId: release.id
2056
- }, false);
2057
- },
1821
+ onClick: openOutsideControls(() => go({
1822
+ ...search,
1823
+ releaseId: release.id
1824
+ }, false)),
2058
1825
  onKeyDown: (event) => {
2059
1826
  if (event.target !== event.currentTarget || event.key !== "Enter" && event.key !== " ") return;
2060
1827
  event.preventDefault();
@@ -2133,10 +1900,10 @@ function BundlesPage() {
2133
1900
  })]
2134
1901
  }) }),
2135
1902
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RolloutPercentageBadge, { percentage: release.rollout_cohort_count / 10 }) }),
2136
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BundleMovementSummary, {
2137
- report: activityQuery.data?.[release.id],
2138
- loading: activityQuery.isFetching
2139
- }) }),
1903
+ featureColumns.map(({ Cell, feature }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cell, {
1904
+ releaseId: release.id,
1905
+ releases: slotReleases
1906
+ }) }, feature)),
2140
1907
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2141
1908
  className: "text-sm text-muted-foreground",
2142
1909
  title: release.message ?? void 0,
@@ -2152,7 +1919,7 @@ function BundlesPage() {
2152
1919
  className: "hover:bg-transparent",
2153
1920
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2154
1921
  className: "border-t-0 p-0",
2155
- colSpan: 11,
1922
+ colSpan: columnCount,
2156
1923
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReleaseBundleChildrenPanel, {
2157
1924
  onDetailClick: openChildBundle,
2158
1925
  panelId,
@@ -2162,8 +1929,8 @@ function BundlesPage() {
2162
1929
  }) : null] }, release.id);
2163
1930
  }), !releasesQuery.isPending && releases.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2164
1931
  className: "h-40 text-center text-muted-foreground",
2165
- colSpan: 11,
2166
- children: search.bundleId || search.channelId || search.enabled !== void 0 || search.platform || search.targetAppVersion ? "No bundles match these filters." : "No bundles yet. Deploy an update to see it here."
1932
+ colSpan: columnCount,
1933
+ children: onLaterPage ? "No more bundles on this side." : hasReleaseFilters(search) ? "No bundles match these filters." : "No bundles yet. Deploy an update to see it here."
2167
1934
  }) }) : null] })]
2168
1935
  })
2169
1936
  }), !releasesQuery.isError && !releasesQuery.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("nav", {
@@ -2172,29 +1939,27 @@ function BundlesPage() {
2172
1939
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
2173
1940
  className: "text-xs font-medium text-muted-foreground",
2174
1941
  children: [
2175
- "Showing ",
2176
1942
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2177
1943
  className: "text-foreground",
2178
- children: startEntry
1944
+ children: releases.length
2179
1945
  }),
2180
- " to",
2181
1946
  " ",
2182
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2183
- className: "text-foreground",
2184
- children: endEntry
2185
- }),
2186
- " entries"
1947
+ releases.length === 1 ? "entry" : "entries",
1948
+ ", newest first"
2187
1949
  ]
2188
1950
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
2189
1951
  className: "flex flex-wrap items-center gap-3 sm:justify-end",
2190
1952
  children: [
2191
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
2192
- className: "text-xs font-medium text-muted-foreground",
2193
- children: ["Page ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2194
- className: "text-foreground",
2195
- children: currentPage
2196
- })]
2197
- }),
1953
+ onLaterPage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
1954
+ className: buttonVariants({
1955
+ className: "h-8 flex-1 px-3 text-xs sm:flex-none",
1956
+ size: "sm",
1957
+ variant: "ghost"
1958
+ }),
1959
+ search: newestSearch,
1960
+ to: "/",
1961
+ children: "Newest"
1962
+ }) : null,
2198
1963
  previousSearch ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
2199
1964
  className: buttonVariants({
2200
1965
  className: "h-8 flex-1 px-3 text-xs sm:flex-none",
@@ -2237,6 +2002,7 @@ function BundlesPage() {
2237
2002
  ...search,
2238
2003
  releaseId: void 0
2239
2004
  }, false),
2005
+ onShowScope: (scopeKey) => changeFilters({ scopeKey }),
2240
2006
  open: Boolean(search.releaseId),
2241
2007
  releaseId: search.releaseId ?? ""
2242
2008
  }),