@hot-updater/console 0.36.6 → 1.0.0-rc.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 (266) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/AnalyticsCapabilityContext-BCke57-7.js +1 -0
  3. package/.output/public/assets/BundleActivityChart-CnsBe_1J.js +42 -0
  4. package/.output/public/assets/BundleIdDisplay-Dky75zLU.js +1 -0
  5. package/.output/public/assets/alert-C-1KvDW8.js +1 -0
  6. package/.output/public/assets/analytics-Bqz0c-BT.js +1 -0
  7. package/.output/public/assets/analytics-api-CJdrTLLO.js +1 -0
  8. package/.output/public/assets/api-B_Rh-uzC.js +1 -0
  9. package/.output/public/assets/api-keys-BurCFhzH.js +1 -0
  10. package/.output/public/assets/api-keys-api-BEDJdQg3.js +1 -0
  11. package/.output/public/assets/badge-Bf0fZ-Gx.js +1 -0
  12. package/.output/public/assets/chart-no-axes-combined-FaYMGmQS.js +1 -0
  13. package/.output/public/assets/createServerFn-gM2-LFBy.js +3 -0
  14. package/.output/public/assets/dialog-BS60BRr2.js +1 -0
  15. package/.output/public/assets/dist-DspNKfMj.js +1 -0
  16. package/.output/public/assets/download-O-yNBc9H.js +1 -0
  17. package/.output/public/assets/field-Buq148-A.js +1 -0
  18. package/.output/public/assets/index-kFhd2S78.js +10 -0
  19. package/.output/public/assets/installations-BrQ-od41.js +2 -0
  20. package/.output/public/assets/installations-CGlZ3ROz.js +1 -0
  21. package/.output/public/assets/lazyRouteComponent-rPzgA7S-.js +1 -0
  22. package/.output/public/assets/loader-circle-DCYF-wJl.js +1 -0
  23. package/.output/public/assets/preload-helper-TKOBYGYD.js +1 -0
  24. package/.output/public/assets/refresh-cw-n8XYbPPj.js +1 -0
  25. package/.output/public/assets/routes-CrdokJ80.js +1 -0
  26. package/.output/public/assets/routes-DcQnVajO.js +2 -0
  27. package/.output/public/assets/search-DLhbWw3W.js +1 -0
  28. package/.output/public/assets/shield-check-DE_hVuHu.js +1 -0
  29. package/.output/public/assets/signing-HRexfjsH.js +1 -0
  30. package/.output/public/assets/styles-eB4EtvFS.css +2 -0
  31. package/.output/public/assets/table-D8CLieHX.js +1 -0
  32. package/.output/public/assets/textarea-YJLTVAoq.js +1 -0
  33. package/.output/public/assets/useMutation-JsGVjQMY.js +1 -0
  34. package/.output/public/assets/useOpenInteractionType-4cRD5xO0.js +1 -0
  35. package/.output/server/__23tanstack-start-server-fn-resolver-DBP9TQ7K.mjs +146 -0
  36. package/.output/server/_libs/@base-ui/react+[...].mjs +16124 -0
  37. package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +1554 -0
  38. package/.output/server/_libs/@tanstack/react-router+[...].mjs +41 -10
  39. package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +132 -0
  40. package/.output/server/_libs/d3-array.mjs +231 -0
  41. package/.output/server/_libs/d3-color.mjs +330 -0
  42. package/.output/server/_libs/d3-format.mjs +252 -0
  43. package/.output/server/_libs/d3-interpolate.mjs +207 -0
  44. package/.output/server/_libs/d3-path.mjs +77 -0
  45. package/.output/server/_libs/d3-scale+[...].mjs +1907 -0
  46. package/.output/server/_libs/d3-shape.mjs +818 -0
  47. package/.output/server/_libs/decimal.js-light.mjs +884 -0
  48. package/.output/server/_libs/es-toolkit.mjs +1134 -0
  49. package/.output/server/_libs/eventemitter3.mjs +236 -0
  50. package/.output/server/_libs/immer.mjs +532 -0
  51. package/.output/server/_libs/lucide-react.mjs +141 -13
  52. package/.output/server/_libs/next-themes.mjs +2 -2
  53. package/.output/server/_libs/react-redux+[...].mjs +205 -0
  54. package/.output/server/_libs/recharts+[...].mjs +14117 -0
  55. package/.output/server/_libs/sonner.mjs +2 -2
  56. package/.output/server/_libs/tanstack__query-core.mjs +114 -1
  57. package/.output/server/_libs/tanstack__react-query.mjs +3 -4
  58. package/.output/server/_runtime.mjs +10 -1
  59. package/.output/server/_ssr/AnalyticsCapabilityContext-ui4DX8GO.mjs +15 -0
  60. package/.output/server/_ssr/BundleActivityChart-BiB9ZORH.mjs +288 -0
  61. package/.output/server/_ssr/BundleIdDisplay-Czk6iR6p.mjs +13 -0
  62. package/.output/server/_ssr/alert-Dim3MGY5.mjs +86 -0
  63. package/.output/server/_ssr/analytics-DtMTn8fn.mjs +858 -0
  64. package/.output/server/_ssr/analytics-api-Cg1M5v_H.mjs +71 -0
  65. package/.output/server/_ssr/analytics-input-fRRRn0uA.mjs +96 -0
  66. package/.output/server/_ssr/analytics-rpc-DY5uXvHT.mjs +155 -0
  67. package/.output/server/_ssr/api-BTSv1tZb.mjs +282 -0
  68. package/.output/server/_ssr/api-keys-BnM_o2nS.mjs +300 -0
  69. package/.output/server/_ssr/api-keys-api-CIywsSF5.mjs +60 -0
  70. package/.output/server/_ssr/api-keys-rpc-BSp1wkIV.mjs +136 -0
  71. package/.output/server/_ssr/api-rpc-cG5wd_tO.mjs +1468 -0
  72. package/.output/server/_ssr/auth-BF8mbAgF.mjs +21 -0
  73. package/.output/server/_ssr/auth-rpc-BrJ6obHJ.mjs +24 -0
  74. package/.output/server/_ssr/auth.server-DwKoZoQM.mjs +50 -0
  75. package/.output/server/_ssr/badge-DCxbEeof.mjs +26 -0
  76. package/.output/server/_ssr/bundle-signing-rpc-COoQhW8E.mjs +16 -0
  77. package/.output/server/_ssr/bundle-signing.server-D5u8KkMp.mjs +51 -0
  78. package/.output/server/_ssr/config-Dv8qLDZ0.mjs +13 -0
  79. package/.output/server/_ssr/config.server-DEiLhKmy.mjs +361 -0
  80. package/.output/server/_ssr/{createServerFn-DzU0k62V.mjs → createServerFn-B2hcXoPM.mjs} +1 -1
  81. package/.output/server/_ssr/createServerRpc-DB29C_5p.mjs +12 -0
  82. package/.output/server/_ssr/{sidebar-Cv_H0_Jv.mjs → createSsrRpc-9P0S0lJ3.mjs} +68 -50
  83. package/.output/server/_ssr/databaseRows-CwbNwYSl.mjs +166 -0
  84. package/.output/server/_ssr/deleteBundle-Cu_XOMt0.mjs +66 -0
  85. package/.output/server/_ssr/dialog-CQuRMNZ4.mjs +170 -0
  86. package/.output/server/_ssr/dist-BVSLTpoP.mjs +250 -0
  87. package/.output/server/_ssr/downloadBundle-CNnYxYO2.mjs +24 -0
  88. package/.output/server/_ssr/{empty-plugin-adapters-B4HCzgmM.mjs → empty-plugin-adapters-B5QvGpEl.mjs} +1 -1
  89. package/.output/server/_ssr/field-DRIXKjZG.mjs +74 -0
  90. package/.output/server/_ssr/{getBundleChildren-CVtSiH5t.mjs → getBundleChildren-BcRMFoDF.mjs} +10 -18
  91. package/.output/server/_ssr/installations-B-azgAvX.mjs +19 -0
  92. package/.output/server/_ssr/installations-Ctvzp2JH.mjs +535 -0
  93. package/.output/server/_ssr/router-C-KUBfOi.mjs +513 -0
  94. package/.output/server/_ssr/routes-BM4ht9jb.mjs +2286 -0
  95. package/.output/server/_ssr/routes-Z7TwC6nC.mjs +37 -0
  96. package/.output/server/_ssr/runtime.server-awTLiiXW.mjs +527 -0
  97. package/.output/server/_ssr/server-BjzmvXnO.mjs +7468 -0
  98. package/.output/server/_ssr/signing-k8GxyBDF.mjs +202 -0
  99. package/.output/server/_ssr/ssr.mjs +4 -5740
  100. package/.output/server/_ssr/start-DpViQGnt.mjs +4 -0
  101. package/.output/server/_ssr/table-v1yCvYo7.mjs +53 -0
  102. package/.output/server/_ssr/textarea-DYHnskhb.mjs +14 -0
  103. package/.output/server/_ssr/uuidv7-BbJ-9D_I.mjs +31 -0
  104. package/.output/server/_tanstack-start-manifest_v-CH4StzJu.mjs +108 -0
  105. package/.output/server/index.mjs +249 -46
  106. package/README.md +29 -8
  107. package/lib/index.d.mts +36 -0
  108. package/lib/index.mjs +4 -0
  109. package/lib/vite-internal.mjs +127 -0
  110. package/lib/vite.d.mts +10 -0
  111. package/lib/vite.mjs +5 -0
  112. package/package.json +51 -29
  113. package/public/apple-touch-icon.png +0 -0
  114. package/public/favicon-16x16.png +0 -0
  115. package/public/favicon-32x32.png +0 -0
  116. package/public/favicon.ico +0 -0
  117. package/public/logo.svg +1 -0
  118. package/public/manifest.json +30 -0
  119. package/public/robots.txt +3 -0
  120. package/src/components/AppSidebar.tsx +159 -0
  121. package/src/components/BundleIdDisplay.tsx +18 -0
  122. package/src/components/ChannelBadge.tsx +31 -0
  123. package/src/components/ConsoleAccessPage.tsx +122 -0
  124. package/src/components/EnabledStatusIcon.tsx +54 -0
  125. package/src/components/HashValueDisplay.tsx +85 -0
  126. package/src/components/HotUpdaterLogo.tsx +30 -0
  127. package/src/components/NotFoundPage.tsx +33 -0
  128. package/src/components/PlatformIcon.tsx +39 -0
  129. package/src/components/RolloutPercentageBadge.tsx +28 -0
  130. package/src/components/ThemeProvider.tsx +116 -0
  131. package/src/components/TimestampDisplay.tsx +41 -0
  132. package/src/components/features/analytics/ActivityChart.tsx +150 -0
  133. package/src/components/features/analytics/AnalyticsCapabilityContext.tsx +24 -0
  134. package/src/components/features/analytics/AnalyticsControls.tsx +115 -0
  135. package/src/components/features/analytics/AnalyticsErrorAlert.tsx +21 -0
  136. package/src/components/features/analytics/AnalyticsOverview.tsx +208 -0
  137. package/src/components/features/analytics/BundleDistribution.tsx +133 -0
  138. package/src/components/features/analytics/BundleSelector.tsx +114 -0
  139. package/src/components/features/analytics/InstallationHistoryCard.tsx +248 -0
  140. package/src/components/features/analytics/InstallationMatchesCard.tsx +132 -0
  141. package/src/components/features/analytics/InstallationPageHeader.tsx +138 -0
  142. package/src/components/features/analytics/InstallationPagination.tsx +48 -0
  143. package/src/components/features/analytics/InstallationSearch.tsx +230 -0
  144. package/src/components/features/analytics/UpdateOutcomes.tsx +147 -0
  145. package/src/components/features/api-keys/ApiKeysPage.tsx +377 -0
  146. package/src/components/features/bundles/BundleActivityChart.tsx +193 -0
  147. package/src/components/features/bundles/BundleAnalyticsSummary.tsx +123 -0
  148. package/src/components/features/bundles/BundleChildrenPanel.tsx +201 -0
  149. package/src/components/features/bundles/BundleMetadata.tsx +136 -0
  150. package/src/components/features/bundles/RolloutCohortsDialog.tsx +201 -0
  151. package/src/components/features/channels/ChannelManagementDialog.tsx +228 -0
  152. package/src/components/features/releases/ReleaseEditorSheet.tsx +879 -0
  153. package/src/components/features/releases/ReleaseStateBadge.tsx +20 -0
  154. package/src/components/features/signing/BundleSigningPage.tsx +247 -0
  155. package/src/components/ui/alert-dialog.tsx +185 -0
  156. package/src/components/ui/alert.tsx +76 -0
  157. package/src/components/ui/badge.tsx +49 -0
  158. package/src/components/ui/button.tsx +58 -0
  159. package/src/components/ui/card.tsx +89 -0
  160. package/src/components/ui/chart.tsx +371 -0
  161. package/src/components/ui/combobox.tsx +303 -0
  162. package/src/components/ui/dialog.tsx +156 -0
  163. package/src/components/ui/dropdown-menu.tsx +270 -0
  164. package/src/components/ui/field.tsx +235 -0
  165. package/src/components/ui/input-group.tsx +147 -0
  166. package/src/components/ui/input.tsx +19 -0
  167. package/src/components/ui/label.tsx +25 -0
  168. package/src/components/ui/progress.tsx +84 -0
  169. package/src/components/ui/select.tsx +205 -0
  170. package/src/components/ui/separator.tsx +23 -0
  171. package/src/components/ui/sheet.tsx +132 -0
  172. package/src/components/ui/sidebar.tsx +779 -0
  173. package/src/components/ui/skeleton.tsx +13 -0
  174. package/src/components/ui/slider.tsx +56 -0
  175. package/src/components/ui/sonner.tsx +45 -0
  176. package/src/components/ui/switch.tsx +25 -0
  177. package/src/components/ui/table.tsx +114 -0
  178. package/src/components/ui/textarea.tsx +18 -0
  179. package/src/components/ui/toggle-group.tsx +89 -0
  180. package/src/components/ui/toggle.tsx +43 -0
  181. package/src/components/ui/tooltip.tsx +66 -0
  182. package/src/hooks/use-mobile.ts +30 -0
  183. package/src/index.ts +48 -0
  184. package/src/lib/analytics-api.ts +145 -0
  185. package/src/lib/analytics-error.ts +19 -0
  186. package/src/lib/analytics-input.ts +187 -0
  187. package/src/lib/analytics-overview.ts +170 -0
  188. package/src/lib/analytics-rpc.ts +218 -0
  189. package/src/lib/api-keys-api.ts +69 -0
  190. package/src/lib/api-keys-rpc.ts +87 -0
  191. package/src/lib/api-rpc.ts +478 -0
  192. package/src/lib/api.ts +444 -0
  193. package/src/lib/auth-rpc.ts +16 -0
  194. package/src/lib/bundle-signing-api.ts +14 -0
  195. package/src/lib/bundle-signing-rpc.ts +16 -0
  196. package/src/lib/constants.ts +1 -0
  197. package/src/lib/git.ts +51 -0
  198. package/src/lib/server/auth.server.ts +43 -0
  199. package/src/lib/server/bundle-signing.server.ts +100 -0
  200. package/src/lib/server/config.server.ts +109 -0
  201. package/src/lib/server/console-runtime.server.ts +70 -0
  202. package/src/lib/server/deleteBundle.ts +145 -0
  203. package/src/lib/server/downloadBundle.ts +46 -0
  204. package/src/lib/server/getBundleChildren.ts +130 -0
  205. package/src/lib/server/listReleases.ts +61 -0
  206. package/src/lib/server/releaseActivity.ts +27 -0
  207. package/src/lib/server/releaseReachability.ts +95 -0
  208. package/src/lib/server/runtime.server.ts +172 -0
  209. package/src/lib/utils.ts +9 -0
  210. package/src/logo.svg +1 -0
  211. package/src/routeTree.gen.ts +199 -0
  212. package/src/router.tsx +21 -0
  213. package/src/routes/-installations-search.ts +19 -0
  214. package/src/routes/-releases-search.ts +74 -0
  215. package/src/routes/__root.tsx +174 -0
  216. package/src/routes/analytics.tsx +139 -0
  217. package/src/routes/api/auth/$.ts +19 -0
  218. package/src/routes/api/bundles/$bundleId/download.ts +17 -0
  219. package/src/routes/api-keys.tsx +37 -0
  220. package/src/routes/index.tsx +982 -0
  221. package/src/routes/installations.tsx +194 -0
  222. package/src/routes/signing.tsx +37 -0
  223. package/src/styles.css +152 -0
  224. package/src/virtual-modules.d.ts +21 -0
  225. package/src/vite-env.d.ts +1 -0
  226. package/src/vite-internal.ts +195 -0
  227. package/src/vite.ts +12 -0
  228. package/.output/public/assets/dist-DJX53faP.js +0 -3
  229. package/.output/public/assets/index-Iylis5kY.js +0 -10
  230. package/.output/public/assets/routes-HT21hs0C.js +0 -54
  231. package/.output/public/assets/styles-C0Re4quB.css +0 -2
  232. package/.output/server/__23tanstack-start-server-fn-resolver-CgwgZ0-i.mjs +0 -66
  233. package/.output/server/_libs/@floating-ui/core+[...].mjs +0 -698
  234. package/.output/server/_libs/@floating-ui/dom+[...].mjs +0 -644
  235. package/.output/server/_libs/@floating-ui/react-dom+[...].mjs +0 -839
  236. package/.output/server/_libs/@radix-ui/react-alert-dialog+[...].mjs +0 -2138
  237. package/.output/server/_libs/@radix-ui/react-popper+[...].mjs +0 -308
  238. package/.output/server/_libs/@radix-ui/react-select+[...].mjs +0 -1038
  239. package/.output/server/_libs/@tanstack/devtools-event-client+[...].mjs +0 -196
  240. package/.output/server/_libs/@tanstack/form-core+[...].mjs +0 -3228
  241. package/.output/server/_libs/@tanstack/react-form+[...].mjs +0 -430
  242. package/.output/server/_libs/@tanstack/react-table+[...].mjs +0 -2382
  243. package/.output/server/_libs/radix-ui__number.mjs +0 -6
  244. package/.output/server/_libs/radix-ui__primitive.mjs +0 -9
  245. package/.output/server/_libs/radix-ui__react-arrow.mjs +0 -23
  246. package/.output/server/_libs/radix-ui__react-collection.mjs +0 -78
  247. package/.output/server/_libs/radix-ui__react-direction.mjs +0 -13
  248. package/.output/server/_libs/radix-ui__react-label.mjs +0 -22
  249. package/.output/server/_libs/radix-ui__react-separator.mjs +0 -30
  250. package/.output/server/_libs/radix-ui__react-slider.mjs +0 -510
  251. package/.output/server/_libs/radix-ui__react-switch.mjs +0 -157
  252. package/.output/server/_libs/radix-ui__react-tooltip.mjs +0 -493
  253. package/.output/server/_ssr/api-rpc-BIbDUKSz.mjs +0 -292
  254. package/.output/server/_ssr/config.server-BSS366KT.mjs +0 -41
  255. package/.output/server/_ssr/deleteBundle-BgbZTtpW.mjs +0 -141
  256. package/.output/server/_ssr/dist-KboydRVk.mjs +0 -120
  257. package/.output/server/_ssr/router-C3hqEy3k.mjs +0 -307
  258. package/.output/server/_ssr/routes-B0lQvvlC.mjs +0 -3048
  259. package/.output/server/_ssr/start-02sLteYG.mjs +0 -4
  260. package/.output/server/_ssr/storageProfile-FVkjPoGb.mjs +0 -9
  261. package/.output/server/_tanstack-start-manifest_v-Bpx52WOU.mjs +0 -20
  262. package/.output/server/node_modules/tslib/modules/index.js +0 -70
  263. package/.output/server/node_modules/tslib/modules/package.json +0 -3
  264. package/.output/server/node_modules/tslib/package.json +0 -47
  265. package/.output/server/node_modules/tslib/tslib.js +0 -484
  266. package/.output/server/package.json +0 -9
@@ -0,0 +1,478 @@
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,
10
+ type ReleasePolicyPatch,
11
+ updateReleasePolicy,
12
+ } from "@hot-updater/plugin-core";
13
+ import { createServerFn } from "@tanstack/react-start";
14
+
15
+ import {
16
+ parseBundleEventAnalyticsInput,
17
+ parseBundleEventSummaryInput,
18
+ parseInstallationHistoryInput,
19
+ parseSearchInstallationsInput,
20
+ } from "./analytics-input";
21
+ import { DEFAULT_PAGE_LIMIT } from "./constants";
22
+ import { listReleases } from "./server/listReleases";
23
+ import { getReleaseActivity30d } from "./server/releaseActivity";
24
+ import { addReleaseReachability } from "./server/releaseReachability";
25
+
26
+ type GetBundlesInput = {
27
+ platform?: "ios" | "android";
28
+ page?: number;
29
+ limit?: string;
30
+ after?: string;
31
+ before?: string;
32
+ };
33
+
34
+ type GetBundleInput = {
35
+ bundleId: string;
36
+ };
37
+
38
+ type GetBundleChildrenInput = {
39
+ baseBundleId: string;
40
+ };
41
+
42
+ type GetBundleChildCountsInput = {
43
+ bundleIds: string[];
44
+ };
45
+
46
+ type DeleteBundleInput = {
47
+ bundleId: string;
48
+ };
49
+
50
+ type DeleteBundlesInput = {
51
+ bundleIds: string[];
52
+ };
53
+
54
+ type GetReleasesInput = {
55
+ afterReleaseId?: string;
56
+ beforeReleaseId?: string;
57
+ bundleId?: string;
58
+ channelId?: string;
59
+ enabled?: boolean;
60
+ platform?: "ios" | "android";
61
+ limit?: number;
62
+ page?: number;
63
+ targetAppVersion?: string;
64
+ };
65
+
66
+ type ReleaseMutationInput = {
67
+ expectedRevision?: number;
68
+ patch: ReleasePolicyPatch;
69
+ releaseId: string;
70
+ };
71
+
72
+ type DeleteReleaseInput = {
73
+ expectedRevision?: number;
74
+ releaseId: string;
75
+ };
76
+
77
+ export const getReleases = createServerFn({ method: "GET" })
78
+ .inputValidator((input: GetReleasesInput | undefined) => input)
79
+ .handler(async ({ data }) => {
80
+ const { prepareConfig } = await import("./server/config.server");
81
+ const { config, hotUpdater } = await prepareConfig();
82
+ const result = await listReleases(config.database.models.releases, {
83
+ ...(data?.afterReleaseId === undefined
84
+ ? {}
85
+ : { afterReleaseId: data.afterReleaseId }),
86
+ ...(data?.beforeReleaseId === undefined
87
+ ? {}
88
+ : { beforeReleaseId: data.beforeReleaseId }),
89
+ ...(data?.bundleId === undefined ? {} : { bundleId: data.bundleId }),
90
+ ...(data?.channelId === undefined ? {} : { channelId: data.channelId }),
91
+ ...(data?.enabled === undefined ? {} : { enabled: data.enabled }),
92
+ ...(data?.page === undefined ? {} : { page: data.page }),
93
+ ...(data?.platform === undefined ? {} : { platform: data.platform }),
94
+ ...(data?.targetAppVersion === undefined
95
+ ? {}
96
+ : { targetAppVersion: data.targetAppVersion }),
97
+ limit: data?.limit ?? DEFAULT_PAGE_LIMIT,
98
+ });
99
+ const [releases, activityByBundleId] = await Promise.all([
100
+ addReleaseReachability(
101
+ config.database.models.releaseCatalogs,
102
+ result.data,
103
+ ),
104
+ getReleaseActivity30d(hotUpdater, result.data),
105
+ ]);
106
+ return {
107
+ ...result,
108
+ data: releases.map((release) => ({
109
+ ...release,
110
+ activity30d:
111
+ release.bundle_id === null
112
+ ? null
113
+ : (activityByBundleId.get(release.bundle_id) ?? null),
114
+ })),
115
+ };
116
+ });
117
+
118
+ export const getRelease = createServerFn({ method: "GET" })
119
+ .inputValidator((input: { releaseId: string }) => input)
120
+ .handler(async ({ data }) => {
121
+ const { prepareConfig } = await import("./server/config.server");
122
+ const { config } = await prepareConfig();
123
+ return config.database.models.releases.findById(data.releaseId);
124
+ });
125
+
126
+ export const updateRelease = createServerFn({ method: "POST" })
127
+ .inputValidator((input: ReleaseMutationInput) => input)
128
+ .handler(async ({ data }) => {
129
+ const { prepareConfig } = await import("./server/config.server");
130
+ const { config } = await prepareConfig();
131
+ return updateReleasePolicy({ database: config.database, ...data });
132
+ });
133
+
134
+ export const preflightRelease = createServerFn({ method: "POST" })
135
+ .inputValidator((input: ReleaseMutationInput) => input)
136
+ .handler(async ({ data }) => {
137
+ const { prepareConfig } = await import("./server/config.server");
138
+ const { config } = await prepareConfig();
139
+ return preflightReleasePolicy({ database: config.database, ...data });
140
+ });
141
+
142
+ export const deleteRelease = createServerFn({ method: "POST" })
143
+ .inputValidator((input: DeleteReleaseInput) => input)
144
+ .handler(async ({ data }) => {
145
+ const { prepareConfig } = await import("./server/config.server");
146
+ const { config } = await prepareConfig();
147
+ return deleteReleaseMutation({ database: config.database, ...data });
148
+ });
149
+
150
+ export const promoteRelease = createServerFn({ method: "POST" })
151
+ .inputValidator(
152
+ (input: {
153
+ action: "copy" | "move";
154
+ expectedRevision?: number;
155
+ releaseId: string;
156
+ targetChannel: string;
157
+ }) => input,
158
+ )
159
+ .handler(async ({ data }) => {
160
+ const { prepareConfig } = await import("./server/config.server");
161
+ const { config } = await prepareConfig();
162
+ return promoteReleaseMutation({ database: config.database, ...data });
163
+ });
164
+
165
+ export const getReleaseCatalogDiagnostics = createServerFn({ method: "GET" })
166
+ .inputValidator((input: { scopeKey: string }) => input)
167
+ .handler(async ({ data }) => {
168
+ const { prepareConfig } = await import("./server/config.server");
169
+ const { config } = await prepareConfig();
170
+ return config.database.models.releaseCatalogs.findByScopeKey(data.scopeKey);
171
+ });
172
+
173
+ // GET /api/config
174
+ export const getConfig = createServerFn().handler(async () => {
175
+ try {
176
+ const { prepareConfig } = await import("./server/config.server");
177
+ const { config } = await prepareConfig();
178
+ return { console: config.console };
179
+ } catch (error) {
180
+ console.error("Error during config retrieval:", error);
181
+ throw error;
182
+ }
183
+ });
184
+
185
+ // GET /api/channels
186
+ export const getChannels = createServerFn().handler(async () => {
187
+ try {
188
+ const { prepareConfig } = await import("./server/config.server");
189
+ const { databaseClient } = await prepareConfig();
190
+ const channels = await databaseClient.getChannels();
191
+ return channels ?? [];
192
+ } catch (error) {
193
+ console.error("Error during channel retrieval:", error);
194
+ throw error;
195
+ }
196
+ });
197
+
198
+ // POST /api/channels
199
+ export const createChannel = createServerFn({ method: "POST" })
200
+ .inputValidator((input: ChannelInsertInput) => input)
201
+ .handler(async ({ data }) => {
202
+ try {
203
+ const { prepareConfig } = await import("./server/config.server");
204
+ const { databaseClient } = await prepareConfig();
205
+ return { data: await databaseClient.insertChannel(data) };
206
+ } catch (error) {
207
+ console.error("Error during channel creation:", error);
208
+ throw error;
209
+ }
210
+ });
211
+
212
+ // DELETE /api/channels/:id
213
+ export const deleteChannel = createServerFn({ method: "POST" })
214
+ .inputValidator((input: ChannelDeleteInput) => input)
215
+ .handler(async ({ data }) => {
216
+ try {
217
+ const { prepareConfig } = await import("./server/config.server");
218
+ const { databaseClient } = await prepareConfig();
219
+ return { data: await databaseClient.deleteChannel(data) };
220
+ } catch (error) {
221
+ console.error("Error during channel deletion:", error);
222
+ throw error;
223
+ }
224
+ });
225
+
226
+ // GET /api/config-loaded
227
+ export const getConfigLoaded = createServerFn().handler(async () => {
228
+ try {
229
+ const [{ getRequest }, { requireConsoleAccess }] = await Promise.all([
230
+ import("@tanstack/react-start/server"),
231
+ import("./server/auth.server"),
232
+ ]);
233
+ await requireConsoleAccess(getRequest());
234
+ const { isConfigLoaded } = await import("./server/config.server");
235
+ const configLoaded = isConfigLoaded();
236
+ return { configLoaded };
237
+ } catch (error) {
238
+ console.error("Error during config loaded retrieval:", error);
239
+ throw error;
240
+ }
241
+ });
242
+
243
+ // GET /api/bundles
244
+ export const getBundles = createServerFn({ method: "GET" })
245
+ .inputValidator((input: GetBundlesInput | undefined) => input)
246
+ .handler(async ({ data }) => {
247
+ try {
248
+ const { prepareConfig } = await import("./server/config.server");
249
+ const query = {
250
+ platform: data?.platform ?? undefined,
251
+ page:
252
+ typeof data?.page === "number" &&
253
+ Number.isInteger(data.page) &&
254
+ data.page > 1
255
+ ? data.page
256
+ : undefined,
257
+ limit: data?.limit ? Number(data.limit) : DEFAULT_PAGE_LIMIT,
258
+ after: data?.after ?? undefined,
259
+ before: data?.before ?? undefined,
260
+ };
261
+ if (
262
+ (query.after !== undefined && query.before !== undefined) ||
263
+ (query.page !== undefined &&
264
+ (query.after !== undefined || query.before !== undefined))
265
+ ) {
266
+ throw new DatabasePluginInputError("invalid-pagination");
267
+ }
268
+ const pagination =
269
+ query.page !== undefined
270
+ ? { page: query.page }
271
+ : query.after !== undefined
272
+ ? { cursor: { after: query.after } }
273
+ : query.before !== undefined
274
+ ? { cursor: { before: query.before } }
275
+ : {};
276
+
277
+ const { databaseClient } = await prepareConfig();
278
+ const bundleQueryOptions: DatabaseBundleQueryOptions = {
279
+ where: {
280
+ platform: query.platform,
281
+ },
282
+ limit: query.limit,
283
+ ...pagination,
284
+ };
285
+ const bundles = await databaseClient.getBundles(bundleQueryOptions);
286
+
287
+ return (
288
+ bundles ?? {
289
+ data: [],
290
+ pagination: {
291
+ total: 0,
292
+ hasNextPage: false,
293
+ hasPreviousPage: false,
294
+ currentPage: 1,
295
+ totalPages: 0,
296
+ },
297
+ }
298
+ );
299
+ } catch (error) {
300
+ console.error("Error during bundle retrieval:", error);
301
+ throw error;
302
+ }
303
+ });
304
+
305
+ // GET /api/bundles/:bundleId
306
+ export const getBundle = createServerFn({ method: "GET" })
307
+ .inputValidator((input: GetBundleInput) => input)
308
+ .handler(async ({ data }) => {
309
+ try {
310
+ const { prepareConfig } = await import("./server/config.server");
311
+ const { databaseClient } = await prepareConfig();
312
+ const bundle = await databaseClient.getBundleById(data.bundleId);
313
+ return bundle ?? null;
314
+ } catch (error) {
315
+ console.error("Error during bundle retrieval:", error);
316
+ throw error;
317
+ }
318
+ });
319
+
320
+ export const getBundleEventSummary = createServerFn({ method: "GET" })
321
+ .inputValidator(parseBundleEventSummaryInput)
322
+ .handler(async ({ data }) => {
323
+ try {
324
+ const { prepareConfig } = await import("./server/config.server");
325
+ const { getBundleEventSummary: getBundleEventSummaryWithRuntime } =
326
+ await import("./server/runtime.server");
327
+ const { hotUpdater } = await prepareConfig();
328
+
329
+ return await getBundleEventSummaryWithRuntime(hotUpdater, data);
330
+ } catch (error) {
331
+ console.error("Error during bundle event summary retrieval:", error);
332
+ throw error;
333
+ }
334
+ });
335
+
336
+ export const getBundleEventAnalytics = createServerFn({ method: "GET" })
337
+ .inputValidator(parseBundleEventAnalyticsInput)
338
+ .handler(async ({ data }) => {
339
+ try {
340
+ const { prepareConfig } = await import("./server/config.server");
341
+ const { getBundleEventAnalytics: getBundleEventAnalyticsWithRuntime } =
342
+ await import("./server/runtime.server");
343
+ const { hotUpdater } = await prepareConfig();
344
+
345
+ return await getBundleEventAnalyticsWithRuntime(hotUpdater, data);
346
+ } catch (error) {
347
+ console.error("Error during bundle event analytics retrieval:", error);
348
+ throw error;
349
+ }
350
+ });
351
+
352
+ export const searchInstallations = createServerFn({ method: "GET" })
353
+ .inputValidator(parseSearchInstallationsInput)
354
+ .handler(async ({ data }) => {
355
+ try {
356
+ const { prepareConfig } = await import("./server/config.server");
357
+ const { searchInstallations: searchInstallationsWithRuntime } =
358
+ await import("./server/runtime.server");
359
+ const { hotUpdater } = await prepareConfig();
360
+
361
+ return await searchInstallationsWithRuntime(hotUpdater, data);
362
+ } catch (error) {
363
+ console.error("Error during installation search:", error);
364
+ throw error;
365
+ }
366
+ });
367
+
368
+ export const getInstallationHistory = createServerFn({ method: "GET" })
369
+ .inputValidator(parseInstallationHistoryInput)
370
+ .handler(async ({ data }) => {
371
+ try {
372
+ const { prepareConfig } = await import("./server/config.server");
373
+ const { getInstallationHistory: getInstallationHistoryWithRuntime } =
374
+ await import("./server/runtime.server");
375
+ const { hotUpdater } = await prepareConfig();
376
+
377
+ return await getInstallationHistoryWithRuntime(hotUpdater, data);
378
+ } catch (error) {
379
+ console.error("Error during installation history retrieval:", error);
380
+ throw error;
381
+ }
382
+ });
383
+
384
+ export const getBundleChildren = createServerFn({ method: "GET" })
385
+ .inputValidator((input: GetBundleChildrenInput) => input)
386
+ .handler(async ({ data }) => {
387
+ try {
388
+ const { prepareConfig } = await import("./server/config.server");
389
+ const { getBundleChildren: getBundleChildrenWithConfig } =
390
+ await import("./server/getBundleChildren");
391
+ const { databaseClient } = await prepareConfig();
392
+
393
+ return await getBundleChildrenWithConfig(data, {
394
+ databaseClient,
395
+ });
396
+ } catch (error) {
397
+ console.error("Error during bundle children retrieval:", error);
398
+ throw error;
399
+ }
400
+ });
401
+
402
+ export const getBundleChildCounts = createServerFn({ method: "GET" })
403
+ .inputValidator((input: GetBundleChildCountsInput) => input)
404
+ .handler(async ({ data }) => {
405
+ try {
406
+ const { prepareConfig } = await import("./server/config.server");
407
+ const { getBundleChildCounts: getBundleChildCountsWithConfig } =
408
+ await import("./server/getBundleChildren");
409
+ const { databaseClient } = await prepareConfig();
410
+
411
+ return await getBundleChildCountsWithConfig(data.bundleIds, {
412
+ databaseClient,
413
+ });
414
+ } catch (error) {
415
+ console.error("Error during bundle child count retrieval:", error);
416
+ throw error;
417
+ }
418
+ });
419
+
420
+ // POST /api/bundles
421
+ export const createBundle = createServerFn({ method: "POST" })
422
+ .inputValidator((input: Bundle) => input)
423
+ .handler(async ({ data }) => {
424
+ try {
425
+ const { prepareConfig } = await import("./server/config.server");
426
+ const { databaseClient } = await prepareConfig();
427
+ await databaseClient.insertBundle(data);
428
+ return { success: true, bundleId: data.id };
429
+ } catch (error) {
430
+ console.error("Error during bundle creation:", error);
431
+ throw error;
432
+ }
433
+ });
434
+
435
+ // DELETE /api/bundles/:bundleId
436
+ export const deleteBundle = createServerFn({ method: "POST" })
437
+ .inputValidator((input: DeleteBundleInput) => input)
438
+ .handler(async ({ data }) => {
439
+ try {
440
+ const { prepareConfig } = await import("./server/config.server");
441
+ const { deleteBundle: deleteBundleWithStorage } =
442
+ await import("./server/deleteBundle");
443
+ const { databaseClient, storagePlugin } = await prepareConfig();
444
+
445
+ await deleteBundleWithStorage(data, {
446
+ databaseClient,
447
+ storagePlugin,
448
+ waitForStorageCleanup: false,
449
+ });
450
+
451
+ return { success: true };
452
+ } catch (error) {
453
+ console.error("Error during bundle deletion:", error);
454
+ throw error;
455
+ }
456
+ });
457
+
458
+ export const deleteBundles = createServerFn({ method: "POST" })
459
+ .inputValidator((input: DeleteBundlesInput) => input)
460
+ .handler(async ({ data }) => {
461
+ try {
462
+ const { prepareConfig } = await import("./server/config.server");
463
+ const { deleteBundles: deleteBundlesWithStorage } =
464
+ await import("./server/deleteBundle");
465
+ const { databaseClient, storagePlugin } = await prepareConfig();
466
+
467
+ const result = await deleteBundlesWithStorage(data, {
468
+ databaseClient,
469
+ storagePlugin,
470
+ waitForStorageCleanup: false,
471
+ });
472
+
473
+ return { success: true, ...result };
474
+ } catch (error) {
475
+ console.error("Error during bundle deletion:", error);
476
+ throw error;
477
+ }
478
+ });