@hot-updater/console 1.0.0-rc.0 → 1.0.0-rc.2

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 (203) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/HashValueDisplay-CB0Eskit.js +1 -0
  3. package/.output/public/assets/InsightsPageHeader-Car5LNiZ.js +1 -0
  4. package/.output/public/assets/api-keys-BzKocqRy.js +1 -0
  5. package/.output/public/assets/api-keys-api-BHcODB7q.js +1 -0
  6. package/.output/public/assets/card-Dhr_eFYj.js +1 -0
  7. package/.output/public/assets/{chart-no-axes-combined-FaYMGmQS.js → chart-no-axes-combined-Dy4WJv2U.js} +1 -1
  8. package/.output/public/assets/composite-Bp98A0Ld.js +1 -0
  9. package/.output/public/assets/createServerFn-CA8fs7QD.js +3 -0
  10. package/.output/public/assets/dialog-CUTrcPlB.js +1 -0
  11. package/.output/public/assets/{dist-DspNKfMj.js → dist-C_NydL0e.js} +1 -1
  12. package/.output/public/assets/index-DdAz-CXv.js +10 -0
  13. package/.output/public/assets/input-group-cSOG4wh_.js +1 -0
  14. package/.output/public/assets/insights-C0PBSZ-n.js +1 -0
  15. package/.output/public/assets/installations-CE33wgbY.js +2 -0
  16. package/.output/public/assets/installations-CStZja8x.js +1 -0
  17. package/.output/public/assets/lazyRouteComponent-Ccp3bwBY.js +1 -0
  18. package/.output/public/assets/link-CI8idAUi.js +1 -0
  19. package/.output/public/assets/loader-circle-BoxLrsOu.js +1 -0
  20. package/.output/public/assets/refresh-cw-Bqc72UZG.js +1 -0
  21. package/.output/public/assets/{routes-DcQnVajO.js → routes-DGVXdzpw.js} +2 -2
  22. package/.output/public/assets/routes-DTlwOr8I.js +1 -0
  23. package/.output/public/assets/{shield-check-DE_hVuHu.js → shield-check-uK3MHWJZ.js} +1 -1
  24. package/.output/public/assets/signing-CMf4aqDO.js +1 -0
  25. package/.output/public/assets/styles-BCvbtKsm.css +2 -0
  26. package/.output/public/assets/table-2vcV89QB.js +1 -0
  27. package/.output/public/assets/useCompositeListItem-CHLITE_4.js +1 -0
  28. package/.output/public/assets/x-DCd0j8c6.js +1 -0
  29. package/.output/server/{__23tanstack-start-server-fn-resolver-DBP9TQ7K.mjs → __23tanstack-start-server-fn-resolver-B7ioJhtE.mjs} +44 -52
  30. package/.output/server/_libs/@base-ui/react+[...].mjs +1906 -4040
  31. package/.output/server/_libs/@tanstack/react-router+[...].mjs +52 -4
  32. package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +2 -2
  33. package/.output/server/_libs/lucide-react.mjs +36 -3
  34. package/.output/server/_libs/next-themes.mjs +2 -2
  35. package/.output/server/_libs/sonner.mjs +2 -2
  36. package/.output/server/_libs/tanstack__react-query.mjs +2 -2
  37. package/.output/server/_libs/verkit.mjs +20 -15
  38. package/.output/server/_runtime.mjs +1 -10
  39. package/.output/server/_ssr/HashValueDisplay-DwpGLfrl.mjs +55 -0
  40. package/.output/server/_ssr/InsightsPageHeader-Df4Brj8u.mjs +484 -0
  41. package/.output/server/_ssr/{api-keys-BnM_o2nS.mjs → api-keys-CZeTPQys.mjs} +11 -13
  42. package/.output/server/_ssr/{api-keys-api-CIywsSF5.mjs → api-keys-api-BUPQVSpk.mjs} +2 -2
  43. package/.output/server/_ssr/{api-keys-rpc-BSp1wkIV.mjs → api-keys-rpc-Cs7tS5_j.mjs} +5 -5
  44. package/.output/server/_ssr/{api-rpc-cG5wd_tO.mjs → api-rpc-tAupfGQm.mjs} +73 -142
  45. package/.output/server/_ssr/{auth-rpc-BrJ6obHJ.mjs → auth-rpc-DUaeOWKK.mjs} +4 -4
  46. package/.output/server/_ssr/{auth.server-DwKoZoQM.mjs → auth.server-DW71WzsD.mjs} +2 -5
  47. package/.output/server/_ssr/{bundle-signing-rpc-COoQhW8E.mjs → bundle-signing-rpc-BhnBw0-d.mjs} +2 -2
  48. package/.output/server/_ssr/bundle-signing.server-C4NW5mWx.mjs +12 -0
  49. package/.output/server/_ssr/{alert-Dim3MGY5.mjs → card-BRiPmi0C.mjs} +61 -39
  50. package/.output/server/_ssr/{config.server-DEiLhKmy.mjs → config.server-afDuAwaG.mjs} +15 -8
  51. package/.output/server/_ssr/{createSsrRpc-9P0S0lJ3.mjs → createSsrRpc-DjWNJ0uc.mjs} +6 -6
  52. package/.output/server/_ssr/databaseJsonValue-d6I3nAS4.mjs +45 -0
  53. package/.output/server/_ssr/{databaseRows-CwbNwYSl.mjs → databaseRows-5bCRTxm-.mjs} +4 -44
  54. package/.output/server/_ssr/{deleteBundle-Cu_XOMt0.mjs → deleteBundle-BTGwBgzx.mjs} +2 -2
  55. package/.output/server/_ssr/{dialog-CQuRMNZ4.mjs → dialog-DS-nw-pA.mjs} +2 -2
  56. package/.output/server/_ssr/{dist-BVSLTpoP.mjs → dist-CyzPaI5v.mjs} +2 -2
  57. package/.output/server/_ssr/{getBundleChildren-BcRMFoDF.mjs → getBundleChildren-C0vh4ZvE.mjs} +2 -2
  58. package/.output/server/_ssr/input-group-BpsnmvZw.mjs +70 -0
  59. package/.output/server/_ssr/insights-BdS364Xu.mjs +460 -0
  60. package/.output/server/_ssr/insights-rpc-38DujK0G.mjs +57 -0
  61. package/.output/server/_ssr/insightsContract-fjJDBeEE.mjs +303 -0
  62. package/.output/server/_ssr/installations-CtA59MQG.mjs +29 -0
  63. package/.output/server/_ssr/installations-DiVKEF5T.mjs +627 -0
  64. package/.output/server/_ssr/{router-C-KUBfOi.mjs → router-B9wG_9f8.mjs} +37 -46
  65. package/.output/server/_ssr/{routes-Z7TwC6nC.mjs → routes-CKrrS2q2.mjs} +3 -3
  66. package/.output/server/_ssr/{routes-BM4ht9jb.mjs → routes-D7Yh_jfj.mjs} +402 -390
  67. package/.output/server/_ssr/runtime.server-DacU1TBV.mjs +438 -0
  68. package/.output/server/_ssr/{server-BjzmvXnO.mjs → server-D_C2rMzf.mjs} +5 -5
  69. package/.output/server/_ssr/{signing-k8GxyBDF.mjs → signing-Dz1WkZOf.mjs} +16 -85
  70. package/.output/server/_ssr/ssr.mjs +1 -1
  71. package/.output/server/_ssr/{field-DRIXKjZG.mjs → table-CnZmon_Z.mjs} +51 -5
  72. package/.output/server/_ssr/{uuidv7-BbJ-9D_I.mjs → uuidv7-D0QFkPL_.mjs} +3 -3
  73. package/.output/server/_tanstack-start-manifest_v-2MjTyxil.mjs +97 -0
  74. package/.output/server/index.mjs +168 -203
  75. package/lib/index.d.mts +4 -4
  76. package/lib/vite-internal.mjs +1 -1
  77. package/lib/vite.d.mts +0 -1
  78. package/package.json +8 -8
  79. package/src/components/AppSidebar.tsx +12 -16
  80. package/src/components/ConsoleAccessPage.tsx +1 -1
  81. package/src/components/HashValueDisplay.tsx +11 -2
  82. package/src/components/features/api-keys/ApiKeysPage.tsx +1 -1
  83. package/src/components/features/bundles/BundleChildrenPanel.tsx +7 -6
  84. package/src/components/features/bundles/BundleMetadata.tsx +1 -20
  85. package/src/components/features/channels/ChannelManagementDialog.tsx +1 -1
  86. package/src/components/features/insights/EventDetails.tsx +151 -0
  87. package/src/components/features/insights/EventHistoryCard.tsx +245 -0
  88. package/src/components/features/insights/EventHistoryList.tsx +63 -0
  89. package/src/components/features/insights/InsightsBundleReports.tsx +51 -0
  90. package/src/components/features/insights/InsightsControls.tsx +121 -0
  91. package/src/components/features/{analytics/AnalyticsErrorAlert.tsx → insights/InsightsErrorAlert.tsx} +6 -6
  92. package/src/components/features/insights/InsightsOverview.tsx +203 -0
  93. package/src/components/features/insights/InsightsPageHeader.tsx +48 -0
  94. package/src/components/features/insights/InsightsPagination.tsx +52 -0
  95. package/src/components/features/insights/InstallationHistoryCard.tsx +250 -0
  96. package/src/components/features/insights/InstallationMatchesCard.tsx +178 -0
  97. package/src/components/features/insights/InstallationPageHeader.tsx +90 -0
  98. package/src/components/features/releases/ReleaseEditorSheet.tsx +24 -24
  99. package/src/components/features/signing/BundleSigningPage.tsx +18 -126
  100. package/src/components/ui/badge.tsx +2 -0
  101. package/src/components/ui/combobox.tsx +1 -0
  102. package/src/components/ui/skeleton.tsx +4 -1
  103. package/src/components/ui/tooltip.tsx +1 -1
  104. package/src/index.ts +7 -3
  105. package/src/lib/api-rpc.ts +19 -90
  106. package/src/lib/api.ts +0 -99
  107. package/src/lib/insights-api.ts +100 -0
  108. package/src/lib/insights-rpc.ts +88 -0
  109. package/src/lib/insights-view.ts +15 -0
  110. package/src/lib/public-bundle-error.ts +19 -0
  111. package/src/lib/server/bundle-signing.server.ts +5 -82
  112. package/src/lib/server/console-runtime.server.ts +0 -9
  113. package/src/lib/server/releaseReachability.ts +1 -4
  114. package/src/lib/server/runtime.server.ts +6 -142
  115. package/src/routeTree.gen.ts +21 -21
  116. package/src/router.tsx +3 -0
  117. package/src/routes/-installations-search.ts +25 -12
  118. package/src/routes/__root.tsx +6 -16
  119. package/src/routes/api-keys.tsx +1 -1
  120. package/src/routes/index.tsx +21 -81
  121. package/src/routes/insights.tsx +84 -0
  122. package/src/routes/installations.tsx +294 -142
  123. package/src/styles.css +6 -0
  124. package/.output/public/assets/AnalyticsCapabilityContext-BCke57-7.js +0 -1
  125. package/.output/public/assets/BundleActivityChart-CnsBe_1J.js +0 -42
  126. package/.output/public/assets/BundleIdDisplay-Dky75zLU.js +0 -1
  127. package/.output/public/assets/alert-C-1KvDW8.js +0 -1
  128. package/.output/public/assets/analytics-Bqz0c-BT.js +0 -1
  129. package/.output/public/assets/analytics-api-CJdrTLLO.js +0 -1
  130. package/.output/public/assets/api-B_Rh-uzC.js +0 -1
  131. package/.output/public/assets/api-keys-BurCFhzH.js +0 -1
  132. package/.output/public/assets/api-keys-api-BEDJdQg3.js +0 -1
  133. package/.output/public/assets/badge-Bf0fZ-Gx.js +0 -1
  134. package/.output/public/assets/createServerFn-gM2-LFBy.js +0 -3
  135. package/.output/public/assets/dialog-BS60BRr2.js +0 -1
  136. package/.output/public/assets/download-O-yNBc9H.js +0 -1
  137. package/.output/public/assets/field-Buq148-A.js +0 -1
  138. package/.output/public/assets/index-kFhd2S78.js +0 -10
  139. package/.output/public/assets/installations-BrQ-od41.js +0 -2
  140. package/.output/public/assets/installations-CGlZ3ROz.js +0 -1
  141. package/.output/public/assets/lazyRouteComponent-rPzgA7S-.js +0 -1
  142. package/.output/public/assets/loader-circle-DCYF-wJl.js +0 -1
  143. package/.output/public/assets/refresh-cw-n8XYbPPj.js +0 -1
  144. package/.output/public/assets/routes-CrdokJ80.js +0 -1
  145. package/.output/public/assets/search-DLhbWw3W.js +0 -1
  146. package/.output/public/assets/signing-HRexfjsH.js +0 -1
  147. package/.output/public/assets/styles-eB4EtvFS.css +0 -2
  148. package/.output/public/assets/table-D8CLieHX.js +0 -1
  149. package/.output/public/assets/textarea-YJLTVAoq.js +0 -1
  150. package/.output/public/assets/useMutation-JsGVjQMY.js +0 -1
  151. package/.output/public/assets/useOpenInteractionType-4cRD5xO0.js +0 -1
  152. package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +0 -1554
  153. package/.output/server/_libs/d3-array.mjs +0 -231
  154. package/.output/server/_libs/d3-color.mjs +0 -330
  155. package/.output/server/_libs/d3-format.mjs +0 -252
  156. package/.output/server/_libs/d3-interpolate.mjs +0 -207
  157. package/.output/server/_libs/d3-path.mjs +0 -77
  158. package/.output/server/_libs/d3-scale+[...].mjs +0 -1907
  159. package/.output/server/_libs/d3-shape.mjs +0 -818
  160. package/.output/server/_libs/decimal.js-light.mjs +0 -884
  161. package/.output/server/_libs/es-toolkit.mjs +0 -1134
  162. package/.output/server/_libs/eventemitter3.mjs +0 -236
  163. package/.output/server/_libs/immer.mjs +0 -532
  164. package/.output/server/_libs/react-redux+[...].mjs +0 -205
  165. package/.output/server/_libs/recharts+[...].mjs +0 -14117
  166. package/.output/server/_ssr/AnalyticsCapabilityContext-ui4DX8GO.mjs +0 -15
  167. package/.output/server/_ssr/BundleActivityChart-BiB9ZORH.mjs +0 -288
  168. package/.output/server/_ssr/BundleIdDisplay-Czk6iR6p.mjs +0 -13
  169. package/.output/server/_ssr/analytics-DtMTn8fn.mjs +0 -858
  170. package/.output/server/_ssr/analytics-api-Cg1M5v_H.mjs +0 -71
  171. package/.output/server/_ssr/analytics-input-fRRRn0uA.mjs +0 -96
  172. package/.output/server/_ssr/analytics-rpc-DY5uXvHT.mjs +0 -155
  173. package/.output/server/_ssr/api-BTSv1tZb.mjs +0 -282
  174. package/.output/server/_ssr/badge-DCxbEeof.mjs +0 -26
  175. package/.output/server/_ssr/bundle-signing.server-D5u8KkMp.mjs +0 -51
  176. package/.output/server/_ssr/installations-B-azgAvX.mjs +0 -19
  177. package/.output/server/_ssr/installations-Ctvzp2JH.mjs +0 -535
  178. package/.output/server/_ssr/runtime.server-awTLiiXW.mjs +0 -527
  179. package/.output/server/_ssr/table-v1yCvYo7.mjs +0 -53
  180. package/.output/server/_ssr/textarea-DYHnskhb.mjs +0 -14
  181. package/.output/server/_tanstack-start-manifest_v-CH4StzJu.mjs +0 -108
  182. package/src/components/features/analytics/ActivityChart.tsx +0 -150
  183. package/src/components/features/analytics/AnalyticsCapabilityContext.tsx +0 -24
  184. package/src/components/features/analytics/AnalyticsControls.tsx +0 -115
  185. package/src/components/features/analytics/AnalyticsOverview.tsx +0 -208
  186. package/src/components/features/analytics/BundleDistribution.tsx +0 -133
  187. package/src/components/features/analytics/BundleSelector.tsx +0 -114
  188. package/src/components/features/analytics/InstallationHistoryCard.tsx +0 -248
  189. package/src/components/features/analytics/InstallationMatchesCard.tsx +0 -132
  190. package/src/components/features/analytics/InstallationPageHeader.tsx +0 -138
  191. package/src/components/features/analytics/InstallationPagination.tsx +0 -48
  192. package/src/components/features/analytics/InstallationSearch.tsx +0 -230
  193. package/src/components/features/analytics/UpdateOutcomes.tsx +0 -147
  194. package/src/components/features/bundles/BundleActivityChart.tsx +0 -193
  195. package/src/components/features/bundles/BundleAnalyticsSummary.tsx +0 -123
  196. package/src/lib/analytics-api.ts +0 -145
  197. package/src/lib/analytics-error.ts +0 -19
  198. package/src/lib/analytics-input.ts +0 -187
  199. package/src/lib/analytics-overview.ts +0 -170
  200. package/src/lib/analytics-rpc.ts +0 -218
  201. package/src/lib/server/releaseActivity.ts +0 -27
  202. package/src/routes/analytics.tsx +0 -139
  203. /package/.output/public/assets/{preload-helper-TKOBYGYD.js → preload-helper-CQ36nxok.js} +0 -0
@@ -1,527 +0,0 @@
1
- import { a as parseSearchInstallationsInput, i as parseInstallationHistoryInput, n as parseBundleEventAnalyticsInput, r as parseBundleEventSummaryInput, t as parseActiveInstallationInput } from "./analytics-input-fRRRn0uA.mjs";
2
- import { t as createUUIDv7 } from "./uuidv7-BbJ-9D_I.mjs";
3
- //#region node_modules/.nitro/vite/services/ssr/assets/runtime.server-awTLiiXW.js
4
- var AnalyticsScanLimitExceededError = class extends Error {
5
- constructor(limit) {
6
- super(`Analytics event scan exceeded ${limit} rows.`);
7
- this.limit = limit;
8
- this.name = "AnalyticsScanLimitExceededError";
9
- }
10
- };
11
- var HOUR_MS = 3600 * 1e3;
12
- var DAY_MS = 24 * HOUR_MS;
13
- var ACTIVE_BUNDLE_EVENT_TYPES = [
14
- "UPDATE_APPLIED",
15
- "RECOVERED",
16
- "RELEASE_ADOPTED",
17
- "UNCHANGED"
18
- ];
19
- var activeWindowDefinitions = {
20
- "24h": {
21
- bucketCount: 24,
22
- bucketSizeMs: HOUR_MS
23
- },
24
- "7d": {
25
- bucketCount: 7,
26
- bucketSizeMs: DAY_MS
27
- },
28
- "30d": {
29
- bucketCount: 30,
30
- bucketSizeMs: DAY_MS
31
- }
32
- };
33
- function getActiveWindowDefinition(window) {
34
- return activeWindowDefinitions[window];
35
- }
36
- function compareCodePoints$1(left, right) {
37
- if (left < right) return -1;
38
- if (left > right) return 1;
39
- return 0;
40
- }
41
- function isNewer(candidate, current) {
42
- return candidate.received_at_ms > current.received_at_ms || candidate.received_at_ms === current.received_at_ms && compareCodePoints$1(candidate.id, current.id) > 0;
43
- }
44
- function collectActiveInstallationOverview(request) {
45
- const definition = getActiveWindowDefinition(request.window);
46
- const windowStartMs = request.asOfMs - definition.bucketCount * definition.bucketSizeMs;
47
- const rows = request.rows.filter((row) => row.received_at_ms >= windowStartMs && row.received_at_ms < request.asOfMs);
48
- const latestByInstall = /* @__PURE__ */ new Map();
49
- for (const row of rows) {
50
- const current = latestByInstall.get(row.install_id);
51
- if (current === void 0 || isNewer(row, current)) latestByInstall.set(row.install_id, row);
52
- }
53
- const selectedRows = [...latestByInstall.values()].filter((row) => request.userId === void 0 || row.user_id === request.userId);
54
- const selectedInstallIds = new Set(selectedRows.map((row) => row.install_id));
55
- const bundleCounts = /* @__PURE__ */ new Map();
56
- for (const row of selectedRows) bundleCounts.set(row.to_bundle_id, (bundleCounts.get(row.to_bundle_id) ?? 0) + 1);
57
- const latestByBucket = Array.from({ length: definition.bucketCount }, () => /* @__PURE__ */ new Map());
58
- for (const row of rows) {
59
- if (!selectedInstallIds.has(row.install_id)) continue;
60
- const bucket = latestByBucket[Math.floor((row.received_at_ms - windowStartMs) / definition.bucketSizeMs)];
61
- if (bucket === void 0) continue;
62
- const current = bucket.get(row.install_id);
63
- if (current === void 0 || isNewer(row, current)) bucket.set(row.install_id, row);
64
- }
65
- const bundleCountsByBucket = latestByBucket.map((bucket) => {
66
- const counts = /* @__PURE__ */ new Map();
67
- for (const row of bucket.values()) counts.set(row.to_bundle_id, (counts.get(row.to_bundle_id) ?? 0) + 1);
68
- return counts;
69
- });
70
- const bundleObservationTotals = /* @__PURE__ */ new Map();
71
- for (const counts of bundleCountsByBucket) for (const [bundleId, count] of counts) bundleObservationTotals.set(bundleId, (bundleObservationTotals.get(bundleId) ?? 0) + count);
72
- return {
73
- asOfMs: request.asOfMs,
74
- window: request.window,
75
- activeInstallations: selectedInstallIds.size,
76
- series: latestByBucket.map((bucket, index) => ({
77
- bucketStartMs: windowStartMs + index * definition.bucketSizeMs,
78
- value: bucket.size
79
- })),
80
- bundleSeries: [...bundleObservationTotals].sort(([leftId, leftTotal], [rightId, rightTotal]) => rightTotal - leftTotal || compareCodePoints$1(leftId, rightId)).map(([bundleId]) => ({
81
- bundleId,
82
- series: bundleCountsByBucket.map((counts, index) => ({
83
- bucketStartMs: windowStartMs + index * definition.bucketSizeMs,
84
- value: counts.get(bundleId) ?? 0
85
- }))
86
- })),
87
- bundles: [...bundleCounts].map(([bundleId, installations]) => ({
88
- bundleId,
89
- installations
90
- })).sort((left, right) => right.installations - left.installations || compareCodePoints$1(left.bundleId, right.bundleId))
91
- };
92
- }
93
- var ANALYTICS_SCAN_MAX_ROWS = 5e4;
94
- var ANALYTICS_MATERIALIZATION_LIMIT = ANALYTICS_SCAN_MAX_ROWS + 1;
95
- var ANALYTICS_SCAN_PAGE_SIZE = 1e3;
96
- var ANALYTICS_LOWER_BOUND_ID = "00000000-0000-0000-0000-000000000000";
97
- var compareCodePoints = (left, right) => {
98
- if (left < right) return -1;
99
- if (left > right) return 1;
100
- return 0;
101
- };
102
- var compareEventNewest = (left, right) => right.received_at_ms - left.received_at_ms || compareCodePoints(right.id, left.id);
103
- var compareEventOldest = (left, right) => left.received_at_ms - right.received_at_ms || compareCodePoints(left.id, right.id);
104
- var materializeEventRows = async (scope) => {
105
- const rows = [];
106
- const seenIds = /* @__PURE__ */ new Set();
107
- let after = scope.lowerBoundMs === void 0 ? void 0 : {
108
- receivedAtMs: scope.lowerBoundMs,
109
- id: ANALYTICS_LOWER_BOUND_ID
110
- };
111
- while (rows.length < ANALYTICS_MATERIALIZATION_LIMIT) {
112
- const limit = Math.min(ANALYTICS_SCAN_PAGE_SIZE, ANALYTICS_MATERIALIZATION_LIMIT - rows.length);
113
- const page = await scope.persistence.scan({
114
- beforeReceivedAtMs: scope.cutoffMs,
115
- ...after === void 0 ? {} : { after },
116
- limit
117
- });
118
- if (page.length === 0) break;
119
- if (page.length > limit) throw new AnalyticsPersistenceOrderError();
120
- let previous = after === void 0 ? void 0 : {
121
- received_at_ms: after.receivedAtMs,
122
- id: after.id
123
- };
124
- for (const row of page) {
125
- if (row.received_at_ms >= scope.cutoffMs || previous !== void 0 && compareEventOldest(previous, row) >= 0 || seenIds.has(row.id)) throw new AnalyticsPersistenceOrderError();
126
- seenIds.add(row.id);
127
- rows.push(row);
128
- previous = row;
129
- }
130
- const last = page.at(-1);
131
- if (last !== void 0) after = {
132
- receivedAtMs: last.received_at_ms,
133
- id: last.id
134
- };
135
- if (rows.length > 5e4) throw new AnalyticsScanLimitExceededError(ANALYTICS_SCAN_MAX_ROWS);
136
- }
137
- return rows;
138
- };
139
- var AnalyticsPersistenceOrderError = class extends Error {
140
- name = "AnalyticsPersistenceOrderError";
141
- constructor() {
142
- super("Analytics persistence did not advance its scan cursor.");
143
- }
144
- };
145
- var materializeActiveRows = async (scope, window) => {
146
- const definition = getActiveWindowDefinition(window);
147
- const durationMs = definition.bucketCount * definition.bucketSizeMs;
148
- return (await materializeEventRows({
149
- ...scope,
150
- lowerBoundMs: scope.cutoffMs - durationMs
151
- })).filter((row) => row.received_at_ms >= scope.cutoffMs - durationMs && ACTIVE_BUNDLE_EVENT_TYPES.includes(row.type));
152
- };
153
- var startOfUtcHour = (value) => {
154
- const date = new Date(value);
155
- return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours());
156
- };
157
- var startOfUtcDay = (value) => {
158
- const date = new Date(value);
159
- return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
160
- };
161
- var getWindowRange = (window, now) => {
162
- if (window === "24h") return {
163
- sizeMs: 3600 * 1e3,
164
- rangeStart: startOfUtcHour(now) - 1380 * 60 * 1e3
165
- };
166
- const days = window === "7d" ? 7 : 30;
167
- return {
168
- sizeMs: 1440 * 60 * 1e3,
169
- rangeStart: startOfUtcDay(now) - (days - 1) * 24 * 60 * 60 * 1e3
170
- };
171
- };
172
- var materializeRowsForWindow = async (scope, window) => {
173
- if (window === "all") return materializeEventRows(scope);
174
- const range = getWindowRange(window, scope.cutoffMs);
175
- return (await materializeEventRows({
176
- ...scope,
177
- lowerBoundMs: range.rangeStart
178
- })).filter(({ received_at_ms }) => received_at_ms >= range.rangeStart);
179
- };
180
- var bucketStart = (receivedAtMs, sizeMs) => sizeMs === 3600 * 1e3 ? startOfUtcHour(receivedAtMs) : startOfUtcDay(receivedAtMs);
181
- var createSeries = (request) => {
182
- const range = request.window === "all" ? void 0 : getWindowRange(request.window, request.cutoffMs);
183
- const sizeMs = range?.sizeMs ?? 1440 * 60 * 1e3;
184
- const installIdsByBucket = /* @__PURE__ */ new Map();
185
- let oldestMs = request.cutoffMs;
186
- for (const row of request.rows) {
187
- oldestMs = Math.min(oldestMs, row.received_at_ms);
188
- const start = bucketStart(row.received_at_ms, sizeMs);
189
- const installIds = installIdsByBucket.get(start) ?? /* @__PURE__ */ new Set();
190
- installIds.add(row.install_id);
191
- installIdsByBucket.set(start, installIds);
192
- }
193
- const first = range?.rangeStart ?? startOfUtcDay(oldestMs);
194
- const last = bucketStart(request.cutoffMs, sizeMs);
195
- return Array.from({ length: Math.floor((last - first) / sizeMs) + 1 }, (_, index) => {
196
- const start = first + index * sizeMs;
197
- return {
198
- bucketStartMs: start,
199
- value: installIdsByBucket.get(start)?.size ?? 0
200
- };
201
- });
202
- };
203
- var collectEventActivity = (request) => {
204
- const range = request.window === "all" ? void 0 : getWindowRange(request.window, request.cutoffMs);
205
- const rows = range === void 0 ? request.rows : request.rows.filter(({ received_at_ms }) => received_at_ms >= range.rangeStart && received_at_ms < request.cutoffMs);
206
- const installs = /* @__PURE__ */ new Set();
207
- const installsByCohort = /* @__PURE__ */ new Map();
208
- for (const row of rows) {
209
- installs.add(row.install_id);
210
- const cohort = installsByCohort.get(row.cohort) ?? /* @__PURE__ */ new Set();
211
- cohort.add(row.install_id);
212
- installsByCohort.set(row.cohort, cohort);
213
- }
214
- return {
215
- summary: installs.size,
216
- cohorts: [...installsByCohort].sort(([left], [right]) => compareCodePoints(left, right)).map(([cohort, installIds]) => ({
217
- cohort,
218
- value: installIds.size
219
- })),
220
- series: createSeries({
221
- ...request,
222
- rows
223
- })
224
- };
225
- };
226
- function toSearchRow(row) {
227
- return {
228
- installId: row.install_id,
229
- username: row.username,
230
- userId: row.user_id,
231
- lastKnownBundleId: row.to_bundle_id,
232
- latestStatus: row.type,
233
- platform: row.platform,
234
- appVersion: row.app_version,
235
- channel: row.channel,
236
- cohort: row.cohort,
237
- receivedAtMs: row.received_at_ms
238
- };
239
- }
240
- function matchesIdentity(row, query) {
241
- return row.install_id.toLowerCase().includes(query) || row.user_id?.toLowerCase().includes(query) === true || row.username?.toLowerCase().includes(query) === true;
242
- }
243
- function searchEventInstallations(request) {
244
- const query = request.query.toLowerCase();
245
- const matchingInstallIds = /* @__PURE__ */ new Set();
246
- for (const row of request.rows) if (query.length === 0 || matchesIdentity(row, query)) matchingInstallIds.add(row.install_id);
247
- const latestByInstall = /* @__PURE__ */ new Map();
248
- for (const row of request.rows) {
249
- if (!matchingInstallIds.has(row.install_id)) continue;
250
- const current = latestByInstall.get(row.install_id);
251
- if (current === void 0 || compareEventNewest(row, current) < 0) latestByInstall.set(row.install_id, row);
252
- }
253
- const matchingRows = [...latestByInstall.values()].sort((left, right) => compareCodePoints(left.install_id, right.install_id));
254
- const pageSize = Math.min(Math.max(request.limit, 0), 100);
255
- return {
256
- data: matchingRows.slice(request.offset, request.offset + pageSize).map(toSearchRow),
257
- pagination: {
258
- total: matchingRows.length,
259
- limit: request.limit,
260
- offset: request.offset
261
- }
262
- };
263
- }
264
- function createBundleEventRow(input) {
265
- const base = {
266
- id: createUUIDv7(),
267
- install_id: input.installId,
268
- user_id: input.userId ?? null,
269
- username: input.username ?? null,
270
- from_release_id: input.fromReleaseId,
271
- to_release_id: input.toReleaseId,
272
- to_bundle_id: input.toBundleId,
273
- platform: input.platform,
274
- app_version: input.appVersion,
275
- channel: input.channel,
276
- cohort: input.cohort,
277
- fingerprint_hash: input.fingerprintHash,
278
- sdk_version: input.sdkVersion ?? null,
279
- received_at_ms: Date.now()
280
- };
281
- switch (input.type) {
282
- case "UPDATE_APPLIED":
283
- case "RECOVERED":
284
- case "RELEASE_ADOPTED": return {
285
- ...base,
286
- type: input.type,
287
- from_bundle_id: input.fromBundleId,
288
- update_strategy: input.updateStrategy
289
- };
290
- case "UNCHANGED": return {
291
- ...base,
292
- type: input.type,
293
- from_bundle_id: null,
294
- update_strategy: null
295
- };
296
- }
297
- }
298
- var isTransitionEventRow = (row) => row.type === "UPDATE_APPLIED" || row.type === "RECOVERED";
299
- var toHistoryRow = (row) => ({
300
- id: row.id,
301
- type: row.type,
302
- fromBundleId: row.from_bundle_id,
303
- toBundleId: row.to_bundle_id,
304
- username: row.username,
305
- userId: row.user_id,
306
- platform: row.platform,
307
- appVersion: row.app_version,
308
- channel: row.channel,
309
- cohort: row.cohort,
310
- receivedAtMs: row.received_at_ms
311
- });
312
- var isInstalledForBundle = (row, bundleId) => row.type === "UPDATE_APPLIED" && row.to_bundle_id === bundleId;
313
- var isRecoveredFromBundle = (row, bundleId) => row.type === "RECOVERED" && row.from_bundle_id === bundleId;
314
- var countDistinctInstallations = (rows) => new Set(rows.map(({ install_id }) => install_id)).size;
315
- var getAnalyticsResult = async (persistence, bundleId, window, limit, offset) => {
316
- const scope = {
317
- persistence,
318
- cutoffMs: Date.now()
319
- };
320
- const rows = (await materializeRowsForWindow(scope, window)).filter(isTransitionEventRow);
321
- const installedRows = rows.filter((row) => isInstalledForBundle(row, bundleId));
322
- const recoveredRows = rows.filter((row) => isRecoveredFromBundle(row, bundleId));
323
- const installed = collectEventActivity({
324
- rows: installedRows,
325
- window,
326
- cutoffMs: scope.cutoffMs
327
- });
328
- const recovered = collectEventActivity({
329
- rows: recoveredRows,
330
- window,
331
- cutoffMs: scope.cutoffMs
332
- });
333
- const recentRows = [...installedRows, ...recoveredRows].sort(compareEventNewest);
334
- return {
335
- summary: {
336
- installed: installed.summary,
337
- recovered: recovered.summary
338
- },
339
- series: {
340
- installed: installed.series,
341
- recovered: recovered.series
342
- },
343
- cohorts: {
344
- installed: installed.cohorts,
345
- recovered: recovered.cohorts
346
- },
347
- recentEvents: {
348
- data: recentRows.slice(offset, offset + limit).map(toHistoryRow),
349
- pagination: {
350
- total: recentRows.length,
351
- limit,
352
- offset
353
- }
354
- }
355
- };
356
- };
357
- var getAnalyticsSummaries = async (persistence, bundleIds, window) => {
358
- const normalizedBundleIds = [...new Set(bundleIds)];
359
- if (normalizedBundleIds.length === 0) return [];
360
- const requestedBundleIds = new Set(normalizedBundleIds);
361
- const installedByBundleId = /* @__PURE__ */ new Map();
362
- const recoveredByBundleId = /* @__PURE__ */ new Map();
363
- const rows = (await materializeRowsForWindow({
364
- persistence,
365
- cutoffMs: Date.now()
366
- }, window)).filter(isTransitionEventRow);
367
- for (const row of rows) {
368
- const bundleId = row.type === "UPDATE_APPLIED" ? row.to_bundle_id : row.from_bundle_id;
369
- if (!requestedBundleIds.has(bundleId)) continue;
370
- const counts = row.type === "UPDATE_APPLIED" ? installedByBundleId : recoveredByBundleId;
371
- const installIds = counts.get(bundleId) ?? /* @__PURE__ */ new Set();
372
- installIds.add(row.install_id);
373
- counts.set(bundleId, installIds);
374
- }
375
- return normalizedBundleIds.map((bundleId) => ({
376
- bundleId,
377
- installed: installedByBundleId.get(bundleId)?.size ?? 0,
378
- recovered: recoveredByBundleId.get(bundleId)?.size ?? 0
379
- }));
380
- };
381
- var createAnalyticsProvider = (persistence) => Object.freeze({
382
- mode: "bounded",
383
- maxMatchingRows: ANALYTICS_SCAN_MAX_ROWS,
384
- async appendBundleEvent(input) {
385
- await persistence.append(createBundleEventRow(input));
386
- },
387
- async getBundleEventSummary(bundleId) {
388
- const rows = (await materializeEventRows({
389
- persistence,
390
- cutoffMs: Date.now()
391
- })).filter(isTransitionEventRow);
392
- return {
393
- installed: countDistinctInstallations(rows.filter((row) => isInstalledForBundle(row, bundleId))),
394
- recovered: countDistinctInstallations(rows.filter((row) => isRecoveredFromBundle(row, bundleId)))
395
- };
396
- },
397
- getBundleEventSummaries(bundleIds, window) {
398
- return getAnalyticsSummaries(persistence, bundleIds, window);
399
- },
400
- getBundleEventAnalytics(bundleId, window, limit, offset) {
401
- return getAnalyticsResult(persistence, bundleId, window, limit, offset);
402
- },
403
- async getBundleEventOverview() {
404
- const rows = await materializeEventRows({
405
- persistence,
406
- cutoffMs: Date.now()
407
- });
408
- const latestByInstall = /* @__PURE__ */ new Map();
409
- for (const row of rows) {
410
- const current = latestByInstall.get(row.install_id);
411
- if (current === void 0 || compareEventNewest(row, current) < 0) latestByInstall.set(row.install_id, row);
412
- }
413
- const counts = /* @__PURE__ */ new Map();
414
- for (const row of latestByInstall.values()) counts.set(row.to_bundle_id, (counts.get(row.to_bundle_id) ?? 0) + 1);
415
- return {
416
- trackedInstallations: latestByInstall.size,
417
- bundles: [...counts].map(([bundleId, installations]) => ({
418
- bundleId,
419
- installations
420
- })).sort((left, right) => right.installations - left.installations || compareCodePoints(left.bundleId, right.bundleId))
421
- };
422
- },
423
- async getActiveInstallationOverview(input) {
424
- const asOfMs = Date.now();
425
- return collectActiveInstallationOverview({
426
- rows: await materializeActiveRows({
427
- persistence,
428
- cutoffMs: asOfMs
429
- }, input.window),
430
- asOfMs,
431
- window: input.window,
432
- ...input.userId === void 0 ? {} : { userId: input.userId }
433
- });
434
- },
435
- async searchInstallations(query, limit, offset) {
436
- return searchEventInstallations({
437
- rows: await materializeEventRows({
438
- persistence,
439
- cutoffMs: Date.now()
440
- }),
441
- query,
442
- limit,
443
- offset
444
- });
445
- },
446
- async getInstallationHistory(installId, limit, offset) {
447
- const ordered = (await materializeEventRows({
448
- persistence,
449
- cutoffMs: Date.now()
450
- })).filter((row) => row.install_id === installId && isTransitionEventRow(row)).toSorted(compareEventNewest);
451
- return {
452
- data: ordered.slice(offset, offset + limit).map(toHistoryRow),
453
- pagination: {
454
- total: ordered.length,
455
- limit,
456
- offset
457
- }
458
- };
459
- }
460
- });
461
- function createRuntimeHotUpdater(config) {
462
- const models = Reflect.get(config.database, "models");
463
- const analytics = typeof models === "object" && models !== null ? Reflect.get(models, "analytics") : void 0;
464
- if (typeof analytics !== "object" || analytics === null || typeof Reflect.get(analytics, "append") !== "function" || typeof Reflect.get(analytics, "scan") !== "function") return null;
465
- return createAnalyticsProvider(analytics);
466
- }
467
- function createApiKeyStore(config) {
468
- const models = Reflect.get(config.database, "models");
469
- const apiKeys = typeof models === "object" && models !== null ? Reflect.get(models, "apiKeys") : void 0;
470
- if (typeof apiKeys !== "object" || apiKeys === null || typeof Reflect.get(apiKeys, "create") !== "function" || typeof Reflect.get(apiKeys, "findByHash") !== "function" || typeof Reflect.get(apiKeys, "list") !== "function" || typeof Reflect.get(apiKeys, "revoke") !== "function") return null;
471
- return apiKeys;
472
- }
473
- var providerMethods = [
474
- "appendBundleEvent",
475
- "getBundleEventSummary",
476
- "getBundleEventSummaries",
477
- "getBundleEventAnalytics",
478
- "getBundleEventOverview",
479
- "getActiveInstallationOverview",
480
- "searchInstallations",
481
- "getInstallationHistory"
482
- ];
483
- var parseAnalyticsProvider = (value) => {
484
- if (typeof value !== "object" || value === null || Reflect.get(value, "mode") !== "bounded" || typeof Reflect.get(value, "maxMatchingRows") !== "number" || !providerMethods.every((method) => typeof Reflect.get(value, method) === "function")) return null;
485
- return value;
486
- };
487
- var getAnalyticsCapability = async (provider) => {
488
- const parsed = parseAnalyticsProvider(provider);
489
- return parsed === null ? {
490
- analytics: false,
491
- analyticsQueries: false,
492
- eventIngestion: false
493
- } : {
494
- analytics: true,
495
- analyticsQueries: true,
496
- eventIngestion: true,
497
- maxMatchingRows: parsed.maxMatchingRows,
498
- mode: "bounded"
499
- };
500
- };
501
- var requireAnalyticsSupport = async (provider) => {
502
- const parsedProvider = parseAnalyticsProvider(provider);
503
- if (parsedProvider === null) throw new Error("Analytics are not supported by the configured database plugin.");
504
- return parsedProvider;
505
- };
506
- async function getBundleEventSummary(provider, input) {
507
- const { bundleId } = parseBundleEventSummaryInput(input);
508
- return (await requireAnalyticsSupport(provider)).getBundleEventSummary(bundleId);
509
- }
510
- async function getActiveInstallationOverview(provider, input) {
511
- const parsed = parseActiveInstallationInput(input);
512
- return (await requireAnalyticsSupport(provider)).getActiveInstallationOverview(parsed);
513
- }
514
- async function getBundleEventAnalytics(provider, input) {
515
- const parsed = parseBundleEventAnalyticsInput(input);
516
- return (await requireAnalyticsSupport(provider)).getBundleEventAnalytics(parsed.bundleId, parsed.window, parsed.limit ?? 50, parsed.offset ?? 0);
517
- }
518
- async function searchInstallations(provider, input) {
519
- const parsed = parseSearchInstallationsInput(input);
520
- return (await requireAnalyticsSupport(provider)).searchInstallations(parsed.query, parsed.limit ?? 50, parsed.offset ?? 0);
521
- }
522
- async function getInstallationHistory(provider, input) {
523
- const parsed = parseInstallationHistoryInput(input);
524
- return (await requireAnalyticsSupport(provider)).getInstallationHistory(parsed.installId, parsed.limit ?? 50, parsed.offset ?? 0);
525
- }
526
- //#endregion
527
- export { createApiKeyStore, createRuntimeHotUpdater, getActiveInstallationOverview, getAnalyticsCapability, getBundleEventAnalytics, getBundleEventSummary, getInstallationHistory, searchInstallations };
@@ -1,53 +0,0 @@
1
- import "../_runtime.mjs";
2
- import { at as require_react, it as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
3
- import { C as cn } from "./createSsrRpc-9P0S0lJ3.mjs";
4
- require_react();
5
- var import_jsx_runtime = require_jsx_runtime();
6
- function Table({ className, ...props }) {
7
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
8
- "data-slot": "table-container",
9
- className: "relative w-full overflow-x-auto",
10
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", {
11
- "data-slot": "table",
12
- className: cn("w-full caption-bottom text-xs", className),
13
- ...props
14
- })
15
- });
16
- }
17
- function TableHeader({ className, ...props }) {
18
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", {
19
- "data-slot": "table-header",
20
- className: cn("[&_tr]:border-b", className),
21
- ...props
22
- });
23
- }
24
- function TableBody({ className, ...props }) {
25
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", {
26
- "data-slot": "table-body",
27
- className: cn("[&_tr:last-child]:border-0", className),
28
- ...props
29
- });
30
- }
31
- function TableRow({ className, ...props }) {
32
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tr", {
33
- "data-slot": "table-row",
34
- className: cn("hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors", className),
35
- ...props
36
- });
37
- }
38
- function TableHead({ className, ...props }) {
39
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
40
- "data-slot": "table-head",
41
- className: cn("text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0", className),
42
- ...props
43
- });
44
- }
45
- function TableCell({ className, ...props }) {
46
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
47
- "data-slot": "table-cell",
48
- className: cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0", className),
49
- ...props
50
- });
51
- }
52
- //#endregion
53
- export { TableHeader as a, TableHead as i, TableBody as n, TableRow as o, TableCell as r, Table as t };
@@ -1,14 +0,0 @@
1
- import "../_runtime.mjs";
2
- import { at as require_react, it as require_jsx_runtime } from "../_libs/@base-ui/react+[...].mjs";
3
- import { C as cn } from "./createSsrRpc-9P0S0lJ3.mjs";
4
- require_react();
5
- var import_jsx_runtime = require_jsx_runtime();
6
- function Textarea({ className, ...props }) {
7
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("textarea", {
8
- "data-slot": "textarea",
9
- className: cn("flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50", className),
10
- ...props
11
- });
12
- }
13
- //#endregion
14
- export { Textarea as t };