@hot-updater/console 1.0.0-rc.4 → 1.0.0-rc.41

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 (330) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/ConsoleFeatureUnavailable-DRzeMGRM.js +1 -0
  3. package/.output/public/assets/EventDetails-SB5ygJzS.js +1 -0
  4. package/.output/public/assets/HashValueDisplay-BFX_kY3-.js +1 -0
  5. package/.output/public/assets/InsightsInfo-btYppp0B.js +1 -0
  6. package/.output/public/assets/InsightsPageHeader-Ba8psD8t.js +1 -0
  7. package/.output/public/assets/NotFoundPage-CyRG2eca.js +1 -0
  8. package/.output/public/assets/alert-dialog-Bbk_4-WJ.js +1 -0
  9. package/.output/public/assets/api-DUgI6yOI.js +1 -0
  10. package/.output/public/assets/api-keys-CIO9L_wu.js +1 -0
  11. package/.output/public/assets/api-keys-CmkNKOhS.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-BMsI3Bj8.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-BEfQ2_7f.js +11 -0
  22. package/.output/public/assets/input-group-ja_30qaF.js +1 -0
  23. package/.output/public/assets/insights-B0ib9qOE.js +2 -0
  24. package/.output/public/assets/insights-BIMJx-0p.js +1 -0
  25. package/.output/public/assets/insights-CndqcWEj.js +42 -0
  26. package/.output/public/assets/insights-api-B6Ewc-OG.js +1 -0
  27. package/.output/public/assets/insights-usage-rpc-DYEhsCKT.js +1 -0
  28. package/.output/public/assets/insights_.distribution-B26PMy4k.js +2 -0
  29. package/.output/public/assets/insights_.distribution-BBDtqqYS.js +1 -0
  30. package/.output/public/assets/insights_.distribution-DhHmYS8k.js +1 -0
  31. package/.output/public/assets/installations-C3cMuwRx.js +1 -0
  32. package/.output/public/assets/installations-C3yrjwDh.js +2 -0
  33. package/.output/public/assets/installations-D3edlN75.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-0i-gDkeU.js +1 -0
  38. package/.output/public/assets/remote-config-An1ROIOQ.js +6 -0
  39. package/.output/public/assets/remote-config-CoeWgA9i.js +1 -0
  40. package/.output/public/assets/routes-DNoaJIQV.js +2 -0
  41. package/.output/public/assets/routes-cWBDtghZ.js +1 -0
  42. package/.output/public/assets/search-DaTDPW25.js +1 -0
  43. package/.output/public/assets/select-CZMQKT7F.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-D8mxMvCB.css +2 -0
  47. package/.output/public/assets/switch-CU4-fupc.js +1 -0
  48. package/.output/public/assets/table-Gm4qRWwE.js +1 -0
  49. package/.output/public/assets/tabs-R1I8CRjR.js +1 -0
  50. package/.output/public/assets/undo-2-CmrHjwFc.js +1 -0
  51. package/.output/public/assets/useCompositeListItem-BaPeC9ZO.js +1 -0
  52. package/.output/public/assets/valueToPercent-CH8GCHaL.js +1 -0
  53. package/.output/server/__23tanstack-start-server-fn-resolver-DTAqlLRd.mjs +178 -0
  54. package/.output/server/_libs/@base-ui/react+[...].mjs +6450 -2741
  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 +235 -31
  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-BNoVW3Dv.mjs +13 -0
  67. package/.output/server/_ssr/ConsoleFeatureUnavailable-BPFa-cmJ.mjs +58 -0
  68. package/.output/server/_ssr/EventDetails-9CeshfdR.mjs +344 -0
  69. package/.output/server/_ssr/HashValueDisplay-DXZlkcps.mjs +55 -0
  70. package/.output/server/_ssr/InsightsInfo-DLNdJQ0m.mjs +75 -0
  71. package/.output/server/_ssr/InsightsPageHeader-DZGVDgvv.mjs +145 -0
  72. package/.output/server/_ssr/NotFoundPage-mYHHg-2s.mjs +37 -0
  73. package/.output/server/_ssr/{dialog-DUaIgpgd.mjs → alert-dialog-Chkim7vZ.mjs} +6 -83
  74. package/.output/server/_ssr/api-C-Il5-sa.mjs +203 -0
  75. package/.output/server/_ssr/api-keys-01FGqj4d.mjs +5 -0
  76. package/.output/server/_ssr/{api-keys-DJml_XoK.mjs → api-keys-B_f9h7ln.mjs} +48 -10
  77. package/.output/server/_ssr/api-keys-rpc-Cf4YCyFc.mjs +52 -0
  78. package/.output/server/_ssr/api-rpc-DRqwxxT_.mjs +296 -0
  79. package/.output/server/_ssr/{auth-BF8mbAgF.mjs → auth-UP0wXs4i.mjs} +1 -1
  80. package/.output/server/_ssr/{auth-rpc-D_hv52-J.mjs → auth-rpc-D8nFpU9C.mjs} +6 -6
  81. package/.output/server/_ssr/auth.server-COZoXu4i.mjs +5425 -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-Dm2l7w0O.mjs +36 -0
  85. package/.output/server/_ssr/console-access--o9FXikU.mjs +17 -0
  86. package/.output/server/_ssr/console-features-BftSkf3f.mjs +60 -0
  87. package/.output/server/_ssr/console-features-api-CYclUQ4h.mjs +43 -0
  88. package/.output/server/_ssr/console-features-rpc-1WaAkPM_.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-BUuNU-qt.mjs +74 -0
  94. package/.output/server/_ssr/dialog-mfSANqjC.mjs +84 -0
  95. package/.output/server/_ssr/{dist-CyzPaI5v.mjs → dist-wmnTk7w6.mjs} +140 -6
  96. package/.output/server/_ssr/{downloadBundle-B3ert-pY.mjs → downloadBundle-DViuIa9U.mjs} +10 -10
  97. package/.output/server/_ssr/empty-BPayFad3.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-DjZ5t7rH.mjs +189 -0
  101. package/.output/server/_ssr/getBundleChildren-CmjDg6Re.mjs +22 -0
  102. package/.output/server/_ssr/{input-group-Bb8ueylQ.mjs → input-group-Dx-MEkNM.mjs} +3 -52
  103. package/.output/server/_ssr/insights-BopxyJjk.mjs +14 -0
  104. package/.output/server/_ssr/insights-Bvm03d61.mjs +5 -0
  105. package/.output/server/_ssr/insights-CrLAHSDy.mjs +2315 -0
  106. package/.output/server/_ssr/insights-api-Bg8ZV_h_.mjs +122 -0
  107. package/.output/server/_ssr/insights-errors-BjnFUyZj.mjs +34 -0
  108. package/.output/server/_ssr/insights-failures-rpc-tyy5m9Cc.mjs +36 -0
  109. package/.output/server/_ssr/insights-failures-xaa41Buf.mjs +46 -0
  110. package/.output/server/_ssr/{insights-recovery-DSFM-YTL.mjs → insights-recovery-BWQhiZaF.mjs} +9 -2
  111. package/.output/server/_ssr/insights-recovery-rpc-CPJOiJAV.mjs +32 -0
  112. package/.output/server/_ssr/{insights-rpc-DrIQCjpD.mjs → insights-rpc-DoC3hla9.mjs} +22 -14
  113. package/.output/server/_ssr/insights-usage-BpBM0U0c.mjs +29 -0
  114. package/.output/server/_ssr/insights-usage-rpc-CFuTYp3T.mjs +29 -0
  115. package/.output/server/_ssr/insights-usage-rpc-O2ruP4iE.mjs +41 -0
  116. package/.output/server/_ssr/insightsUsage-CzhVjsc8.mjs +56 -0
  117. package/.output/server/_ssr/insights_.distribution-B3BVPD00.mjs +16 -0
  118. package/.output/server/_ssr/insights_.distribution-BMoisxRG.mjs +347 -0
  119. package/.output/server/_ssr/insights_.distribution-BiCcFyrG.mjs +7 -0
  120. package/.output/server/_ssr/{installations-YumqpNpa.mjs → installations-Cx3jIrwl.mjs} +280 -364
  121. package/.output/server/_ssr/installations-DTGPaKXx.mjs +69 -0
  122. package/.output/server/_ssr/installations-osiAuNKr.mjs +5 -0
  123. package/.output/server/_ssr/listReleases-BfUBlCHo.mjs +79 -0
  124. package/.output/server/_ssr/release-adoption-005tQRpo.mjs +55 -0
  125. package/.output/server/_ssr/release-adoption-rpc-BVySDR0L.mjs +41 -0
  126. package/.output/server/_ssr/releaseAdoption-2PJPA09N.mjs +114 -0
  127. package/.output/server/_ssr/releaseManagement-BTCWEY8-.mjs +11 -0
  128. package/.output/server/_ssr/remote-config-CUoAxUMy.mjs +430 -0
  129. package/.output/server/_ssr/remote-config-Cc5P4J-r.mjs +17 -0
  130. package/.output/server/_ssr/remote-config-CjdxcZ9B.mjs +5 -0
  131. package/.output/server/_ssr/remote-config-D2GmbGwI.mjs +2594 -0
  132. package/.output/server/_ssr/remote-config-rpc-kjoZ9PRS.mjs +115 -0
  133. package/.output/server/_ssr/rolldown-runtime-rSIU-vHC.mjs +13 -0
  134. package/.output/server/_ssr/{router-iP95Vqi2.mjs → router-DwGVewL-.mjs} +141 -139
  135. package/.output/server/_ssr/{routes-ivsV2TDu.mjs → routes-C4yxv3JU.mjs} +192 -685
  136. package/.output/server/_ssr/routes-D3_aegLY.mjs +409 -0
  137. package/.output/server/_ssr/runtime.server-BoWf4QhU.mjs +1716 -0
  138. package/.output/server/_ssr/schema-DrOtkRVD.mjs +361 -0
  139. package/.output/server/_ssr/select-DkzM2miy.mjs +107 -0
  140. package/.output/server/_ssr/server-BW0gzB0p.mjs +8325 -0
  141. package/.output/server/_ssr/{createSsrRpc-NHF2PxuK.mjs → sidebar-DPcOijvL.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-BqJ2mAwC.mjs +17 -0
  145. package/.output/server/_ssr/{table-D1mL8fJu.mjs → table-R7RY92q9.mjs} +2 -2
  146. package/.output/server/_ssr/tabs-trDcbRkT.mjs +45 -0
  147. package/.output/server/_ssr/updateFailures-H6pnnYK4.mjs +40 -0
  148. package/.output/server/_ssr/{uuidv7-D0QFkPL_.mjs → uuidv7-ctA_XVZA.mjs} +2 -2
  149. package/.output/server/_tanstack-start-manifest_v-BwInaUTw.mjs +139 -0
  150. package/.output/server/index.mjs +315 -154
  151. package/LICENSE +13 -14
  152. package/README.md +82 -72
  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 +100 -71
  158. package/src/components/ConsoleAccessPage.tsx +5 -1
  159. package/src/components/ConsoleFeatureUnavailable.tsx +80 -0
  160. package/src/components/NotFoundPage.tsx +7 -7
  161. package/src/components/features/FeatureSlots.tsx +103 -0
  162. package/src/components/features/api-keys/apiKeysFeatureUi.tsx +15 -0
  163. package/src/components/features/bundles/BundleMetadata.tsx +8 -5
  164. package/src/components/features/bundles/RolloutCohortsDialog.tsx +1 -1
  165. package/src/components/features/channels/ChannelManagementDialog.tsx +2 -5
  166. package/src/components/features/insights/AppUsage.tsx +366 -0
  167. package/src/components/features/insights/BuiltinBundle.tsx +36 -0
  168. package/src/components/features/insights/ComparedBundlesChart.tsx +310 -0
  169. package/src/components/features/insights/EstimatedCount.tsx +18 -0
  170. package/src/components/features/insights/EventDetails.tsx +400 -39
  171. package/src/components/features/insights/EventHistoryCard.tsx +112 -26
  172. package/src/components/features/insights/EventHistoryList.tsx +2 -2
  173. package/src/components/features/insights/FailureReports.tsx +407 -0
  174. package/src/components/features/insights/InsightsControls.tsx +265 -88
  175. package/src/components/features/insights/InsightsErrorAlert.tsx +14 -1
  176. package/src/components/features/insights/InsightsInfo.tsx +48 -0
  177. package/src/components/features/insights/InsightsOverview.tsx +604 -355
  178. package/src/components/features/insights/InsightsPageHeader.tsx +35 -20
  179. package/src/components/features/insights/InsightsPeriodSelector.tsx +89 -0
  180. package/src/components/features/insights/InstallationHistoryCard.tsx +66 -11
  181. package/src/components/features/insights/InstallationMatchesCard.tsx +1 -1
  182. package/src/components/features/insights/ReleaseActivity.tsx +308 -0
  183. package/src/components/features/insights/ReportingDevicesSummary.tsx +48 -0
  184. package/src/components/features/insights/RollbackButton.tsx +118 -0
  185. package/src/components/features/insights/UpdateFailures.tsx +382 -0
  186. package/src/components/features/insights/insightsFeatureUi.tsx +35 -0
  187. package/src/components/features/releases/ReleaseEditorSheet.tsx +26 -12
  188. package/src/components/features/remote-config/ConditionDialog.tsx +581 -0
  189. package/src/components/features/remote-config/ConditionsCard.tsx +244 -0
  190. package/src/components/features/remote-config/ParameterDialog.tsx +407 -0
  191. package/src/components/features/remote-config/ParametersCard.tsx +244 -0
  192. package/src/components/features/remote-config/PreviewCard.tsx +284 -0
  193. package/src/components/features/remote-config/PublishDialog.tsx +319 -0
  194. package/src/components/features/remote-config/RemoteConfigPage.tsx +353 -0
  195. package/src/components/features/remote-config/RuleSummary.tsx +21 -0
  196. package/src/components/features/remote-config/ValueInput.tsx +148 -0
  197. package/src/components/features/remote-config/VersionsCard.tsx +361 -0
  198. package/src/components/features/remote-config/remoteConfigFeatureUi.tsx +15 -0
  199. package/src/components/features/remote-config/useDateTimeText.ts +16 -0
  200. package/src/components/ui/card.tsx +1 -1
  201. package/src/components/ui/scroll-area.tsx +52 -0
  202. package/src/components/ui/sidebar.tsx +22 -29
  203. package/src/components/ui/tabs.tsx +81 -0
  204. package/src/index.ts +26 -19
  205. package/src/lib/api-keys-api.ts +0 -28
  206. package/src/lib/api-keys-rpc.ts +27 -38
  207. package/src/lib/api-rpc.ts +189 -266
  208. package/src/lib/api.ts +19 -102
  209. package/src/lib/bundle-activity.ts +24 -4
  210. package/src/lib/console-access.ts +20 -0
  211. package/src/lib/console-features-api.ts +68 -0
  212. package/src/lib/console-features-rpc.ts +13 -0
  213. package/src/lib/console-features.ts +97 -0
  214. package/src/lib/insights-api.ts +56 -2
  215. package/src/lib/insights-errors.ts +64 -0
  216. package/src/lib/insights-failures-rpc.ts +36 -0
  217. package/src/lib/insights-failures.ts +130 -0
  218. package/src/lib/insights-recovery-rpc.ts +13 -17
  219. package/src/lib/insights-recovery.ts +10 -27
  220. package/src/lib/insights-retention.ts +21 -0
  221. package/src/lib/insights-rpc.ts +30 -12
  222. package/src/lib/insights-search.ts +93 -0
  223. package/src/lib/insights-usage-rpc.ts +29 -0
  224. package/src/lib/insights-usage.ts +76 -0
  225. package/src/lib/insights-view.ts +34 -5
  226. package/src/lib/release-adoption-api.ts +214 -0
  227. package/src/lib/release-adoption-rpc.ts +49 -0
  228. package/src/lib/release-adoption.ts +164 -0
  229. package/src/lib/remote-config-api.ts +119 -0
  230. package/src/lib/remote-config-draft.ts +652 -0
  231. package/src/lib/remote-config-rpc.ts +196 -0
  232. package/src/lib/scroll-restoration.ts +21 -0
  233. package/src/lib/server/adminInsights.ts +124 -0
  234. package/src/lib/server/auth.server.ts +13 -5
  235. package/src/lib/server/bundleActivity.ts +27 -28
  236. package/src/lib/server/config.server.ts +21 -74
  237. package/src/lib/server/console-feature-apis.ts +70 -0
  238. package/src/lib/server/console-runtime.server.ts +82 -38
  239. package/src/lib/server/downloadBundle.ts +16 -15
  240. package/src/lib/server/failureReports.ts +49 -0
  241. package/src/lib/server/getBundleChildren.ts +31 -122
  242. package/src/lib/server/insightsUsage.ts +63 -0
  243. package/src/lib/server/listReleases.ts +109 -44
  244. package/src/lib/server/releaseAdoption.ts +154 -0
  245. package/src/lib/server/releaseReachability.ts +8 -7
  246. package/src/lib/server/remoteConfig.ts +191 -0
  247. package/src/lib/server/runtime.server.ts +120 -31
  248. package/src/lib/server/updateFailures.ts +65 -0
  249. package/src/routeTree.gen.ts +65 -44
  250. package/src/router.tsx +3 -2
  251. package/src/routes/-installations-search.ts +32 -8
  252. package/src/routes/-releases-search.ts +76 -29
  253. package/src/routes/__root.tsx +10 -4
  254. package/src/routes/api/bundles/$bundleId/download.ts +2 -5
  255. package/src/routes/api-keys.tsx +5 -2
  256. package/src/routes/index.tsx +210 -152
  257. package/src/routes/insights.tsx +133 -18
  258. package/src/routes/insights_.distribution.tsx +422 -0
  259. package/src/routes/installations.tsx +98 -41
  260. package/src/routes/remote-config.tsx +42 -0
  261. package/src/styles.css +9 -0
  262. package/src/vite-internal.ts +15 -3
  263. package/src/vite.ts +2 -0
  264. package/.output/public/assets/InsightsPageHeader-C-Xc2MB9.js +0 -1
  265. package/.output/public/assets/api-keys-C1sgC6ko.js +0 -1
  266. package/.output/public/assets/api-keys-api-LchP65vQ.js +0 -1
  267. package/.output/public/assets/badge-BuMDU0Rf.js +0 -1
  268. package/.output/public/assets/card-BEvx_QKh.js +0 -1
  269. package/.output/public/assets/chart-no-axes-combined-C0G0fQ3J.js +0 -1
  270. package/.output/public/assets/composite-CHTH1Xhh.js +0 -1
  271. package/.output/public/assets/createServerFn-DHc2erub.js +0 -3
  272. package/.output/public/assets/dialog-dyZ1SphZ.js +0 -1
  273. package/.output/public/assets/dist-Bh1gaDfB.js +0 -1
  274. package/.output/public/assets/field-79SVH26s.js +0 -1
  275. package/.output/public/assets/index-BNkxg4jz.js +0 -10
  276. package/.output/public/assets/input-group-BbHfaBzQ.js +0 -1
  277. package/.output/public/assets/insights-D_7uSKfc.js +0 -1
  278. package/.output/public/assets/installations-BzoHWuXw.js +0 -1
  279. package/.output/public/assets/installations-DvjbUqd1.js +0 -2
  280. package/.output/public/assets/lazyRouteComponent-BN0MS05o.js +0 -1
  281. package/.output/public/assets/link-BG06whwB.js +0 -1
  282. package/.output/public/assets/loader-circle-Bbp8LGVC.js +0 -1
  283. package/.output/public/assets/preload-helper-uTix4PVD.js +0 -1
  284. package/.output/public/assets/refresh-cw-DZgiAOMk.js +0 -1
  285. package/.output/public/assets/routes-BFE-oRIT.js +0 -1
  286. package/.output/public/assets/routes-DaPMY31P.js +0 -2
  287. package/.output/public/assets/shield-check-DoIiaaXU.js +0 -1
  288. package/.output/public/assets/signing-BTRhaF5D.js +0 -1
  289. package/.output/public/assets/styles-C7U0oVke.css +0 -2
  290. package/.output/public/assets/table-BBEzJ7Xl.js +0 -1
  291. package/.output/public/assets/useCompositeListItem-BkPDaqyj.js +0 -42
  292. package/.output/server/__23tanstack-start-server-fn-resolver-Dr2ixDgQ.mjs +0 -146
  293. package/.output/server/_ssr/InsightsPageHeader-C5Has8Ry.mjs +0 -60
  294. package/.output/server/_ssr/api-keys-api-CrCZyvnl.mjs +0 -60
  295. package/.output/server/_ssr/api-keys-rpc-CFaNf-q0.mjs +0 -136
  296. package/.output/server/_ssr/api-rpc-B61KL3Eo.mjs +0 -1399
  297. package/.output/server/_ssr/auth.server-DF_shCeq.mjs +0 -47
  298. package/.output/server/_ssr/badge-BgsCP9Dp.mjs +0 -28
  299. package/.output/server/_ssr/bundle-signing-rpc-BBipZnFs.mjs +0 -16
  300. package/.output/server/_ssr/bundle-signing.server-Co_zHdJx.mjs +0 -12
  301. package/.output/server/_ssr/bundleActivity-D3_fIda2.mjs +0 -27
  302. package/.output/server/_ssr/card-DrbxCPtG.mjs +0 -86
  303. package/.output/server/_ssr/chart-qxa-_30a.mjs +0 -162
  304. package/.output/server/_ssr/config-Dv8qLDZ0.mjs +0 -13
  305. package/.output/server/_ssr/config.server-CBr6PDj5.mjs +0 -368
  306. package/.output/server/_ssr/databaseRows-5bCRTxm-.mjs +0 -126
  307. package/.output/server/_ssr/deleteBundle-BAq3JuGr.mjs +0 -66
  308. package/.output/server/_ssr/field-CqNUlqUq.mjs +0 -74
  309. package/.output/server/_ssr/getBundleChildren-COMt16m_.mjs +0 -50
  310. package/.output/server/_ssr/insights-B-DUbksX.mjs +0 -502
  311. package/.output/server/_ssr/insights-recovery-rpc-P71FH66n.mjs +0 -37
  312. package/.output/server/_ssr/insightsContract-fjJDBeEE.mjs +0 -303
  313. package/.output/server/_ssr/insightsRecovery-CqcosG7B.mjs +0 -149
  314. package/.output/server/_ssr/installations-BQrppti7.mjs +0 -29
  315. package/.output/server/_ssr/routes-BDabsmc7.mjs +0 -37
  316. package/.output/server/_ssr/runtime.server-jmZOKIQM.mjs +0 -438
  317. package/.output/server/_ssr/server-p7yrVBfD.mjs +0 -7468
  318. package/.output/server/_ssr/signing-CxCbnFCt.mjs +0 -134
  319. package/.output/server/_ssr/start-DpViQGnt.mjs +0 -4
  320. package/.output/server/_tanstack-start-manifest_v-Cwpu0C9Q.mjs +0 -100
  321. package/src/components/features/bundles/BundleActivityChart.tsx +0 -95
  322. package/src/components/features/bundles/BundleInsightsSummary.tsx +0 -121
  323. package/src/components/features/signing/BundleSigningPage.tsx +0 -139
  324. package/src/lib/bundle-signing-api.ts +0 -14
  325. package/src/lib/bundle-signing-rpc.ts +0 -16
  326. package/src/lib/server/bundle-signing.server.ts +0 -23
  327. package/src/lib/server/deleteBundle.ts +0 -145
  328. package/src/lib/server/insightsHistory.ts +0 -52
  329. package/src/lib/server/insightsRecovery.ts +0 -186
  330. package/src/routes/signing.tsx +0 -37
@@ -1,36 +1,29 @@
1
1
  import { i as __toESM } from "../_runtime.mjs";
2
- import { c as createServerFn } from "./createServerFn-B2hcXoPM.mjs";
3
- import { A as DialogDescription, D as DialogTitle, J as require_react, M as DialogBackdrop, O as DialogPortal, _ as SelectPortal, a as SliderTrack, b as SelectTrigger$1, c as SelectGroup$1, d as SelectItemText, f as SelectItemIndicator, g as SelectPositioner, h as SelectPopup, i as SliderThumb, j as DialogClose, k as DialogPopup, l as SelectScrollUpArrow, m as SelectList, n as SwitchRoot, o as SliderControl, p as SelectItem$1, q as require_jsx_runtime, r as SliderIndicator, s as SliderRoot, t as SwitchThumb, u as SelectScrollDownArrow, v as SelectIcon, w as DialogRoot, x as SelectRoot, y as SelectValue$1 } from "../_libs/@base-ui/react+[...].mjs";
4
- 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, j as ChevronUp, k as CircleOff, n as TriangleAlert, p as Plus, r as Trash2, t as X, w as Funnel, x as List, y as Minus } from "../_libs/lucide-react.mjs";
5
- 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, w as createSsrRpc } from "./createSsrRpc-NHF2PxuK.mjs";
6
- import { m as Link } from "../_libs/@tanstack/react-router+[...].mjs";
7
- import { i as useQueryClient, n as useQuery, t as useMutation } from "../_libs/tanstack__react-query.mjs";
8
- import { a as Card, i as AlertTitle, l as CardHeader, o as CardContent, r as AlertDescription, s as CardDescription, t as Alert, u as CardTitle } from "./card-DrbxCPtG.mjs";
9
- 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-DUaIgpgd.mjs";
10
- import { t as Badge } from "./badge-BgsCP9Dp.mjs";
11
- import { a as FieldLabel, i as FieldGroup, n as FieldDescription, o as Label, r as FieldError, t as Field } from "./field-CqNUlqUq.mjs";
12
- import { a as TableHeader, i as TableHead, n as TableBody, o as TableRow, r as TableCell, t as Table } from "./table-D1mL8fJu.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-DPcOijvL.mjs";
5
+ import { h as Link } from "../_libs/@tanstack/react-router+[...].mjs";
6
+ 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-DjZ5t7rH.mjs";
7
+ 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-Chkim7vZ.mjs";
8
+ 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-mfSANqjC.mjs";
9
+ import { a as TableHeader, i as TableHead, n as TableBody, o as TableRow, r as TableCell, t as Table } from "./table-R7RY92q9.mjs";
13
10
  import { n as toast } from "../_libs/sonner.mjs";
14
- 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";
15
- import { r as extractTimestampFromUUIDv7, t as createUUIDv7 } from "./uuidv7-D0QFkPL_.mjs";
16
- import { a as Area, i as XAxis, r as YAxis, s as CartesianGrid, t as AreaChart } from "../_libs/recharts+[...].mjs";
17
- import { a as ChartTooltipContent, i as ChartTooltip, n as ChartLegend, o as getBundleActivityRpc, r as ChartLegendContent, t as ChartContainer } from "./chart-qxa-_30a.mjs";
18
- import { a as InputGroupInput, n as InputGroup, o as InputGroupText, r as InputGroupAddon, s as Textarea, t as HashValueDisplay } from "./input-group-Bb8ueylQ.mjs";
19
- import { n as updateReleaseFilters, t as Route } from "./routes-BDabsmc7.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-wmnTk7w6.mjs";
12
+ import { r as extractTimestampFromUUIDv7 } from "./uuidv7-ctA_XVZA.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-DkzM2miy.mjs";
15
+ import { a as InputGroupText, i as InputGroupInput, n as InputGroupAddon, o as Textarea, t as InputGroup } from "./input-group-Dx-MEkNM.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-C-Il5-sa.mjs";
17
+ import { t as BundleIdDisplay } from "./BundleIdDisplay-BNoVW3Dv.mjs";
18
+ import { t as HashValueDisplay } from "./HashValueDisplay-DXZlkcps.mjs";
19
+ import { t as Switch$1 } from "./switch-BqJ2mAwC.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-ivsV2TDu.js
21
+ import { a as updateReleaseFilters, i as releaseFilterOf, n as Route, r as hasReleaseFilters, s as useReleaseColumns, t as ReleaseSections } from "./routes-D3_aegLY.mjs";
22
+ //#region node_modules/.nitro/vite/services/ssr/assets/routes-C4yxv3JU.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,355 +252,6 @@ function BundleChildrenPanel({ panelId, bundle, bundles, loading, onDetailClick
259
252
  })
260
253
  });
261
254
  }
262
- function useBundleActivityQuery(inputs) {
263
- const sorted = [...inputs].sort((a, b) => a.releaseId.localeCompare(b.releaseId));
264
- return useQuery({
265
- queryKey: ["bundle-activity", sorted],
266
- queryFn: () => getBundleActivityRpc({ data: sorted }),
267
- enabled: sorted.length > 0,
268
- staleTime: 3e4
269
- });
270
- }
271
- var config = {
272
- active: {
273
- label: "Active",
274
- color: "var(--chart-2)"
275
- },
276
- recoveredInstallations: {
277
- label: "Rollback",
278
- color: "var(--muted-foreground)"
279
- }
280
- };
281
- var formatDate = (ms) => new Intl.DateTimeFormat("en", {
282
- month: "short",
283
- day: "numeric",
284
- timeZone: "UTC"
285
- }).format(ms);
286
- function BundleActivityChart({ series }) {
287
- if (!series) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
288
- className: "flex h-16 items-center justify-center border-t text-xs text-muted-foreground sm:h-20",
289
- children: "No reports in 30 days. Check again after the app reports activity."
290
- });
291
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
292
- className: "border-t pt-3",
293
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartContainer, {
294
- "aria-label": "Bundle activity over 30 days, UTC",
295
- className: "h-32 w-full aspect-auto sm:h-40",
296
- config,
297
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AreaChart, {
298
- accessibilityLayer: true,
299
- data: series.points,
300
- margin: {
301
- left: -16,
302
- right: 4,
303
- top: 4
304
- },
305
- children: [
306
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CartesianGrid, { vertical: false }),
307
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XAxis, {
308
- axisLine: false,
309
- dataKey: "startMs",
310
- minTickGap: 28,
311
- tickFormatter: formatDate,
312
- tickLine: false
313
- }),
314
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(YAxis, {
315
- allowDecimals: false,
316
- axisLine: false,
317
- tickLine: false,
318
- width: 40
319
- }),
320
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartLegend, { content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartLegendContent, {}) }),
321
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltipContent, { labelFormatter: (_, payload) => `${formatDate(payload[0]?.payload.startMs)} · UTC` }) }),
322
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Area, {
323
- dataKey: "active",
324
- fill: "var(--color-active)",
325
- fillOpacity: .12,
326
- isAnimationActive: false,
327
- stroke: "var(--color-active)",
328
- strokeWidth: 2,
329
- type: "linear"
330
- }),
331
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Area, {
332
- dataKey: "recoveredInstallations",
333
- fill: "var(--color-recoveredInstallations)",
334
- fillOpacity: .04,
335
- isAnimationActive: false,
336
- stroke: "var(--color-recoveredInstallations)",
337
- strokeWidth: 1.5,
338
- type: "linear"
339
- })
340
- ]
341
- })
342
- })
343
- });
344
- }
345
- function BundleMovementSummary({ report, loading = false }) {
346
- if (!report) return loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, {
347
- "aria-label": "Loading bundle activity",
348
- className: "h-4 w-32"
349
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
350
- "aria-label": "30-day bundle activity unavailable",
351
- className: "text-sm text-muted-foreground",
352
- children: "—"
353
- });
354
- const series = report.series[0];
355
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
356
- role: "group",
357
- "aria-label": "Bundle activity over 30 days",
358
- 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.",
359
- className: "flex min-w-[140px] items-baseline gap-3 whitespace-nowrap",
360
- children: [
361
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
362
- className: "flex items-baseline gap-1.5",
363
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
364
- className: "text-xs text-muted-foreground",
365
- children: "Active"
366
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
367
- className: "text-sm font-medium tabular-nums",
368
- children: series?.activeInstallations ?? 0
369
- })]
370
- }),
371
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
372
- className: "flex items-baseline gap-1.5",
373
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
374
- className: "text-xs text-muted-foreground",
375
- children: "Rollback"
376
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
377
- className: "text-sm font-medium tabular-nums",
378
- children: series?.recoveredInstallations ?? 0
379
- })]
380
- }),
381
- report.truncated ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
382
- className: "text-xs text-muted-foreground",
383
- children: "Partial"
384
- }) : null
385
- ]
386
- });
387
- }
388
- function BundleInsightsSummary({ input }) {
389
- const query = useBundleActivityQuery([input]);
390
- const report = query.data?.[input.releaseId];
391
- const series = report?.series[0];
392
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, {
393
- className: "px-4 pt-4 pb-3",
394
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
395
- className: "text-sm font-medium",
396
- children: "Activity · 30 days"
397
- })
398
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, {
399
- className: "flex flex-col gap-3 px-4 pb-4",
400
- children: query.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, {
401
- "aria-label": "Loading bundle activity",
402
- className: "h-32 w-full"
403
- }) : query.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
404
- className: "flex items-center justify-between gap-3 text-sm text-muted-foreground",
405
- children: ["Insights unavailable", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
406
- variant: "outline",
407
- size: "sm",
408
- onClick: () => void query.refetch(),
409
- children: "Retry"
410
- })]
411
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
412
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dl", {
413
- className: "grid grid-cols-2 divide-x divide-border/70",
414
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
415
- className: "pr-4",
416
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
417
- className: "text-xs text-muted-foreground",
418
- children: "Active"
419
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
420
- className: "mt-1 text-xl font-semibold tabular-nums",
421
- children: series?.activeInstallations ?? 0
422
- })]
423
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
424
- className: "pl-4",
425
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
426
- className: "text-xs text-muted-foreground",
427
- children: "Rollback · 30d"
428
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
429
- className: "mt-1 text-xl font-semibold tabular-nums",
430
- children: series?.recoveredInstallations ?? 0
431
- })]
432
- })]
433
- }),
434
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BundleActivityChart, { series }),
435
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
436
- className: "text-xs text-muted-foreground",
437
- children: ["Last observed active installations · daily rollbacks", report?.truncated ? " · Partial history" : ""]
438
- })
439
- ] })
440
- })] });
441
- }
442
- var getReleases = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("206547cb1526f961070a989818ca7b9e34f6b2b0e4ab851698c3807fe9fb5e0c"));
443
- var getRelease = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("a6f23116eeaf76166d405e28a95213123025613c6603030894e519015bf48032"));
444
- var updateRelease = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("7ea0186f19f9f2bc2ca4b26e3c59636891cf046957f84287b6783f8d88bd8cb7"));
445
- var preflightRelease = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("b46c95dba95a6a3e8fa5c9d100e3622fa5ae7af4f38e10fb1ed2fa48289a3a8f"));
446
- var deleteRelease = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("d5b58722ce514e3b63a377f736b4823c2011782495442ae4870ed547e392c70b"));
447
- var promoteRelease = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("956539a300d79a7efa191c1cc2d529d62fc4bfd940442548fdbc1404e0d53078"));
448
- var getReleaseCatalogDiagnostics = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("e8c24b7247936f045a145ffd5c177fd0e3df3b52769d67dfbd8d1de491d66396"));
449
- var getConfig = createServerFn().handler(createSsrRpc("51a34c05479a893c7d320bd4cd1604427289d667698c48b9f30a01aabf8a5e68"));
450
- var getChannels = createServerFn().handler(createSsrRpc("79ada05964de8f2123bfcd62b10097d59bf8fd689ef5c7161031e5871d8396c5"));
451
- var createChannel = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("2b9b8d1f49f79a511589617d8d4bfc6094a3acf5264f33651b9569ba66d3f321"));
452
- var deleteChannel = createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("52756dde414919a906bfe83d1ab6d29910c63bcafdb47653d6f1df562d958920"));
453
- createServerFn().handler(createSsrRpc("f8bdca3d0579adb812d6404f55d9261a89cdb025e920b1fcad82883646a5fe9e"));
454
- createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("00ccacb4a0212c83ec29f4d11719046ad91ea8291cfc557d514dbf00d3bd7f5f"));
455
- var getBundle = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("1bd85c2a50e24785cb6abb023a247a9f048f37ddfa85cbb1c57e579563bad013"));
456
- var getBundleChildren = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("4370f1bf70b91f1168d85379d3008449a1bedb915e9878ca4ef89d5f3a80fa7f"));
457
- var getBundleChildCounts = createServerFn({ method: "GET" }).inputValidator((input) => input).handler(createSsrRpc("4ca367070b00f58179a572f0bb8196a4ccdd3881e9b1dbfe33deee0cb6e1f549"));
458
- createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("16cc7c2f080ea5b73e0c6bba815b110dbd7727796036d248ba0d8ae819ddef08"));
459
- createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("3a27ff5679228b86a346b3fe42142e7a5bf0264f73173c0dbe5f07fb37c43cf7"));
460
- createServerFn({ method: "POST" }).inputValidator((input) => input).handler(createSsrRpc("61de3b69779c5ce2a5f5d3c27e2cfaca8fba8f14c8803559b9cd733c456494fa"));
461
- var bundleListQueryKey = ["bundles"];
462
- var releaseListQueryKey = ["releases"];
463
- var queryKeys = {
464
- config: ["config"],
465
- channels: ["channels"],
466
- configLoaded: ["config-loaded"],
467
- bundles: {
468
- all: bundleListQueryKey,
469
- list: (filters) => [...bundleListQueryKey, filters ?? {}]
470
- },
471
- releases: {
472
- all: releaseListQueryKey,
473
- list: (filters) => [...releaseListQueryKey, filters ?? {}]
474
- },
475
- release: (releaseId) => ["release", releaseId],
476
- releaseCatalog: (scopeKey) => ["release-catalog", scopeKey],
477
- bundleChildren: {
478
- all: ["bundle-children"],
479
- list: (baseBundleId) => ["bundle-children", baseBundleId],
480
- counts: (bundleIds) => [
481
- "bundle-children",
482
- "counts",
483
- ...bundleIds
484
- ]
485
- },
486
- bundle: (bundleId) => ["bundle", bundleId]
487
- };
488
- function useConfigQuery() {
489
- return useQuery({
490
- queryKey: queryKeys.config,
491
- queryFn: () => getConfig(),
492
- staleTime: Infinity
493
- });
494
- }
495
- function useChannelsQuery() {
496
- return useQuery({
497
- queryKey: queryKeys.channels,
498
- queryFn: () => getChannels(),
499
- staleTime: Infinity
500
- });
501
- }
502
- function useReleasesQuery(filters) {
503
- return useQuery({
504
- queryKey: queryKeys.releases.list(filters),
505
- queryFn: () => getReleases({ data: filters }),
506
- placeholderData: (previousData) => previousData
507
- });
508
- }
509
- function useReleaseQuery(releaseId) {
510
- return useQuery({
511
- enabled: releaseId.length > 0,
512
- queryFn: () => getRelease({ data: { releaseId } }),
513
- queryKey: queryKeys.release(releaseId)
514
- });
515
- }
516
- function useReleaseCatalogDiagnosticsQuery(scopeKey) {
517
- return useQuery({
518
- enabled: scopeKey.length > 0,
519
- queryFn: () => getReleaseCatalogDiagnostics({ data: { scopeKey } }),
520
- queryKey: queryKeys.releaseCatalog(scopeKey)
521
- });
522
- }
523
- function useBundleQuery(bundleId) {
524
- return useQuery({
525
- queryKey: queryKeys.bundle(bundleId),
526
- queryFn: () => getBundle({ data: { bundleId } }),
527
- staleTime: Infinity,
528
- enabled: !!bundleId
529
- });
530
- }
531
- function useBundleChildrenQuery(baseBundleId) {
532
- return useQuery({
533
- queryKey: queryKeys.bundleChildren.list(baseBundleId),
534
- queryFn: () => getBundleChildren({ data: { baseBundleId } }),
535
- staleTime: Infinity,
536
- enabled: !!baseBundleId
537
- });
538
- }
539
- function useBundleChildCountsQuery(bundleIds) {
540
- const normalizedBundleIds = [...bundleIds].sort((left, right) => left.localeCompare(right));
541
- return useQuery({
542
- queryKey: queryKeys.bundleChildren.counts(normalizedBundleIds),
543
- queryFn: () => getBundleChildCounts({ data: { bundleIds: normalizedBundleIds } }),
544
- staleTime: Infinity,
545
- enabled: normalizedBundleIds.length > 0
546
- });
547
- }
548
- function useCreateChannelMutation() {
549
- const queryClient = useQueryClient();
550
- return useMutation({
551
- mutationFn: (input) => createChannel({ data: input }).then((response) => response.data),
552
- onSuccess: async () => {
553
- await queryClient.invalidateQueries({ queryKey: queryKeys.channels });
554
- }
555
- });
556
- }
557
- function useDeleteChannelMutation() {
558
- const queryClient = useQueryClient();
559
- return useMutation({
560
- mutationFn: (input) => deleteChannel({ data: input }).then((response) => response.data),
561
- onSettled: async () => {
562
- await queryClient.invalidateQueries({ queryKey: queryKeys.channels });
563
- }
564
- });
565
- }
566
- function useUpdateReleaseMutation() {
567
- const queryClient = useQueryClient();
568
- return useMutation({
569
- mutationFn: (input) => updateRelease({ data: input }),
570
- onSuccess: async (_, input) => {
571
- await Promise.all([
572
- queryClient.invalidateQueries({ queryKey: queryKeys.releases.all }),
573
- queryClient.invalidateQueries({ queryKey: queryKeys.release(input.releaseId) }),
574
- queryClient.invalidateQueries({ queryKey: ["release-catalog"] }),
575
- queryClient.invalidateQueries({ queryKey: queryKeys.channels })
576
- ]);
577
- }
578
- });
579
- }
580
- function usePreflightReleaseMutation() {
581
- return useMutation({ mutationFn: (input) => preflightRelease({ data: input }) });
582
- }
583
- function useDeleteReleaseMutation() {
584
- const queryClient = useQueryClient();
585
- return useMutation({
586
- mutationFn: (input) => deleteRelease({ data: input }),
587
- onSuccess: async (_, input) => {
588
- queryClient.removeQueries({ queryKey: queryKeys.release(input.releaseId) });
589
- await Promise.all([
590
- queryClient.invalidateQueries({ queryKey: queryKeys.releases.all }),
591
- queryClient.invalidateQueries({ queryKey: ["release-catalog"] }),
592
- queryClient.invalidateQueries({ queryKey: queryKeys.channels })
593
- ]);
594
- }
595
- });
596
- }
597
- function usePromoteReleaseMutation() {
598
- const queryClient = useQueryClient();
599
- return useMutation({
600
- mutationFn: (input) => promoteRelease({ data: input }),
601
- onSuccess: async () => {
602
- await Promise.all([
603
- queryClient.invalidateQueries({ queryKey: queryKeys.releases.all }),
604
- queryClient.invalidateQueries({ queryKey: ["release"] }),
605
- queryClient.invalidateQueries({ queryKey: ["release-catalog"] }),
606
- queryClient.invalidateQueries({ queryKey: queryKeys.channels })
607
- ]);
608
- }
609
- });
610
- }
611
255
  function ChannelManagementDialog({ open, onOpenChange }) {
612
256
  const [channelName, setChannelName] = (0, import_react.useState)("");
613
257
  const [channelToDelete, setChannelToDelete] = (0, import_react.useState)(null);
@@ -619,13 +263,7 @@ function ChannelManagementDialog({ open, onOpenChange }) {
619
263
  event.preventDefault();
620
264
  if (!normalizedName || createChannel.isPending) return;
621
265
  try {
622
- const result = await createChannel.mutateAsync({
623
- row: {
624
- id: createUUIDv7(),
625
- name: normalizedName
626
- },
627
- onConflict: "returnExisting"
628
- });
266
+ const result = await createChannel.mutateAsync({ name: normalizedName });
629
267
  setChannelName("");
630
268
  if (result.inserted) toast.success(`Channel ${result.row.name} created`);
631
269
  else toast.info(`Channel ${result.row.name} already exists`);
@@ -653,10 +291,10 @@ function ChannelManagementDialog({ open, onOpenChange }) {
653
291
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogContent, {
654
292
  className: "sm:max-w-lg",
655
293
  children: [
656
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogTitle$1, {
294
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogTitle, {
657
295
  className: "flex items-center gap-2",
658
296
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { className: "size-4 text-muted-foreground" }), "Channels"]
659
- }), /* @__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." })] }),
297
+ }), /* @__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." })] }),
660
298
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("form", {
661
299
  onSubmit: handleCreate,
662
300
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FieldGroup, {
@@ -791,7 +429,7 @@ function BundleMetadata({ bundle, release }) {
791
429
  const hbcPatchBaseFileHash = bundle ? getPatchBaseFileHash(bundle) : null;
792
430
  const gitCommitUrl = bundle?.gitCommitHash && isFetched ? getCommitUrl(configData?.console.gitUrl, bundle.gitCommitHash) : null;
793
431
  const target = release.strategy === "APP_VERSION" ? release.target_app_version : release.fingerprint_hash;
794
- if (!(target || bundle?.gitCommitHash || bundle?.fileHash || hbcPatchBaseFileHash || hbcPatchFileHash)) return null;
432
+ if (!(target || bundle?.gitCommitHash || bundle?.manifestFileHash || hbcPatchBaseFileHash || hbcPatchFileHash)) return null;
795
433
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardHeader, {
796
434
  className: "p-4 pb-3",
797
435
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
@@ -829,11 +467,11 @@ function BundleMetadata({ bundle, release }) {
829
467
  }) : null]
830
468
  })
831
469
  }) : null,
832
- bundle?.fileHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Row, {
833
- label: "Bundle hash",
470
+ bundle?.manifestFileHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Row, {
471
+ label: "Manifest hash",
834
472
  value: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HashValueDisplay, {
835
473
  maxLength: 16,
836
- value: bundle.fileHash
474
+ value: bundle.manifestFileHash
837
475
  })
838
476
  }) : null,
839
477
  hbcPatchBaseFileHash ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Row, {
@@ -947,7 +585,7 @@ function RolloutCohortsDialog({ releaseId, rolloutCohortCount, targetCohorts })
947
585
  children: [
948
586
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogHeader, {
949
587
  className: "shrink-0 border-b border-border/70 px-4 py-4",
950
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle$1, { children: "Rolled out cohorts" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogDescription$1, { children: [
588
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, { children: "Rolled out cohorts" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogDescription, { children: [
951
589
  rolloutPercentage,
952
590
  "% includes ",
953
591
  selectedCount,
@@ -968,7 +606,7 @@ function RolloutCohortsDialog({ releaseId, rolloutCohortCount, targetCohorts })
968
606
  })
969
607
  ]
970
608
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
971
- /* @__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: [
609
+ /* @__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: [
972
610
  rolloutPercentage,
973
611
  "% includes ",
974
612
  selectedCount,
@@ -983,165 +621,6 @@ function RolloutCohortsDialog({ releaseId, rolloutCohortCount, targetCohorts })
983
621
  ] })
984
622
  })] });
985
623
  }
986
- function AppleIcon({ className }) {
987
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
988
- "aria-hidden": "true",
989
- viewBox: "0 0 24 24",
990
- xmlns: "http://www.w3.org/2000/svg",
991
- className,
992
- fill: "currentColor",
993
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701" })
994
- });
995
- }
996
- function AndroidIcon({ className }) {
997
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
998
- "aria-hidden": "true",
999
- viewBox: "0 0 24 24",
1000
- xmlns: "http://www.w3.org/2000/svg",
1001
- className,
1002
- fill: "currentColor",
1003
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18.4395 5.5586c-.675 1.1664-1.352 2.3318-2.0274 3.498-.0366-.0155-.0742-.0286-.1113-.043-1.8249-.6957-3.484-.8-4.42-.787-1.8551.0185-3.3544.4643-4.2597.8203-.084-.1494-1.7526-3.021-2.0215-3.4864a1.1451 1.1451 0 0 0-.1406-.1914c-.3312-.364-.9054-.4859-1.379-.203-.475.282-.7136.9361-.3886 1.5019 1.9466 3.3696-.0966-.2158 1.9473 3.3593.0172.031-.4946.2642-1.3926 1.0177C2.8987 12.176.452 14.772 0 18.9902h24c-.119-1.1108-.3686-2.099-.7461-3.0683-.7438-1.9118-1.8435-3.2928-2.7402-4.1836a12.1048 12.1048 0 0 0-2.1309-1.6875c.6594-1.122 1.312-2.2559 1.9649-3.3848.2077-.3615.1886-.7956-.0079-1.1191a1.1001 1.1001 0 0 0-.8515-.5332c-.5225-.0536-.9392.3128-1.0488.5449zm-.0391 8.461c.3944.5926.324 1.3306-.1563 1.6503-.4799.3197-1.188.0985-1.582-.4941-.3944-.5927-.324-1.3307.1563-1.6504.4727-.315 1.1812-.1086 1.582.4941zM7.207 13.5273c.4803.3197.5506 1.0577.1563 1.6504-.394.5926-1.1038.8138-1.584.4941-.48-.3197-.5503-1.0577-.1563-1.6504.4008-.6021 1.1087-.8106 1.584-.4941z" })
1004
- });
1005
- }
1006
- function PlatformIcon({ platform, className }) {
1007
- if (platform === "ios") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppleIcon, { className });
1008
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AndroidIcon, { className });
1009
- }
1010
- var Select$1 = SelectRoot;
1011
- function SelectGroup({ className, ...props }) {
1012
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectGroup$1, {
1013
- "data-slot": "select-group",
1014
- className: cn("scroll-my-1 p-1", className),
1015
- ...props
1016
- });
1017
- }
1018
- function SelectValue({ className, ...props }) {
1019
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue$1, {
1020
- "data-slot": "select-value",
1021
- className: cn("flex flex-1 text-left", className),
1022
- ...props
1023
- });
1024
- }
1025
- function SelectTrigger({ className, size = "default", children, ...props }) {
1026
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectTrigger$1, {
1027
- "data-slot": "select-trigger",
1028
- "data-size": size,
1029
- className: cn("flex w-fit items-center justify-between gap-1.5 rounded-md border border-input bg-input/20 px-2 py-1.5 text-xs/relaxed whitespace-nowrap transition-colors outline-none focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/30 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-7 data-[size=sm]:h-6 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5", className),
1030
- ...props,
1031
- children: [children, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectIcon, { render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, { className: "pointer-events-none size-3.5 text-muted-foreground" }) })]
1032
- });
1033
- }
1034
- function SelectContent({ className, children, side = "bottom", sideOffset = 4, align = "center", alignOffset = 0, alignItemWithTrigger = true, ...props }) {
1035
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectPositioner, {
1036
- side,
1037
- sideOffset,
1038
- align,
1039
- alignOffset,
1040
- alignItemWithTrigger,
1041
- className: "isolate z-50",
1042
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectPopup, {
1043
- "data-slot": "select-content",
1044
- "data-align-trigger": alignItemWithTrigger,
1045
- className: cn("dark relative isolate z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
1046
- ...props,
1047
- children: [
1048
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectScrollUpButton, {}),
1049
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectList, { children }),
1050
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectScrollDownButton, {})
1051
- ]
1052
- })
1053
- }) });
1054
- }
1055
- function SelectItem({ className, children, ...props }) {
1056
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectItem$1, {
1057
- "data-slot": "select-item",
1058
- className: cn("relative flex min-h-7 w-full cursor-default items-center gap-2 rounded-md px-2 py-1 text-xs/relaxed outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-3.5 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", className),
1059
- ...props,
1060
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItemText, {
1061
- className: "flex flex-1 shrink-0 gap-2 whitespace-nowrap",
1062
- children
1063
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItemIndicator, {
1064
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "pointer-events-none absolute right-2 flex items-center justify-center" }),
1065
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "pointer-events-none" })
1066
- })]
1067
- });
1068
- }
1069
- function SelectScrollUpButton({ className, ...props }) {
1070
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectScrollUpArrow, {
1071
- "data-slot": "select-scroll-up-button",
1072
- className: cn("top-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-3.5", className),
1073
- ...props,
1074
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronUp, {})
1075
- });
1076
- }
1077
- function SelectScrollDownButton({ className, ...props }) {
1078
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectScrollDownArrow, {
1079
- "data-slot": "select-scroll-down-button",
1080
- className: cn("bottom-0 z-10 flex w-full cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-3.5", className),
1081
- ...props,
1082
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, {})
1083
- });
1084
- }
1085
- function Sheet({ ...props }) {
1086
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogRoot, {
1087
- "data-slot": "sheet",
1088
- ...props
1089
- });
1090
- }
1091
- function SheetPortal({ ...props }) {
1092
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogPortal, {
1093
- "data-slot": "sheet-portal",
1094
- ...props
1095
- });
1096
- }
1097
- function SheetOverlay({ className, ...props }) {
1098
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogBackdrop, {
1099
- "data-slot": "sheet-overlay",
1100
- 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),
1101
- ...props
1102
- });
1103
- }
1104
- function SheetContent({ className, children, side = "right", showCloseButton = true, ...props }) {
1105
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SheetPortal, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SheetOverlay, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogPopup, {
1106
- "data-slot": "sheet-content",
1107
- "data-side": side,
1108
- 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),
1109
- ...props,
1110
- children: [children, showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogClose, {
1111
- "data-slot": "sheet-close",
1112
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1113
- variant: "ghost",
1114
- className: "absolute top-4 right-4",
1115
- size: "icon-sm"
1116
- }),
1117
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
1118
- className: "sr-only",
1119
- children: "Close"
1120
- })]
1121
- })]
1122
- })] });
1123
- }
1124
- function SheetHeader({ className, ...props }) {
1125
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
1126
- "data-slot": "sheet-header",
1127
- className: cn("flex flex-col gap-1.5 p-6", className),
1128
- ...props
1129
- });
1130
- }
1131
- function SheetTitle({ className, ...props }) {
1132
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogTitle, {
1133
- "data-slot": "sheet-title",
1134
- className: cn("text-sm font-medium text-foreground", className),
1135
- ...props
1136
- });
1137
- }
1138
- function SheetDescription({ className, ...props }) {
1139
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DialogDescription, {
1140
- "data-slot": "sheet-description",
1141
- className: cn("text-xs/relaxed text-muted-foreground", className),
1142
- ...props
1143
- });
1144
- }
1145
624
  function Slider$1({ className, defaultValue, value, min = 0, max = 100, ...props }) {
1146
625
  const _values = Array.isArray(value) ? value : value !== void 0 ? [value] : Array.isArray(defaultValue) ? defaultValue : defaultValue !== void 0 ? [defaultValue] : [min];
1147
626
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SliderRoot, {
@@ -1169,17 +648,6 @@ function Slider$1({ className, defaultValue, value, min = 0, max = 100, ...props
1169
648
  })
1170
649
  });
1171
650
  }
1172
- function Switch$1({ className, ...props }) {
1173
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwitchRoot, {
1174
- "data-slot": "switch",
1175
- 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),
1176
- ...props,
1177
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SwitchThumb, {
1178
- "data-slot": "switch-thumb",
1179
- 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"
1180
- })
1181
- });
1182
- }
1183
651
  var promoteActionItems = [{
1184
652
  label: "Move bundle",
1185
653
  value: "move"
@@ -1262,7 +730,7 @@ function RolloutPercentageInput({ value, onChange }) {
1262
730
  })]
1263
731
  });
1264
732
  }
1265
- function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
733
+ function ReleaseEditorSheet({ channels, onOpenChange, onShowScope, open, releaseId }) {
1266
734
  const releaseQuery = useReleaseQuery(releaseId);
1267
735
  const release = releaseQuery.data;
1268
736
  const bundleQuery = useBundleQuery(release?.bundle_id ?? "");
@@ -1400,7 +868,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1400
868
  maxLength: 18
1401
869
  }), !release.bundle_id ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
1402
870
  className: "text-xs text-foreground",
1403
- children: "Built-in app"
871
+ children: "Built-in bundle"
1404
872
  }) : null]
1405
873
  })]
1406
874
  }),
@@ -1441,10 +909,11 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1441
909
  }) : null, release && draft ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1442
910
  className: "flex flex-col gap-6 px-4 pb-4 sm:px-6 sm:pb-6",
1443
911
  children: [
1444
- channelName ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BundleInsightsSummary, { input: {
912
+ channelName ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReleaseSections, { release: {
1445
913
  platform: release.platform,
1446
914
  channel: channelName,
1447
- releaseId: release.id
915
+ releaseId: release.id,
916
+ builtIn: !release.bundle_id
1448
917
  } }) : null,
1449
918
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
1450
919
  "aria-labelledby": "delivery-settings-heading",
@@ -1624,7 +1093,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1624
1093
  },
1625
1094
  size: "sm",
1626
1095
  variant: "outline",
1627
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { "data-icon": "inline-start" }), "Download bundle"]
1096
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Download, { "data-icon": "inline-start" }), "Download manifest"]
1628
1097
  }) : null,
1629
1098
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1630
1099
  className: "w-full",
@@ -1663,7 +1132,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1663
1132
  className: "sm:col-span-2",
1664
1133
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Artifact ID" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
1665
1134
  className: "mt-1 break-all font-mono text-foreground",
1666
- children: release.bundle_id ?? "Built-in app"
1135
+ children: release.bundle_id ?? "Built-in bundle"
1667
1136
  })]
1668
1137
  }),
1669
1138
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Revision" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
@@ -1687,10 +1156,20 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1687
1156
  })] }),
1688
1157
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1689
1158
  className: "sm:col-span-2",
1690
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Scope key" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
1691
- className: "mt-1 break-all font-mono text-foreground",
1692
- children: release.scope_key
1693
- })]
1159
+ children: [
1160
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", { children: "Scope key" }),
1161
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", {
1162
+ className: "mt-1 break-all font-mono text-foreground",
1163
+ children: release.scope_key
1164
+ }),
1165
+ onShowScope ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1166
+ className: "mt-1 h-auto px-0 text-xs",
1167
+ onClick: () => onShowScope(release.scope_key),
1168
+ size: "sm",
1169
+ variant: "link",
1170
+ children: "Show bundles for this target"
1171
+ }) : null
1172
+ ]
1694
1173
  })
1695
1174
  ]
1696
1175
  }),
@@ -1749,7 +1228,7 @@ function ReleaseEditorSheet({ channels, onOpenChange, open, releaseId }) {
1749
1228
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DialogContent, {
1750
1229
  showCloseButton: !promote.isPending,
1751
1230
  children: [
1752
- /* @__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." })] }),
1231
+ /* @__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." })] }),
1753
1232
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1754
1233
  className: "space-y-4 py-4",
1755
1234
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
@@ -1855,18 +1334,25 @@ function RolloutPercentageBadge({ percentage, className }) {
1855
1334
  });
1856
1335
  }
1857
1336
  var PAGE_SIZE = 20;
1858
- var platformFilterItems = [
1337
+ var platformFilterItems = [{
1338
+ label: "iOS",
1339
+ value: "ios"
1340
+ }, {
1341
+ label: "Android",
1342
+ value: "android"
1343
+ }];
1344
+ var statusFilterItems = [
1859
1345
  {
1860
- label: "All Platforms",
1346
+ label: "Any Status",
1861
1347
  value: "all"
1862
1348
  },
1863
1349
  {
1864
- label: "iOS",
1865
- value: "ios"
1350
+ label: "Enabled",
1351
+ value: "enabled"
1866
1352
  },
1867
1353
  {
1868
- label: "Android",
1869
- value: "android"
1354
+ label: "Disabled",
1355
+ value: "disabled"
1870
1356
  }
1871
1357
  ];
1872
1358
  var dateFormatter = new Intl.DateTimeFormat(void 0, {
@@ -1874,9 +1360,17 @@ var dateFormatter = new Intl.DateTimeFormat(void 0, {
1874
1360
  timeStyle: "short"
1875
1361
  });
1876
1362
  var tableDateFormatter = new Intl.DateTimeFormat(void 0, { dateStyle: "medium" });
1363
+ /**
1364
+ * Opens a bundle from a click anywhere on its row or card, except on a
1365
+ * control inside it, which keeps its own action.
1366
+ */
1367
+ var openOutsideControls = (open) => (event) => {
1368
+ if (event.target instanceof Element && event.target.closest("button, a, input, select, textarea")) return;
1369
+ open();
1370
+ };
1877
1371
  function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, search }) {
1878
- const [targetAppVersion, setTargetAppVersion] = (0, import_react.useState)(search.targetAppVersion ?? "");
1879
- const hasFilters = Boolean(search.bundleId || search.channelId || search.enabled !== void 0 || search.platform || search.targetAppVersion);
1372
+ const hasFilters = hasReleaseFilters(search);
1373
+ const channelSelected = search.channelId !== void 0;
1880
1374
  const channelFilterItems = [{
1881
1375
  label: "All Channels",
1882
1376
  value: "all"
@@ -1884,12 +1378,6 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1884
1378
  label: channel.name,
1885
1379
  value: channel.id
1886
1380
  }))];
1887
- const applyTargetAppVersion = () => {
1888
- onChange({ targetAppVersion: targetAppVersion.trim() || void 0 });
1889
- };
1890
- (0, import_react.useEffect)(() => {
1891
- setTargetAppVersion(search.targetAppVersion ?? "");
1892
- }, [search.targetAppVersion]);
1893
1381
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", {
1894
1382
  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",
1895
1383
  children: [
@@ -1905,40 +1393,6 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1905
1393
  children: "Filters"
1906
1394
  })]
1907
1395
  }),
1908
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1909
- items: platformFilterItems,
1910
- onValueChange: (value) => onChange({ platform: value === "all" ? void 0 : value }),
1911
- value: search.platform ?? "all",
1912
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
1913
- "aria-label": "Platform",
1914
- className: "h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]",
1915
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {})
1916
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [
1917
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1918
- value: "all",
1919
- children: "All Platforms"
1920
- }),
1921
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1922
- value: "ios",
1923
- children: "iOS"
1924
- }),
1925
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1926
- value: "android",
1927
- children: "Android"
1928
- })
1929
- ] }) })]
1930
- }),
1931
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Input, {
1932
- "aria-label": "Target app version",
1933
- className: "h-8 w-full min-w-[132px] text-xs sm:w-[160px]",
1934
- onBlur: applyTargetAppVersion,
1935
- onChange: (event) => setTargetAppVersion(event.target.value),
1936
- onKeyDown: (event) => {
1937
- if (event.key === "Enter") applyTargetAppVersion();
1938
- },
1939
- placeholder: "Target version",
1940
- value: targetAppVersion
1941
- }),
1942
1396
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1943
1397
  items: channelFilterItems,
1944
1398
  onValueChange: (value) => onChange({ channelId: value === null || value === "all" ? void 0 : value }),
@@ -1955,6 +1409,48 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1955
1409
  children: channel.name
1956
1410
  }, channel.id))] }) })]
1957
1411
  }),
1412
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1413
+ disabled: !channelSelected,
1414
+ items: platformFilterItems,
1415
+ onValueChange: (value) => onChange({ platform: value === "android" ? "android" : "ios" }),
1416
+ value: search.platform ?? "ios",
1417
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
1418
+ "aria-label": "Platform",
1419
+ className: "h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]",
1420
+ title: channelSelected ? void 0 : "Choose a channel first",
1421
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {})
1422
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1423
+ value: "ios",
1424
+ children: "iOS"
1425
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1426
+ value: "android",
1427
+ children: "Android"
1428
+ })] }) })]
1429
+ }),
1430
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
1431
+ disabled: !channelSelected && search.scopeKey === void 0,
1432
+ items: statusFilterItems,
1433
+ onValueChange: (value) => onChange({ enabled: value === "enabled" ? true : value === "disabled" ? false : void 0 }),
1434
+ value: search.enabled === void 0 ? "all" : search.enabled ? "enabled" : "disabled",
1435
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
1436
+ "aria-label": "Status",
1437
+ className: "h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]",
1438
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {})
1439
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [
1440
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1441
+ value: "all",
1442
+ children: "Any Status"
1443
+ }),
1444
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1445
+ value: "enabled",
1446
+ children: "Enabled"
1447
+ }),
1448
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
1449
+ value: "disabled",
1450
+ children: "Disabled"
1451
+ })
1452
+ ] }) })]
1453
+ }),
1958
1454
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
1959
1455
  "aria-label": "Manage channels",
1960
1456
  onClick: onManageChannels,
@@ -1974,6 +1470,17 @@ function BundleFilterToolbar({ channels, onChange, onClear, onManageChannels, se
1974
1470
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "size-3" })
1975
1471
  })]
1976
1472
  }) : null,
1473
+ search.scopeKey ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Badge, {
1474
+ className: "max-w-48 gap-1",
1475
+ variant: "secondary",
1476
+ children: ["Target filter", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", {
1477
+ "aria-label": "Clear target filter",
1478
+ className: "rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
1479
+ onClick: () => onChange({ scopeKey: void 0 }),
1480
+ type: "button",
1481
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "size-3" })
1482
+ })]
1483
+ }) : null,
1977
1484
  hasFilters ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Button$1, {
1978
1485
  className: "h-8 px-2 text-xs text-muted-foreground hover:text-foreground sm:ml-auto",
1979
1486
  onClick: onClear,
@@ -2015,7 +1522,7 @@ function BundleEntry({ expanded, onOpen, onToggleExpand, release }) {
2015
1522
  fullOnMobile: true
2016
1523
  }), !release.bundle_id ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
2017
1524
  className: "inline-flex items-center gap-1.5 text-sm",
2018
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RotateCcw, { className: "size-3.5" }), " Built-in app"]
1525
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(RotateCcw, { className: "size-3.5" }), " Built-in bundle"]
2019
1526
  }) : null]
2020
1527
  }),
2021
1528
  operationLabel ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
@@ -2024,9 +1531,9 @@ function BundleEntry({ expanded, onOpen, onToggleExpand, release }) {
2024
1531
  children: operationLabel
2025
1532
  }) : null,
2026
1533
  release.currentlyUnreachable ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
2027
- "aria-label": "Currently unreachable. No catalog segment or cohort selects this bundle first.",
1534
+ "aria-label": "Unreachable: no device gets this bundle with the current delivery settings.",
2028
1535
  className: "inline-flex shrink-0 items-center gap-1 text-xs text-muted-foreground",
2029
- title: "No catalog segment or cohort selects this bundle first with the current delivery settings.",
1536
+ title: "No device gets this bundle with the current delivery settings.",
2030
1537
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CircleOff, { className: "size-3.5" }), "Unreachable"]
2031
1538
  }) : null
2032
1539
  ]
@@ -2071,26 +1578,25 @@ function BundlesPage() {
2071
1578
  const releasesQuery = useReleasesQuery({
2072
1579
  afterReleaseId: search.afterReleaseId,
2073
1580
  beforeReleaseId: search.beforeReleaseId,
2074
- bundleId: search.bundleId,
2075
- channelId: search.channelId,
2076
- enabled: search.enabled,
2077
- limit: PAGE_SIZE,
2078
- page: search.page,
2079
- platform: search.platform,
2080
- targetAppVersion: search.targetAppVersion
1581
+ filter: releaseFilterOf(search),
1582
+ limit: PAGE_SIZE
2081
1583
  });
2082
1584
  const channels = useChannelsQuery().data ?? [];
2083
1585
  const releases = releasesQuery.data?.data ?? [];
2084
1586
  const patchCountsByBundleId = useBundleChildCountsQuery(Array.from(new Set(releases.flatMap((release) => release.bundle_id ? [release.bundle_id] : [])))).data ?? {};
2085
- const pagination = releasesQuery.data?.pagination;
2086
- const activityQuery = useBundleActivityQuery(releases.flatMap((release) => {
1587
+ const nextCursor = releasesQuery.data?.next;
1588
+ const previousCursor = releasesQuery.data?.previous;
1589
+ const slotReleases = releases.flatMap((release) => {
2087
1590
  const channel = channels.find((item) => item.id === release.channel_id)?.name;
2088
1591
  return channel ? [{
2089
1592
  releaseId: release.id,
2090
1593
  platform: release.platform,
2091
- channel
1594
+ channel,
1595
+ builtIn: !release.bundle_id
2092
1596
  }] : [];
2093
- }));
1597
+ });
1598
+ const featureColumns = useReleaseColumns();
1599
+ const columnCount = 10 + featureColumns.length;
2094
1600
  const channelNames = new Map(channels.map((channel) => [channel.id, channel.name]));
2095
1601
  (0, import_react.useEffect)(() => {
2096
1602
  if (expandedReleaseId && !releases.some((release) => release.id === expandedReleaseId)) setExpandedReleaseId(void 0);
@@ -2113,26 +1619,25 @@ function BundlesPage() {
2113
1619
  }
2114
1620
  changeFilters({ bundleId: bundle.id });
2115
1621
  };
2116
- const currentPage = pagination?.currentPage ?? 1;
2117
- const startEntry = releases.length === 0 ? 0 : (currentPage - 1) * PAGE_SIZE + 1;
2118
- const endEntry = startEntry === 0 ? 0 : startEntry + releases.length - 1;
2119
- const previousPage = currentPage - 1;
2120
- const firstReleaseId = releases[0]?.id;
2121
- const lastReleaseId = releases.at(-1)?.id;
2122
- const previousSearch = pagination?.hasPreviousPage && firstReleaseId ? {
1622
+ const onLaterPage = search.afterReleaseId !== void 0 || search.beforeReleaseId !== void 0;
1623
+ const previousSearch = previousCursor ? {
2123
1624
  ...search,
2124
- afterReleaseId: firstReleaseId,
1625
+ afterReleaseId: previousCursor,
2125
1626
  beforeReleaseId: void 0,
2126
- page: previousPage > 1 ? previousPage : void 0,
2127
1627
  releaseId: void 0
2128
1628
  } : null;
2129
- const nextSearch = pagination?.hasNextPage && lastReleaseId ? {
1629
+ const nextSearch = nextCursor ? {
2130
1630
  ...search,
2131
1631
  afterReleaseId: void 0,
2132
- beforeReleaseId: lastReleaseId,
2133
- page: currentPage + 1,
1632
+ beforeReleaseId: nextCursor,
2134
1633
  releaseId: void 0
2135
1634
  } : null;
1635
+ const newestSearch = {
1636
+ ...search,
1637
+ afterReleaseId: void 0,
1638
+ beforeReleaseId: void 0,
1639
+ releaseId: void 0
1640
+ };
2136
1641
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
2137
1642
  className: "flex h-svh min-h-0 min-w-0 flex-col",
2138
1643
  children: [
@@ -2165,7 +1670,13 @@ function BundlesPage() {
2165
1670
  const isExpanded = expandedReleaseId === release.id;
2166
1671
  const panelId = `bundle-lineage-panel-${release.id}`;
2167
1672
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("article", {
2168
- 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"),
1673
+ "aria-label": `Bundle ${release.id}`,
1674
+ 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"),
1675
+ "data-state": search.releaseId === release.id ? "selected" : void 0,
1676
+ onClick: openOutsideControls(() => go({
1677
+ ...search,
1678
+ releaseId: release.id
1679
+ }, false)),
2169
1680
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
2170
1681
  className: "flex items-start justify-between gap-3",
2171
1682
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(BundleEntry, {
@@ -2226,16 +1737,16 @@ function BundlesPage() {
2226
1737
  children: patchCount === void 0 ? "Checking" : patchCount > 0 ? `${patchCount} ${patchCount === 1 ? "patch" : "patches"}` : "—"
2227
1738
  })]
2228
1739
  }),
2229
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
1740
+ featureColumns.map(({ Cell, feature, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
2230
1741
  className: "col-span-2 rounded-md bg-muted/40 p-3",
2231
1742
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
2232
1743
  className: "mb-2 text-muted-foreground",
2233
- children: "Activity · 30d"
2234
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BundleMovementSummary, {
2235
- report: activityQuery.data?.[release.id],
2236
- loading: activityQuery.isFetching
1744
+ children: label
1745
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cell, {
1746
+ releaseId: release.id,
1747
+ releases: slotReleases
2237
1748
  }) })]
2238
- }),
1749
+ }, feature)),
2239
1750
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
2240
1751
  className: "col-span-2 flex flex-wrap items-center gap-2 rounded-md bg-muted/40 p-3",
2241
1752
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReleaseStateBadge, { release }), release.should_force_update ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
@@ -2244,7 +1755,7 @@ function BundlesPage() {
2244
1755
  }) : null]
2245
1756
  }),
2246
1757
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
2247
- className: "col-span-2 grid gap-2 rounded-md border bg-background/80 p-3",
1758
+ className: "col-span-2 grid grid-cols-1 gap-2 rounded-md border bg-background/80 p-3",
2248
1759
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
2249
1760
  className: "flex items-start justify-between gap-3",
2250
1761
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("dt", {
@@ -2274,7 +1785,7 @@ function BundlesPage() {
2274
1785
  }) : null] }, release.id);
2275
1786
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
2276
1787
  className: "p-8 text-center text-sm text-muted-foreground",
2277
- 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."
1788
+ 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."
2278
1789
  })
2279
1790
  }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table, {
2280
1791
  className: "min-w-max",
@@ -2291,13 +1802,13 @@ function BundlesPage() {
2291
1802
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Enabled" }),
2292
1803
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Force update" }),
2293
1804
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Rollout" }),
2294
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Activity · 30d" }),
1805
+ featureColumns.map(({ feature, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: label }, feature)),
2295
1806
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Message" }),
2296
1807
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Created" })
2297
1808
  ]
2298
1809
  })
2299
1810
  }), /* @__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, {
2300
- colSpan: 11,
1811
+ colSpan: columnCount,
2301
1812
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, { className: "h-8 w-full" })
2302
1813
  }) }, index)) : releases.map((release) => {
2303
1814
  const isExpanded = expandedReleaseId === release.id;
@@ -2306,13 +1817,10 @@ function BundlesPage() {
2306
1817
  "aria-label": `Open bundle ${release.id}`,
2307
1818
  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"),
2308
1819
  "data-state": search.releaseId === release.id ? "selected" : void 0,
2309
- onClick: (event) => {
2310
- if (event.target instanceof Element && event.target.closest("button, a, input, select, textarea")) return;
2311
- go({
2312
- ...search,
2313
- releaseId: release.id
2314
- }, false);
2315
- },
1820
+ onClick: openOutsideControls(() => go({
1821
+ ...search,
1822
+ releaseId: release.id
1823
+ }, false)),
2316
1824
  onKeyDown: (event) => {
2317
1825
  if (event.target !== event.currentTarget || event.key !== "Enter" && event.key !== " ") return;
2318
1826
  event.preventDefault();
@@ -2391,10 +1899,10 @@ function BundlesPage() {
2391
1899
  })]
2392
1900
  }) }),
2393
1901
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RolloutPercentageBadge, { percentage: release.rollout_cohort_count / 10 }) }),
2394
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BundleMovementSummary, {
2395
- report: activityQuery.data?.[release.id],
2396
- loading: activityQuery.isFetching
2397
- }) }),
1902
+ featureColumns.map(({ Cell, feature }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Cell, {
1903
+ releaseId: release.id,
1904
+ releases: slotReleases
1905
+ }) }, feature)),
2398
1906
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2399
1907
  className: "text-sm text-muted-foreground",
2400
1908
  title: release.message ?? void 0,
@@ -2410,7 +1918,7 @@ function BundlesPage() {
2410
1918
  className: "hover:bg-transparent",
2411
1919
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2412
1920
  className: "border-t-0 p-0",
2413
- colSpan: 11,
1921
+ colSpan: columnCount,
2414
1922
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReleaseBundleChildrenPanel, {
2415
1923
  onDetailClick: openChildBundle,
2416
1924
  panelId,
@@ -2420,8 +1928,8 @@ function BundlesPage() {
2420
1928
  }) : null] }, release.id);
2421
1929
  }), !releasesQuery.isPending && releases.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
2422
1930
  className: "h-40 text-center text-muted-foreground",
2423
- colSpan: 11,
2424
- 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."
1931
+ colSpan: columnCount,
1932
+ 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."
2425
1933
  }) }) : null] })]
2426
1934
  })
2427
1935
  }), !releasesQuery.isError && !releasesQuery.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("nav", {
@@ -2430,29 +1938,27 @@ function BundlesPage() {
2430
1938
  children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
2431
1939
  className: "text-xs font-medium text-muted-foreground",
2432
1940
  children: [
2433
- "Showing ",
2434
1941
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2435
1942
  className: "text-foreground",
2436
- children: startEntry
1943
+ children: releases.length
2437
1944
  }),
2438
- " to",
2439
1945
  " ",
2440
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2441
- className: "text-foreground",
2442
- children: endEntry
2443
- }),
2444
- " entries"
1946
+ releases.length === 1 ? "entry" : "entries",
1947
+ ", newest first"
2445
1948
  ]
2446
1949
  }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
2447
1950
  className: "flex flex-wrap items-center gap-3 sm:justify-end",
2448
1951
  children: [
2449
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
2450
- className: "text-xs font-medium text-muted-foreground",
2451
- children: ["Page ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
2452
- className: "text-foreground",
2453
- children: currentPage
2454
- })]
2455
- }),
1952
+ onLaterPage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Link, {
1953
+ className: buttonVariants({
1954
+ className: "h-8 flex-1 px-3 text-xs sm:flex-none",
1955
+ size: "sm",
1956
+ variant: "ghost"
1957
+ }),
1958
+ search: newestSearch,
1959
+ to: "/",
1960
+ children: "Newest"
1961
+ }) : null,
2456
1962
  previousSearch ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
2457
1963
  className: buttonVariants({
2458
1964
  className: "h-8 flex-1 px-3 text-xs sm:flex-none",
@@ -2495,6 +2001,7 @@ function BundlesPage() {
2495
2001
  ...search,
2496
2002
  releaseId: void 0
2497
2003
  }, false),
2004
+ onShowScope: (scopeKey) => changeFilters({ scopeKey }),
2498
2005
  open: Boolean(search.releaseId),
2499
2006
  releaseId: search.releaseId ?? ""
2500
2007
  }),