@hot-updater/console 1.0.0-rc.9 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/ConsoleFeatureUnavailable-jB4Loglh.js +1 -0
  3. package/.output/public/assets/EventDetails-B6yUsyNA.js +1 -0
  4. package/.output/public/assets/HashValueDisplay-BFX_kY3-.js +1 -0
  5. package/.output/public/assets/InsightsInfo-BNO0WznZ.js +1 -0
  6. package/.output/public/assets/InsightsPageHeader-B892oVml.js +1 -0
  7. package/.output/public/assets/NotFoundPage-DIqCpWa3.js +1 -0
  8. package/.output/public/assets/alert-dialog-Bbk_4-WJ.js +1 -0
  9. package/.output/public/assets/api-DCM0wr6O.js +1 -0
  10. package/.output/public/assets/api-keys-CIO9L_wu.js +1 -0
  11. package/.output/public/assets/api-keys-DVTL_--f.js +1 -0
  12. package/.output/public/assets/arrow-left-CnMYpqB7.js +1 -0
  13. package/.output/public/assets/arrow-up-right-BtffZA6e.js +1 -0
  14. package/.output/public/assets/chevron-right-BqD5wtFb.js +1 -0
  15. package/.output/public/assets/clipboard-DS9ucUQL.js +1 -0
  16. package/.output/public/assets/console-features-api-BH5m_PtQ.js +1 -0
  17. package/.output/public/assets/dialog-Bqbb7B0N.js +1 -0
  18. package/.output/public/assets/dist-LxKJB-Vu.js +1 -0
  19. package/.output/public/assets/empty-CuT2UhFp.js +1 -0
  20. package/.output/public/assets/field-BBDpjIqu.js +1 -0
  21. package/.output/public/assets/index-6o51GkFe.js +11 -0
  22. package/.output/public/assets/input-group-ja_30qaF.js +1 -0
  23. package/.output/public/assets/insights-CmraDzQh.js +1 -0
  24. package/.output/public/assets/insights-CxZ2GCYV.js +2 -0
  25. package/.output/public/assets/insights-api-BigAU9sZ.js +1 -0
  26. package/.output/public/assets/insights-usage-rpc-DYEhsCKT.js +1 -0
  27. package/.output/public/assets/insights-vNRCrfnS.js +42 -0
  28. package/.output/public/assets/insights_.distribution-ChOerfJt.js +1 -0
  29. package/.output/public/assets/insights_.distribution-D-e4iga8.js +1 -0
  30. package/.output/public/assets/insights_.distribution-DZtkibX1.js +2 -0
  31. package/.output/public/assets/installations-BazSJXE0.js +2 -0
  32. package/.output/public/assets/installations-ClHTqdAO.js +1 -0
  33. package/.output/public/assets/installations-DpKsBuHi.js +1 -0
  34. package/.output/public/assets/key-round-wS_SIZ6b.js +1 -0
  35. package/.output/public/assets/list-CgrYiadM.js +1 -0
  36. package/.output/public/assets/refresh-cw-BYgoNCco.js +1 -0
  37. package/.output/public/assets/remote-config-BWwHOkCK.js +1 -0
  38. package/.output/public/assets/remote-config-Br56BODb.js +6 -0
  39. package/.output/public/assets/remote-config-CXOi0LRu.js +1 -0
  40. package/.output/public/assets/routes-B88Erkpk.js +2 -0
  41. package/.output/public/assets/routes-CfzsAleC.js +1 -0
  42. package/.output/public/assets/search-DaTDPW25.js +1 -0
  43. package/.output/public/assets/select-BZZBXMkr.js +1 -0
  44. package/.output/public/assets/sidebar-DNVyJPfX.js +3 -0
  45. package/.output/public/assets/smartphone-DpTFgtKf.js +1 -0
  46. package/.output/public/assets/styles-DTGEAJFv.css +2 -0
  47. package/.output/public/assets/switch-DZ1TPwx-.js +1 -0
  48. package/.output/public/assets/table-Gm4qRWwE.js +1 -0
  49. package/.output/public/assets/tabs-C7FOEjFC.js +1 -0
  50. package/.output/public/assets/undo-2-CmrHjwFc.js +1 -0
  51. package/.output/public/assets/useCompositeListItem-9E4pj_CH.js +1 -0
  52. package/.output/public/assets/valueToPercent-CH8GCHaL.js +1 -0
  53. package/.output/server/__23tanstack-start-server-fn-resolver-BpRlos5Q.mjs +170 -0
  54. package/.output/server/_libs/@base-ui/react+[...].mjs +4389 -4207
  55. package/.output/server/_libs/@tanstack/react-router+[...].mjs +3802 -4022
  56. package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +140 -97
  57. package/.output/server/_libs/lucide-react.mjs +221 -9
  58. package/.output/server/_libs/next-themes.mjs +1 -1
  59. package/.output/server/_libs/react-redux+[...].mjs +1 -1
  60. package/.output/server/_libs/recharts+[...].mjs +483 -901
  61. package/.output/server/_libs/sonner.mjs +1 -1
  62. package/.output/server/_libs/tanstack__history.mjs +68 -41
  63. package/.output/server/_libs/tanstack__query-core.mjs +2010 -309
  64. package/.output/server/_libs/tanstack__react-query.mjs +448 -21
  65. package/.output/server/_libs/verkit.mjs +102 -1
  66. package/.output/server/_ssr/BundleIdDisplay-x94o9rlU.mjs +13 -0
  67. package/.output/server/_ssr/ConsoleFeatureUnavailable-ldW8v8-q.mjs +58 -0
  68. package/.output/server/_ssr/EventDetails-Q8kfj9Nr.mjs +344 -0
  69. package/.output/server/_ssr/{HashValueDisplay-CyMmr0O9.mjs → HashValueDisplay-n1GholGS.mjs} +3 -3
  70. package/.output/server/_ssr/InsightsInfo-DuJFatQO.mjs +75 -0
  71. package/.output/server/_ssr/InsightsPageHeader-BSUX3Ye9.mjs +145 -0
  72. package/.output/server/_ssr/NotFoundPage-DZzOOzS3.mjs +37 -0
  73. package/.output/server/_ssr/{dialog-CKvQ4VIE.mjs → alert-dialog-C43Doa0I.mjs} +6 -83
  74. package/.output/server/_ssr/{api-keys-CzZ7Ont4.mjs → api-keys-B4sYm8dM.mjs} +48 -9
  75. package/.output/server/_ssr/api-keys-CEnM9fqG.mjs +5 -0
  76. package/.output/server/_ssr/api-keys-rpc-BIFuUgMt.mjs +52 -0
  77. package/.output/server/_ssr/api-oZjRn9tP.mjs +186 -0
  78. package/.output/server/_ssr/api-rpc-BNiFRRK8.mjs +240 -0
  79. package/.output/server/_ssr/{auth-BF8mbAgF.mjs → auth-UP0wXs4i.mjs} +1 -1
  80. package/.output/server/_ssr/{auth-rpc-DH6Bhwcz.mjs → auth-rpc-DnZqYxyq.mjs} +6 -6
  81. package/.output/server/_ssr/auth.server-DFpyxRDd.mjs +5374 -0
  82. package/.output/server/_ssr/bundleActivity-M5gzBFNg.mjs +18 -0
  83. package/.output/server/_ssr/config-WVX4IxSR.mjs +15 -0
  84. package/.output/server/_ssr/config.server-DskXCAyI.mjs +35 -0
  85. package/.output/server/_ssr/console-access-BJfAXknd.mjs +17 -0
  86. package/.output/server/_ssr/console-features-Oz0q20jJ.mjs +61 -0
  87. package/.output/server/_ssr/console-features-api-C9kiKvaV.mjs +43 -0
  88. package/.output/server/_ssr/console-features-rpc-P0GL7Z-R.mjs +19 -0
  89. package/.output/server/_ssr/{createServerFn-B2hcXoPM.mjs → createMiddleware-Cm6Tn0_Y.mjs} +67 -56
  90. package/.output/server/_ssr/{createServerRpc-DB29C_5p.mjs → createServerRpc-RLR4H-Fn.mjs} +2 -2
  91. package/.output/server/_ssr/databaseConfig-C5SkAyUy.mjs +5 -0
  92. package/.output/server/_ssr/{databaseJsonValue-d6I3nAS4.mjs → databaseJsonValue-Csbuzc9Q.mjs} +28 -5
  93. package/.output/server/_ssr/databaseRows-CPphvbag.mjs +73 -0
  94. package/.output/server/_ssr/dialog-BbYDMjdC.mjs +84 -0
  95. package/.output/server/_ssr/{dist-CyzPaI5v.mjs → dist-CbQbBIw-.mjs} +140 -7
  96. package/.output/server/_ssr/{downloadBundle-CI7JUKvC.mjs → downloadBundle-CZysjmNW.mjs} +10 -10
  97. package/.output/server/_ssr/empty-CVLGfxuu.mjs +60 -0
  98. package/.output/server/_ssr/{empty-plugin-adapters-B5QvGpEl.mjs → empty-plugin-adapters-CPtwX8a7.mjs} +1 -1
  99. package/.output/server/_ssr/failureReports-DKDhVsXA.mjs +33 -0
  100. package/.output/server/_ssr/field-asw83X0v.mjs +189 -0
  101. package/.output/server/_ssr/getBundleChildren-Cv9iz1As.mjs +22 -0
  102. package/.output/server/_ssr/{input-group-BrGSjz4S.mjs → input-group-CuYJHosb.mjs} +2 -2
  103. package/.output/server/_ssr/insights-B55FG5fm.mjs +14 -0
  104. package/.output/server/_ssr/insights-CWnHIFUV.mjs +5 -0
  105. package/.output/server/_ssr/insights-CpLpedFZ.mjs +2315 -0
  106. package/.output/server/_ssr/insights-api-sjws23WF.mjs +122 -0
  107. package/.output/server/_ssr/insights-errors-BjnFUyZj.mjs +34 -0
  108. package/.output/server/_ssr/insights-failures-rpc-BvbWvqNf.mjs +36 -0
  109. package/.output/server/_ssr/insights-failures-xaa41Buf.mjs +46 -0
  110. package/.output/server/_ssr/insights-recovery-BWQhiZaF.mjs +28 -0
  111. package/.output/server/_ssr/insights-recovery-rpc-GiYXdkaY.mjs +32 -0
  112. package/.output/server/_ssr/{insights-rpc-DDKmIrpV.mjs → insights-rpc-DP_8Rmz4.mjs} +22 -14
  113. package/.output/server/_ssr/insights-usage-BpBM0U0c.mjs +29 -0
  114. package/.output/server/_ssr/insights-usage-rpc-BiolgB8e.mjs +29 -0
  115. package/.output/server/_ssr/insights-usage-rpc-KStL0zOx.mjs +41 -0
  116. package/.output/server/_ssr/insightsUsage-CzhVjsc8.mjs +56 -0
  117. package/.output/server/_ssr/insights_.distribution-CVrnbP3R.mjs +7 -0
  118. package/.output/server/_ssr/insights_.distribution-D2HaNTAA.mjs +16 -0
  119. package/.output/server/_ssr/{insights_.distribution-cIsU-kHG.mjs → insights_.distribution-DN9pR422.mjs} +50 -22
  120. package/.output/server/_ssr/installations-BHmbbnH8.mjs +5 -0
  121. package/.output/server/_ssr/{installations-C5anhyP0.mjs → installations-BSCmFq8Q.mjs} +279 -367
  122. package/.output/server/_ssr/installations-DD1g__Nc.mjs +69 -0
  123. package/.output/server/_ssr/listReleases-BfUBlCHo.mjs +79 -0
  124. package/.output/server/_ssr/plugins-BaD1slHx.mjs +2086 -0
  125. package/.output/server/_ssr/release-adoption-005tQRpo.mjs +55 -0
  126. package/.output/server/_ssr/release-adoption-rpc-BsstqxUp.mjs +41 -0
  127. package/.output/server/_ssr/releaseAdoption-CtOFkwli.mjs +114 -0
  128. package/.output/server/_ssr/releaseManagement-DFMUnDF5.mjs +11 -0
  129. package/.output/server/_ssr/remote-config-C2Ee8lXO.mjs +5 -0
  130. package/.output/server/_ssr/remote-config-Dv1ccMo-.mjs +17 -0
  131. package/.output/server/_ssr/remote-config-of0lGQH8.mjs +2648 -0
  132. package/.output/server/_ssr/remote-config-rpc-BzX31mUS.mjs +115 -0
  133. package/.output/server/_ssr/rolldown-runtime-rSIU-vHC.mjs +13 -0
  134. package/.output/server/_ssr/{router-BuanSsRI.mjs → router-D8NuoJ_I.mjs} +107 -134
  135. package/.output/server/_ssr/{routes-DY-vqU6R.mjs → routes-DgvnFqDy.mjs} +195 -429
  136. package/.output/server/_ssr/routes-V8sDybGf.mjs +409 -0
  137. package/.output/server/_ssr/runtime.server-De0QVWc9.mjs +104 -0
  138. package/.output/server/_ssr/schema-BiAVyEj2.mjs +361 -0
  139. package/.output/server/_ssr/{select-DD2szs3Y.mjs → select-t3iXRwc9.mjs} +3 -3
  140. package/.output/server/_ssr/server-h4VxnExB.mjs +8325 -0
  141. package/.output/server/_ssr/{createSsrRpc-CdlfejmI.mjs → sidebar-DJcErBMo.mjs} +107 -47
  142. package/.output/server/_ssr/ssr.mjs +1 -1
  143. package/.output/server/_ssr/start-BfFbHKMK.mjs +4 -0
  144. package/.output/server/_ssr/switch-E-btwMGt.mjs +43 -0
  145. package/.output/server/_ssr/{table-CTj6n-4F.mjs → table-37Dd23TN.mjs} +2 -2
  146. package/.output/server/_ssr/tabs-DEFnTm95.mjs +45 -0
  147. package/.output/server/_ssr/updateFailures-H6pnnYK4.mjs +40 -0
  148. package/.output/server/_ssr/{uuidv7-D0QFkPL_.mjs → uuidv7-C88s9jWF.mjs} +2 -2
  149. package/.output/server/_tanstack-start-manifest_v-55AGsehh.mjs +139 -0
  150. package/.output/server/index.mjs +309 -211
  151. package/LICENSE +13 -14
  152. package/README.md +80 -71
  153. package/lib/index.d.mts +23 -11
  154. package/lib/vite-internal.mjs +13 -3
  155. package/lib/vite.d.mts +2 -0
  156. package/package.json +14 -14
  157. package/src/components/AppSidebar.tsx +69 -74
  158. package/src/components/ConsoleFeatureUnavailable.tsx +80 -0
  159. package/src/components/NotFoundPage.tsx +7 -7
  160. package/src/components/features/FeatureSlots.tsx +103 -0
  161. package/src/components/features/api-keys/apiKeysFeatureUi.tsx +15 -0
  162. package/src/components/features/bundles/BundleMetadata.tsx +8 -5
  163. package/src/components/features/bundles/RolloutCohortsDialog.tsx +1 -1
  164. package/src/components/features/channels/ChannelManagementDialog.tsx +8 -6
  165. package/src/components/features/insights/AppUsage.tsx +41 -14
  166. package/src/components/features/insights/BuiltinBundle.tsx +36 -0
  167. package/src/components/features/insights/ComparedBundlesChart.tsx +310 -0
  168. package/src/components/features/insights/EstimatedCount.tsx +18 -0
  169. package/src/components/features/insights/EventDetails.tsx +390 -26
  170. package/src/components/features/insights/EventHistoryCard.tsx +111 -25
  171. package/src/components/features/insights/EventHistoryList.tsx +1 -1
  172. package/src/components/features/insights/FailureReports.tsx +407 -0
  173. package/src/components/features/insights/InsightsControls.tsx +240 -142
  174. package/src/components/features/insights/InsightsErrorAlert.tsx +14 -1
  175. package/src/components/features/insights/InsightsOverview.tsx +601 -403
  176. package/src/components/features/insights/InsightsPageHeader.tsx +19 -14
  177. package/src/components/features/insights/InsightsPeriodSelector.tsx +67 -12
  178. package/src/components/features/insights/InstallationHistoryCard.tsx +65 -10
  179. package/src/components/features/insights/InstallationMatchesCard.tsx +1 -1
  180. package/src/components/features/insights/ReleaseActivity.tsx +308 -0
  181. package/src/components/features/insights/ReportingDevicesSummary.tsx +13 -13
  182. package/src/components/features/insights/RollbackButton.tsx +118 -0
  183. package/src/components/features/insights/UpdateFailures.tsx +382 -0
  184. package/src/components/features/insights/insightsFeatureUi.tsx +35 -0
  185. package/src/components/features/releases/ReleaseEditorSheet.tsx +27 -13
  186. package/src/components/features/remote-config/ConditionDialog.tsx +592 -0
  187. package/src/components/features/remote-config/ConditionsCard.tsx +247 -0
  188. package/src/components/features/remote-config/ParameterDialog.tsx +426 -0
  189. package/src/components/features/remote-config/ParametersCard.tsx +254 -0
  190. package/src/components/features/remote-config/PreviewCard.tsx +284 -0
  191. package/src/components/features/remote-config/PublishDialog.tsx +325 -0
  192. package/src/components/features/remote-config/RemoteConfigPage.tsx +353 -0
  193. package/src/components/features/remote-config/RuleSummary.tsx +21 -0
  194. package/src/components/features/remote-config/ValueInput.tsx +151 -0
  195. package/src/components/features/remote-config/VersionsCard.tsx +384 -0
  196. package/src/components/features/remote-config/remoteConfigFeatureUi.tsx +15 -0
  197. package/src/components/features/remote-config/useDateTimeText.ts +16 -0
  198. package/src/components/ui/sidebar.tsx +22 -29
  199. package/src/index.ts +26 -19
  200. package/src/lib/api-keys-api.ts +0 -28
  201. package/src/lib/api-keys-rpc.ts +27 -38
  202. package/src/lib/api-rpc.ts +125 -288
  203. package/src/lib/api.ts +15 -134
  204. package/src/lib/bundle-activity.ts +24 -4
  205. package/src/lib/console-access.ts +20 -0
  206. package/src/lib/console-features-api.ts +68 -0
  207. package/src/lib/console-features-rpc.ts +13 -0
  208. package/src/lib/console-features.ts +98 -0
  209. package/src/lib/insights-api.ts +56 -2
  210. package/src/lib/insights-errors.ts +64 -0
  211. package/src/lib/insights-failures-rpc.ts +36 -0
  212. package/src/lib/insights-failures.ts +130 -0
  213. package/src/lib/insights-recovery-rpc.ts +13 -17
  214. package/src/lib/insights-recovery.ts +12 -36
  215. package/src/lib/insights-retention.ts +21 -0
  216. package/src/lib/insights-rpc.ts +30 -12
  217. package/src/lib/insights-search.ts +50 -4
  218. package/src/lib/insights-usage-rpc.ts +15 -9
  219. package/src/lib/insights-usage.ts +41 -3
  220. package/src/lib/insights-view.ts +34 -5
  221. package/src/lib/release-adoption-api.ts +214 -0
  222. package/src/lib/release-adoption-rpc.ts +49 -0
  223. package/src/lib/release-adoption.ts +164 -0
  224. package/src/lib/remote-config-api.ts +119 -0
  225. package/src/lib/remote-config-draft.ts +666 -0
  226. package/src/lib/remote-config-rpc.ts +196 -0
  227. package/src/lib/scroll-restoration.ts +21 -0
  228. package/src/lib/server/auth.server.ts +13 -5
  229. package/src/lib/server/bundleActivity.ts +27 -28
  230. package/src/lib/server/config.server.ts +21 -76
  231. package/src/lib/server/console-feature-apis.ts +70 -0
  232. package/src/lib/server/console-runtime.server.ts +82 -38
  233. package/src/lib/server/downloadBundle.ts +14 -15
  234. package/src/lib/server/failureReports.ts +50 -0
  235. package/src/lib/server/getBundleChildren.ts +31 -122
  236. package/src/lib/server/insightsUsage.ts +52 -113
  237. package/src/lib/server/listReleases.ts +109 -44
  238. package/src/lib/server/releaseAdoption.ts +151 -0
  239. package/src/lib/server/releaseReachability.ts +8 -8
  240. package/src/lib/server/remoteConfig.ts +75 -0
  241. package/src/lib/server/runtime.server.ts +120 -31
  242. package/src/lib/server/updateFailures.ts +66 -0
  243. package/src/lib/use-dialog-target.ts +27 -0
  244. package/src/routeTree.gen.ts +44 -44
  245. package/src/router.tsx +3 -2
  246. package/src/routes/-installations-search.ts +32 -8
  247. package/src/routes/-releases-search.ts +76 -29
  248. package/src/routes/__root.tsx +7 -1
  249. package/src/routes/api/bundles/$bundleId/download.ts +2 -5
  250. package/src/routes/api-keys.tsx +5 -2
  251. package/src/routes/index.tsx +210 -152
  252. package/src/routes/insights.tsx +91 -23
  253. package/src/routes/insights_.distribution.tsx +50 -9
  254. package/src/routes/installations.tsx +97 -40
  255. package/src/routes/remote-config.tsx +42 -0
  256. package/src/styles.css +9 -0
  257. package/src/vite-internal.ts +15 -3
  258. package/src/vite.ts +2 -0
  259. package/.output/public/assets/HashValueDisplay-BpTc3Oyg.js +0 -1
  260. package/.output/public/assets/InsightsPageHeader-DC2eEst8.js +0 -1
  261. package/.output/public/assets/api-CdUyUqzR.js +0 -42
  262. package/.output/public/assets/api-keys-64PM9PwW.js +0 -1
  263. package/.output/public/assets/api-keys-api-BeaJnvY5.js +0 -1
  264. package/.output/public/assets/arrow-left-04Rh8Zgp.js +0 -1
  265. package/.output/public/assets/card-CYHs5FZv.js +0 -1
  266. package/.output/public/assets/chart-no-axes-combined-DwyMsVFW.js +0 -1
  267. package/.output/public/assets/createServerFn-DU71xucx.js +0 -3
  268. package/.output/public/assets/dialog-IVMkBRCq.js +0 -1
  269. package/.output/public/assets/dist-BR4GzeEu.js +0 -1
  270. package/.output/public/assets/field-B3CYDpjg.js +0 -1
  271. package/.output/public/assets/index-Cb_D1D6N.js +0 -10
  272. package/.output/public/assets/info-C3y9HNoU.js +0 -1
  273. package/.output/public/assets/input-group-nLZylhWF.js +0 -1
  274. package/.output/public/assets/insights-Bm9v8uO3.js +0 -2
  275. package/.output/public/assets/insights-DS3iO7Up.js +0 -1
  276. package/.output/public/assets/insights-search-Byj3g3Mp.js +0 -1
  277. package/.output/public/assets/insights-usage-rpc-BaGR3lgq.js +0 -1
  278. package/.output/public/assets/insights_.distribution-B1i6cjlQ.js +0 -1
  279. package/.output/public/assets/insights_.distribution-C1Wf27eB.js +0 -2
  280. package/.output/public/assets/installations-CkFW4fV9.js +0 -2
  281. package/.output/public/assets/installations-DxTaIcHD.js +0 -1
  282. package/.output/public/assets/lazyRouteComponent-BapzjYnb.js +0 -1
  283. package/.output/public/assets/list-Dqt53fWZ.js +0 -1
  284. package/.output/public/assets/loader-circle-CUKfUqow.js +0 -1
  285. package/.output/public/assets/preload-helper-ClBMtM1g.js +0 -1
  286. package/.output/public/assets/refresh-cw-CNE_2PnD.js +0 -1
  287. package/.output/public/assets/routes-Cgtvspjg.js +0 -2
  288. package/.output/public/assets/routes-O2r2UUN8.js +0 -1
  289. package/.output/public/assets/shield-check-BFcJ46kz.js +0 -1
  290. package/.output/public/assets/signing-BgspC-xP.js +0 -1
  291. package/.output/public/assets/styles-DnrWuBwd.css +0 -2
  292. package/.output/public/assets/table-BuWQgxJJ.js +0 -1
  293. package/.output/public/assets/useMutation-CSV9NCUl.js +0 -1
  294. package/.output/public/assets/useOpenInteractionType-D5kduCTD.js +0 -1
  295. package/.output/public/assets/valueToPercent-BAtcbSLk.js +0 -1
  296. package/.output/server/__23tanstack-start-server-fn-resolver-DBRojHaG.mjs +0 -150
  297. package/.output/server/_ssr/InsightsPageHeader-mtxVuZKK.mjs +0 -64
  298. package/.output/server/_ssr/api-BfCgYlj5.mjs +0 -332
  299. package/.output/server/_ssr/api-keys-api-C3oeq01R.mjs +0 -60
  300. package/.output/server/_ssr/api-keys-rpc-CdPFdGOx.mjs +0 -136
  301. package/.output/server/_ssr/api-rpc-B2E1ZIG5.mjs +0 -1399
  302. package/.output/server/_ssr/auth.server-CmicHh0J.mjs +0 -47
  303. package/.output/server/_ssr/bundle-signing-rpc-Di7-I6fE.mjs +0 -16
  304. package/.output/server/_ssr/bundle-signing.server-Uqt1OF49.mjs +0 -12
  305. package/.output/server/_ssr/bundleActivity-pBrPSG01.mjs +0 -28
  306. package/.output/server/_ssr/card-Bemj0dpY.mjs +0 -108
  307. package/.output/server/_ssr/config-Dv8qLDZ0.mjs +0 -13
  308. package/.output/server/_ssr/config.server-B8WsT3s0.mjs +0 -368
  309. package/.output/server/_ssr/databaseRows-5bCRTxm-.mjs +0 -126
  310. package/.output/server/_ssr/deleteBundle-8X-jq7Z7.mjs +0 -66
  311. package/.output/server/_ssr/field-BrQ2u0fT.mjs +0 -74
  312. package/.output/server/_ssr/getBundleChildren-DoL8l_AS.mjs +0 -50
  313. package/.output/server/_ssr/insights-BwQ-wF2a.mjs +0 -10
  314. package/.output/server/_ssr/insights-gr1I_dJU.mjs +0 -938
  315. package/.output/server/_ssr/insights-recovery-Cv6RSyeR.mjs +0 -21
  316. package/.output/server/_ssr/insights-recovery-rpc-DOzxfYfv.mjs +0 -37
  317. package/.output/server/_ssr/insights-search-1czJMZgk.mjs +0 -21
  318. package/.output/server/_ssr/insights-usage-rpc-4ImOq_0p.mjs +0 -184
  319. package/.output/server/_ssr/insights-usage-rpc-BUruODjE.mjs +0 -24
  320. package/.output/server/_ssr/insightsContract-B09K_Px1.mjs +0 -303
  321. package/.output/server/_ssr/insightsHistory-Ci4rYAgl.mjs +0 -41
  322. package/.output/server/_ssr/insightsRecovery-CaghWL2t.mjs +0 -113
  323. package/.output/server/_ssr/insightsUsage-DNIj6jxF.mjs +0 -71
  324. package/.output/server/_ssr/insights_.distribution-VmHuikRE.mjs +0 -10
  325. package/.output/server/_ssr/installations-HXMF_kKf.mjs +0 -29
  326. package/.output/server/_ssr/routes-Dru3IRj0.mjs +0 -37
  327. package/.output/server/_ssr/runtime.server-CsiKFp_Z.mjs +0 -436
  328. package/.output/server/_ssr/server-DJm72Kj-.mjs +0 -7468
  329. package/.output/server/_ssr/signing-H8Lg4lPe.mjs +0 -133
  330. package/.output/server/_ssr/start-DpViQGnt.mjs +0 -4
  331. package/.output/server/_tanstack-start-manifest_v-DsFcTLw_.mjs +0 -125
  332. package/src/components/features/bundles/BundleActivityChart.tsx +0 -97
  333. package/src/components/features/bundles/BundleInsightsSummary.tsx +0 -126
  334. package/src/components/features/signing/BundleSigningPage.tsx +0 -139
  335. package/src/lib/bundle-signing-api.ts +0 -14
  336. package/src/lib/bundle-signing-rpc.ts +0 -16
  337. package/src/lib/server/bundle-signing.server.ts +0 -23
  338. package/src/lib/server/deleteBundle.ts +0 -145
  339. package/src/lib/server/insightsHistory.ts +0 -52
  340. package/src/lib/server/insightsRecovery.ts +0 -187
  341. package/src/routes/signing.tsx +0 -37
@@ -1,30 +1,18 @@
1
1
  import {
2
- DatabasePluginInputError,
3
- type Bundle,
4
- type ChannelDeleteInput,
5
- type ChannelInsertInput,
6
- type DatabaseBundleQueryOptions,
7
- deleteRelease as deleteReleaseMutation,
8
- preflightReleasePolicy,
9
- promoteRelease as promoteReleaseMutation,
2
+ type ChannelDeleteResult,
3
+ type ChannelRow,
4
+ type ReleaseFilter,
10
5
  type ReleasePolicyPatch,
11
- updateReleasePolicy,
6
+ rowToBundle,
12
7
  } from "@hot-updater/plugin-core";
13
8
  import { createServerFn } from "@tanstack/react-start";
14
9
 
10
+ import { consoleAccess } from "./console-access";
15
11
  import { DEFAULT_PAGE_LIMIT } from "./constants";
16
12
  import { withPublicBundleMutationErrors } from "./public-bundle-error";
17
- import { listReleases } from "./server/listReleases";
13
+ import { listReleases, readReleaseFilter } from "./server/listReleases";
18
14
  import { addReleaseReachability } from "./server/releaseReachability";
19
15
 
20
- type GetBundlesInput = {
21
- platform?: "ios" | "android";
22
- page?: number;
23
- limit?: string;
24
- after?: string;
25
- before?: string;
26
- };
27
-
28
16
  type GetBundleInput = {
29
17
  bundleId: string;
30
18
  };
@@ -37,24 +25,14 @@ type GetBundleChildCountsInput = {
37
25
  bundleIds: string[];
38
26
  };
39
27
 
40
- type DeleteBundleInput = {
41
- bundleId: string;
42
- };
43
-
44
- type DeleteBundlesInput = {
45
- bundleIds: string[];
46
- };
47
-
48
28
  type GetReleasesInput = {
49
- afterReleaseId?: string;
29
+ /** One of the filter sets the release indexes serve. */
30
+ filter?: ReleaseFilter;
31
+ /** Releases older than this id: the next page. */
50
32
  beforeReleaseId?: string;
51
- bundleId?: string;
52
- channelId?: string;
53
- enabled?: boolean;
54
- platform?: "ios" | "android";
33
+ /** Releases newer than this id: the previous page. */
34
+ afterReleaseId?: string;
55
35
  limit?: number;
56
- page?: number;
57
- targetAppVersion?: string;
58
36
  };
59
37
 
60
38
  type ReleaseMutationInput = {
@@ -68,78 +46,78 @@ type DeleteReleaseInput = {
68
46
  releaseId: string;
69
47
  };
70
48
 
49
+ const MAX_PAGE_LIMIT = 100;
50
+
51
+ const pageLimit = (limit: number | undefined) => {
52
+ const value = limit ?? DEFAULT_PAGE_LIMIT;
53
+ if (!Number.isSafeInteger(value) || value < 1 || value > MAX_PAGE_LIMIT) {
54
+ throw new Error(`limit must be between 1 and ${MAX_PAGE_LIMIT}.`);
55
+ }
56
+ return value;
57
+ };
58
+
59
+ const prepare = async () => {
60
+ const { prepareConfig } = await import("./server/config.server");
61
+ return prepareConfig();
62
+ };
63
+
71
64
  export const getReleases = createServerFn({ method: "GET" })
72
- .inputValidator((input: GetReleasesInput | undefined) => input)
73
- .handler(async ({ data }) => {
74
- const { prepareConfig } = await import("./server/config.server");
75
- const { config } = await prepareConfig();
76
- const result = await listReleases(config.database.models.releases, {
77
- ...(data?.afterReleaseId === undefined
78
- ? {}
79
- : { afterReleaseId: data.afterReleaseId }),
80
- ...(data?.beforeReleaseId === undefined
81
- ? {}
82
- : { beforeReleaseId: data.beforeReleaseId }),
83
- ...(data?.bundleId === undefined ? {} : { bundleId: data.bundleId }),
84
- ...(data?.channelId === undefined ? {} : { channelId: data.channelId }),
85
- ...(data?.enabled === undefined ? {} : { enabled: data.enabled }),
86
- ...(data?.page === undefined ? {} : { page: data.page }),
87
- ...(data?.platform === undefined ? {} : { platform: data.platform }),
88
- ...(data?.targetAppVersion === undefined
89
- ? {}
90
- : { targetAppVersion: data.targetAppVersion }),
91
- limit: data?.limit ?? DEFAULT_PAGE_LIMIT,
92
- });
93
- const releases = await addReleaseReachability(
94
- config.database.models.releaseCatalogs,
95
- result.data,
96
- );
65
+ .middleware([consoleAccess])
66
+ .validator((input: GetReleasesInput | undefined) => ({
67
+ filter: readReleaseFilter(input?.filter),
68
+ ...(input?.afterReleaseId === undefined
69
+ ? {}
70
+ : { afterReleaseId: input.afterReleaseId }),
71
+ ...(input?.beforeReleaseId === undefined
72
+ ? {}
73
+ : { beforeReleaseId: input.beforeReleaseId }),
74
+ limit: pageLimit(input?.limit),
75
+ }))
76
+ .handler(async ({ data }) => {
77
+ const { core } = await prepare();
78
+ const result = await listReleases(core, data);
97
79
  return {
98
80
  ...result,
99
- data: releases,
81
+ data: await addReleaseReachability(core, result.data),
100
82
  };
101
83
  });
102
84
 
103
85
  export const getRelease = createServerFn({ method: "GET" })
104
- .inputValidator((input: { releaseId: string }) => input)
105
- .handler(async ({ data }) => {
106
- const { prepareConfig } = await import("./server/config.server");
107
- const { config } = await prepareConfig();
108
- return config.database.models.releases.findById(data.releaseId);
109
- });
86
+ .middleware([consoleAccess])
87
+ .validator((input: { releaseId: string }) => input)
88
+ .handler(async ({ data }) =>
89
+ (await prepare()).core.getRelease(data.releaseId),
90
+ );
110
91
 
111
92
  export const updateRelease = createServerFn({ method: "POST" })
112
- .inputValidator((input: ReleaseMutationInput) => input)
93
+ .middleware([consoleAccess])
94
+ .validator((input: ReleaseMutationInput) => input)
113
95
  .handler(async ({ data }) => {
114
- const { prepareConfig } = await import("./server/config.server");
115
- const { config } = await prepareConfig();
116
- return withPublicBundleMutationErrors(() =>
117
- updateReleasePolicy({ database: config.database, ...data }),
118
- );
96
+ const { core } = await prepare();
97
+ return withPublicBundleMutationErrors(() => core.updateReleasePolicy(data));
119
98
  });
120
99
 
121
100
  export const preflightRelease = createServerFn({ method: "POST" })
122
- .inputValidator((input: ReleaseMutationInput) => input)
101
+ .middleware([consoleAccess])
102
+ .validator((input: ReleaseMutationInput) => input)
123
103
  .handler(async ({ data }) => {
124
- const { prepareConfig } = await import("./server/config.server");
125
- const { config } = await prepareConfig();
104
+ const { core } = await prepare();
126
105
  return withPublicBundleMutationErrors(() =>
127
- preflightReleasePolicy({ database: config.database, ...data }),
106
+ core.preflightReleasePolicy(data),
128
107
  );
129
108
  });
130
109
 
131
110
  export const deleteRelease = createServerFn({ method: "POST" })
132
- .inputValidator((input: DeleteReleaseInput) => input)
111
+ .middleware([consoleAccess])
112
+ .validator((input: DeleteReleaseInput) => input)
133
113
  .handler(async ({ data }) => {
134
- const { prepareConfig } = await import("./server/config.server");
135
- const { config } = await prepareConfig();
136
- return withPublicBundleMutationErrors(() =>
137
- deleteReleaseMutation({ database: config.database, ...data }),
138
- );
114
+ const { core } = await prepare();
115
+ return withPublicBundleMutationErrors(() => core.deleteRelease(data));
139
116
  });
140
117
 
141
118
  export const promoteRelease = createServerFn({ method: "POST" })
142
- .inputValidator(
119
+ .middleware([consoleAccess])
120
+ .validator(
143
121
  (input: {
144
122
  action: "copy" | "move";
145
123
  expectedRevision?: number;
@@ -148,260 +126,119 @@ export const promoteRelease = createServerFn({ method: "POST" })
148
126
  }) => input,
149
127
  )
150
128
  .handler(async ({ data }) => {
151
- const { prepareConfig } = await import("./server/config.server");
152
- const { config } = await prepareConfig();
153
- return withPublicBundleMutationErrors(() =>
154
- promoteReleaseMutation({ database: config.database, ...data }),
155
- );
129
+ const { core } = await prepare();
130
+ return withPublicBundleMutationErrors(() => core.promoteRelease(data));
156
131
  });
157
132
 
158
133
  export const getReleaseCatalogDiagnostics = createServerFn({ method: "GET" })
159
- .inputValidator((input: { scopeKey: string }) => input)
160
- .handler(async ({ data }) => {
161
- const { prepareConfig } = await import("./server/config.server");
162
- const { config } = await prepareConfig();
163
- return config.database.models.releaseCatalogs.findByScopeKey(data.scopeKey);
164
- });
165
-
166
- // GET /api/config
167
- export const getConfig = createServerFn().handler(async () => {
168
- try {
169
- const { prepareConfig } = await import("./server/config.server");
170
- const { config } = await prepareConfig();
171
- return { console: config.console };
172
- } catch (error) {
173
- console.error("Error during config retrieval:", error);
174
- throw error;
175
- }
176
- });
177
-
178
- // GET /api/channels
179
- export const getChannels = createServerFn().handler(async () => {
180
- try {
181
- const { prepareConfig } = await import("./server/config.server");
182
- const { databaseClient } = await prepareConfig();
183
- const channels = await databaseClient.getChannels();
184
- return channels ?? [];
185
- } catch (error) {
186
- console.error("Error during channel retrieval:", error);
187
- throw error;
188
- }
189
- });
190
-
191
- // POST /api/channels
192
- export const createChannel = createServerFn({ method: "POST" })
193
- .inputValidator((input: ChannelInsertInput) => input)
194
- .handler(async ({ data }) => {
134
+ .middleware([consoleAccess])
135
+ .validator((input: { scopeKey: string }) => input)
136
+ .handler(async ({ data }) =>
137
+ (await prepare()).core.getReleaseCatalogRow(data.scopeKey),
138
+ );
139
+
140
+ export const getConfig = createServerFn()
141
+ .middleware([consoleAccess])
142
+ .handler(async () => {
195
143
  try {
196
- const { prepareConfig } = await import("./server/config.server");
197
- const { databaseClient } = await prepareConfig();
198
- return { data: await databaseClient.insertChannel(data) };
144
+ const { config } = await prepare();
145
+ return { console: { gitUrl: config.gitUrl } };
199
146
  } catch (error) {
200
- console.error("Error during channel creation:", error);
147
+ console.error("Error during config retrieval:", error);
201
148
  throw error;
202
149
  }
203
150
  });
204
151
 
205
- // DELETE /api/channels/:id
206
- export const deleteChannel = createServerFn({ method: "POST" })
207
- .inputValidator((input: ChannelDeleteInput) => input)
208
- .handler(async ({ data }) => {
152
+ export const getChannels = createServerFn()
153
+ .middleware([consoleAccess])
154
+ .handler(async (): Promise<ChannelRow[]> => {
209
155
  try {
210
- const { prepareConfig } = await import("./server/config.server");
211
- const { databaseClient } = await prepareConfig();
212
- return { data: await databaseClient.deleteChannel(data) };
156
+ return await (await prepare()).core.listChannels();
213
157
  } catch (error) {
214
- console.error("Error during channel deletion:", error);
158
+ console.error("Error during channel retrieval:", error);
215
159
  throw error;
216
160
  }
217
161
  });
218
162
 
219
- // GET /api/config-loaded
220
- export const getConfigLoaded = createServerFn().handler(async () => {
221
- try {
222
- const [{ getRequest }, { requireConsoleAccess }] = await Promise.all([
223
- import("@tanstack/react-start/server"),
224
- import("./server/auth.server"),
225
- ]);
226
- await requireConsoleAccess(getRequest());
227
- const { isConfigLoaded } = await import("./server/config.server");
228
- const configLoaded = isConfigLoaded();
229
- return { configLoaded };
230
- } catch (error) {
231
- console.error("Error during config loaded retrieval:", error);
232
- throw error;
233
- }
234
- });
235
-
236
- // GET /api/bundles
237
- export const getBundles = createServerFn({ method: "GET" })
238
- .inputValidator((input: GetBundlesInput | undefined) => input)
163
+ export const createChannel = createServerFn({ method: "POST" })
164
+ .middleware([consoleAccess])
165
+ .validator((input: { name: string }) => {
166
+ const name = typeof input?.name === "string" ? input.name.trim() : "";
167
+ if (name.length === 0) throw new Error("Channel name is required.");
168
+ return { name };
169
+ })
239
170
  .handler(async ({ data }) => {
240
171
  try {
241
- const { prepareConfig } = await import("./server/config.server");
242
- const query = {
243
- platform: data?.platform ?? undefined,
244
- page:
245
- typeof data?.page === "number" &&
246
- Number.isInteger(data.page) &&
247
- data.page > 1
248
- ? data.page
249
- : undefined,
250
- limit: data?.limit ? Number(data.limit) : DEFAULT_PAGE_LIMIT,
251
- after: data?.after ?? undefined,
252
- before: data?.before ?? undefined,
253
- };
254
- if (
255
- (query.after !== undefined && query.before !== undefined) ||
256
- (query.page !== undefined &&
257
- (query.after !== undefined || query.before !== undefined))
258
- ) {
259
- throw new DatabasePluginInputError("invalid-pagination");
172
+ const { core } = await prepare();
173
+ const existing = await core.findChannelByName(data.name);
174
+ if (existing !== null) {
175
+ return { data: { row: existing, inserted: false } };
260
176
  }
261
- const pagination =
262
- query.page !== undefined
263
- ? { page: query.page }
264
- : query.after !== undefined
265
- ? { cursor: { after: query.after } }
266
- : query.before !== undefined
267
- ? { cursor: { before: query.before } }
268
- : {};
269
-
270
- const { databaseClient } = await prepareConfig();
271
- const bundleQueryOptions: DatabaseBundleQueryOptions = {
272
- where: {
273
- platform: query.platform,
274
- },
275
- limit: query.limit,
276
- ...pagination,
177
+ return {
178
+ data: { row: await core.ensureChannel(data.name), inserted: true },
277
179
  };
278
- const bundles = await databaseClient.getBundles(bundleQueryOptions);
279
-
280
- return (
281
- bundles ?? {
282
- data: [],
283
- pagination: {
284
- total: 0,
285
- hasNextPage: false,
286
- hasPreviousPage: false,
287
- currentPage: 1,
288
- totalPages: 0,
289
- },
290
- }
291
- );
292
- } catch (error) {
293
- console.error("Error during bundle retrieval:", error);
294
- throw error;
295
- }
296
- });
297
-
298
- // GET /api/bundles/:bundleId
299
- export const getBundle = createServerFn({ method: "GET" })
300
- .inputValidator((input: GetBundleInput) => input)
301
- .handler(async ({ data }) => {
302
- try {
303
- const { prepareConfig } = await import("./server/config.server");
304
- const { databaseClient } = await prepareConfig();
305
- const bundle = await databaseClient.getBundleById(data.bundleId);
306
- return bundle ?? null;
307
180
  } catch (error) {
308
- console.error("Error during bundle retrieval:", error);
181
+ console.error("Error during channel creation:", error);
309
182
  throw error;
310
183
  }
311
184
  });
312
185
 
313
- export const getBundleChildren = createServerFn({ method: "GET" })
314
- .inputValidator((input: GetBundleChildrenInput) => input)
315
- .handler(async ({ data }) => {
186
+ export const deleteChannel = createServerFn({ method: "POST" })
187
+ .middleware([consoleAccess])
188
+ .validator((input: { id: string }) => input)
189
+ .handler(async ({ data }): Promise<{ data: ChannelDeleteResult }> => {
316
190
  try {
317
- const { prepareConfig } = await import("./server/config.server");
318
- const { getBundleChildren: getBundleChildrenWithConfig } =
319
- await import("./server/getBundleChildren");
320
- const { databaseClient } = await prepareConfig();
321
-
322
- return await getBundleChildrenWithConfig(data, {
323
- databaseClient,
324
- });
191
+ return { data: await (await prepare()).core.deleteChannel(data.id) };
325
192
  } catch (error) {
326
- console.error("Error during bundle children retrieval:", error);
193
+ console.error("Error during channel deletion:", error);
327
194
  throw error;
328
195
  }
329
196
  });
330
197
 
331
- export const getBundleChildCounts = createServerFn({ method: "GET" })
332
- .inputValidator((input: GetBundleChildCountsInput) => input)
198
+ export const getBundle = createServerFn({ method: "GET" })
199
+ .middleware([consoleAccess])
200
+ .validator((input: GetBundleInput) => input)
333
201
  .handler(async ({ data }) => {
334
202
  try {
335
- const { prepareConfig } = await import("./server/config.server");
336
- const { getBundleChildCounts: getBundleChildCountsWithConfig } =
337
- await import("./server/getBundleChildren");
338
- const { databaseClient } = await prepareConfig();
339
-
340
- return await getBundleChildCountsWithConfig(data.bundleIds, {
341
- databaseClient,
342
- });
203
+ const detail = await (await prepare()).core.getBundle(data.bundleId);
204
+ return detail === null
205
+ ? null
206
+ : rowToBundle(detail.bundle, detail.patches);
343
207
  } catch (error) {
344
- console.error("Error during bundle child count retrieval:", error);
208
+ console.error("Error during bundle retrieval:", error);
345
209
  throw error;
346
210
  }
347
211
  });
348
212
 
349
- // POST /api/bundles
350
- export const createBundle = createServerFn({ method: "POST" })
351
- .inputValidator((input: Bundle) => input)
213
+ export const getBundleChildren = createServerFn({ method: "GET" })
214
+ .middleware([consoleAccess])
215
+ .validator((input: GetBundleChildrenInput) => input)
352
216
  .handler(async ({ data }) => {
353
217
  try {
354
- const { prepareConfig } = await import("./server/config.server");
355
- const { databaseClient } = await prepareConfig();
356
- await databaseClient.insertBundle(data);
357
- return { success: true, bundleId: data.id };
218
+ const [{ core }, { getBundleChildren: readBundleChildren }] =
219
+ await Promise.all([prepare(), import("./server/getBundleChildren")]);
220
+ return await readBundleChildren(core, data.baseBundleId);
358
221
  } catch (error) {
359
- console.error("Error during bundle creation:", error);
222
+ console.error("Error during bundle children retrieval:", error);
360
223
  throw error;
361
224
  }
362
225
  });
363
226
 
364
- // DELETE /api/bundles/:bundleId
365
- export const deleteBundle = createServerFn({ method: "POST" })
366
- .inputValidator((input: DeleteBundleInput) => input)
367
- .handler(async ({ data }) => {
368
- try {
369
- const { prepareConfig } = await import("./server/config.server");
370
- const { deleteBundle: deleteBundleWithStorage } =
371
- await import("./server/deleteBundle");
372
- const { databaseClient, storagePlugin } = await prepareConfig();
373
-
374
- await deleteBundleWithStorage(data, {
375
- databaseClient,
376
- storagePlugin,
377
- waitForStorageCleanup: false,
378
- });
379
-
380
- return { success: true };
381
- } catch (error) {
382
- console.error("Error during bundle deletion:", error);
383
- throw error;
227
+ export const getBundleChildCounts = createServerFn({ method: "GET" })
228
+ .middleware([consoleAccess])
229
+ .validator((input: GetBundleChildCountsInput) => {
230
+ if (!Array.isArray(input?.bundleIds) || input.bundleIds.length > 100) {
231
+ throw new Error("Choose up to 100 bundles.");
384
232
  }
385
- });
386
-
387
- export const deleteBundles = createServerFn({ method: "POST" })
388
- .inputValidator((input: DeleteBundlesInput) => input)
233
+ return input;
234
+ })
389
235
  .handler(async ({ data }) => {
390
236
  try {
391
- const { prepareConfig } = await import("./server/config.server");
392
- const { deleteBundles: deleteBundlesWithStorage } =
393
- await import("./server/deleteBundle");
394
- const { databaseClient, storagePlugin } = await prepareConfig();
395
-
396
- const result = await deleteBundlesWithStorage(data, {
397
- databaseClient,
398
- storagePlugin,
399
- waitForStorageCleanup: false,
400
- });
401
-
402
- return { success: true, ...result };
237
+ const [{ core }, { getBundleChildCounts: readBundleChildCounts }] =
238
+ await Promise.all([prepare(), import("./server/getBundleChildren")]);
239
+ return await readBundleChildCounts(core, data.bundleIds);
403
240
  } catch (error) {
404
- console.error("Error during bundle deletion:", error);
241
+ console.error("Error during bundle child count retrieval:", error);
405
242
  throw error;
406
243
  }
407
244
  });